From 4c6b83d75b7666507e557b44bce3f081b16c7dd8 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Tue, 26 Nov 2024 11:04:09 +0100 Subject: [PATCH 01/54] Enable static linking with libc++ * Add a version script which hides all the symbols except for the handful we have to export. * Enable exceptions --- src/native/CMakeLists.txt | 9 ++------- src/native/CMakePresets.json.in | 4 ++-- src/native/libmono-android.map.txt | 15 +++++++++++++++ src/native/monodroid/CMakeLists.txt | 6 ++++++ 4 files changed, 25 insertions(+), 9 deletions(-) create mode 100644 src/native/libmono-android.map.txt diff --git a/src/native/CMakeLists.txt b/src/native/CMakeLists.txt index 6abbe4f5a03..f5be63f38d6 100644 --- a/src/native/CMakeLists.txt +++ b/src/native/CMakeLists.txt @@ -120,13 +120,8 @@ else() set(USES_LIBSTDCPP True) endif() -if(ANALYZERS_ENABLED) - message(STATUS "Analyzers enabled") - set(SHARED_LIB_NAME xa::shared-no-abi) -else() - message(STATUS "NO analyzers enabled") - set(SHARED_LIB_NAME xa::shared) -endif() +set(SHARED_LIB_NAME xa::shared-no-abi) + # # Needed modules # diff --git a/src/native/CMakePresets.json.in b/src/native/CMakePresets.json.in index e7b90193064..33c910f6845 100644 --- a/src/native/CMakePresets.json.in +++ b/src/native/CMakePresets.json.in @@ -48,8 +48,8 @@ "hidden": true, "inherits": "common", "cacheVariables": { - "ANDROID_STL": "none", - "ANDROID_CPP_FEATURES": "no-rtti no-exceptions" + "ANDROID_STL": "c++_static", + "ANDROID_CPP_FEATURES": "no-rtti exceptions" } }, diff --git a/src/native/libmono-android.map.txt b/src/native/libmono-android.map.txt new file mode 100644 index 00000000000..18bcab675ef --- /dev/null +++ b/src/native/libmono-android.map.txt @@ -0,0 +1,15 @@ +LIBMONO_ANDROID { + global: + JNI_OnLoad; + Java_mono_android_Runtime_dumpTimingData; + Java_mono_android_Runtime_init; + Java_mono_android_Runtime_initInternal; + Java_mono_android_Runtime_notifyTimeZoneChanged; + Java_mono_android_Runtime_propagateUncaughtException; + Java_mono_android_Runtime_register; + _monodroid_freeifaddrs; + _monodroid_getifaddrs; + + local: + *; +}; diff --git a/src/native/monodroid/CMakeLists.txt b/src/native/monodroid/CMakeLists.txt index 8a5ebc0ec12..c191a6103bb 100644 --- a/src/native/monodroid/CMakeLists.txt +++ b/src/native/monodroid/CMakeLists.txt @@ -243,6 +243,12 @@ endmacro () lib_target_options(${XAMARIN_MONO_ANDROID_LIB}) xa_add_compile_definitions(${XAMARIN_MONO_ANDROID_LIB}) +target_link_options(${XAMARIN_MONO_ANDROID_LIB} + PRIVATE + -Wl,--version-script,${CMAKE_SOURCE_DIR}/libmono-android.map.txt + -Wl,--no-undefined-version +) + if(BUILD_STATIC_LIBRARY) lib_target_options(${XAMARIN_MONO_ANDROID_STATIC_LIB}) xa_add_compile_definitions(${XAMARIN_MONO_ANDROID_STATIC_LIB}) From e2f89a416191a64570ba684ef3e4de2792942e61 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Tue, 26 Nov 2024 11:11:57 +0100 Subject: [PATCH 02/54] Remove C++ ABI compatibility sources --- src-ThirdParty/llvm/verbose_abort.cpp | 77 -------------------------- src/native/CMakeLists.txt | 2 +- src/native/shared/CMakeLists.txt | 21 +------ src/native/shared/cxx-abi/string.cc | 12 ---- src/native/shared/cxx-abi/terminate.cc | 17 ------ src/native/tracing/CMakeLists.txt | 2 +- 6 files changed, 3 insertions(+), 128 deletions(-) delete mode 100644 src-ThirdParty/llvm/verbose_abort.cpp delete mode 100644 src/native/shared/cxx-abi/string.cc delete mode 100644 src/native/shared/cxx-abi/terminate.cc diff --git a/src-ThirdParty/llvm/verbose_abort.cpp b/src-ThirdParty/llvm/verbose_abort.cpp deleted file mode 100644 index 719134e2ae5..00000000000 --- a/src-ThirdParty/llvm/verbose_abort.cpp +++ /dev/null @@ -1,77 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include <__config> -#include <__verbose_abort> -#include -#include -#include - -#ifdef __BIONIC__ -# include -# if __ANDROID_API__ >= 21 -# include -extern "C" void android_set_abort_message(const char* msg); -# else -# include -# endif // __ANDROID_API__ >= 21 -#endif // __BIONIC__ - -#if defined(__APPLE__) && __has_include() -# include -#endif - -_LIBCPP_BEGIN_NAMESPACE_STD - -_LIBCPP_WEAK void __libcpp_verbose_abort(char const* format, ...) { - // Write message to stderr. We do this before formatting into a - // buffer so that we still get some information out if that fails. - { - va_list list; - va_start(list, format); - std::vfprintf(stderr, format, list); - va_end(list); - } - - // Format the arguments into an allocated buffer for CrashReport & friends. - // We leak the buffer on purpose, since we're about to abort() anyway. - char* buffer; - (void)buffer; - va_list list; - va_start(list, format); - -#if defined(__APPLE__) && __has_include() - // Note that we should technically synchronize accesses here (by e.g. taking a lock), - // however concretely we're only setting a pointer, so the likelihood of a race here - // is low. - vasprintf(&buffer, format, list); - CRSetCrashLogMessage(buffer); -#elif defined(__BIONIC__) - vasprintf(&buffer, format, list); - -# if __ANDROID_API__ >= 21 - // Show error in tombstone. - android_set_abort_message(buffer); - - // Show error in logcat. - openlog("libc++", 0, 0); - syslog(LOG_CRIT, "%s", buffer); - closelog(); -# else - // The good error reporting wasn't available in Android until L. Since we're - // about to abort anyway, just call __assert2, which will log _somewhere_ - // (tombstone and/or logcat) in older releases. - __assert2(__FILE__, __LINE__, __func__, buffer); -# endif // __ANDROID_API__ >= 21 -#endif - va_end(list); - - std::abort(); -} - -_LIBCPP_END_NAMESPACE_STD diff --git a/src/native/CMakeLists.txt b/src/native/CMakeLists.txt index f5be63f38d6..b6109634c19 100644 --- a/src/native/CMakeLists.txt +++ b/src/native/CMakeLists.txt @@ -120,7 +120,7 @@ else() set(USES_LIBSTDCPP True) endif() -set(SHARED_LIB_NAME xa::shared-no-abi) +set(SHARED_LIB_NAME xa::shared) # # Needed modules diff --git a/src/native/shared/CMakeLists.txt b/src/native/shared/CMakeLists.txt index 958c474f63c..4a3bb7ece18 100644 --- a/src/native/shared/CMakeLists.txt +++ b/src/native/shared/CMakeLists.txt @@ -1,21 +1,12 @@ set(LIB_NAME xa-shared-bits) set(LIB_ALIAS xa::shared) -set(LIB_NAME_NO_ABI ${LIB_NAME}-no-abi) -set(LIB_ALIAS_NO_ABI ${LIB_ALIAS}-no-abi) - -set(XA_SHARED_CXX_ABI_SOURCES - cxx-abi/string.cc - cxx-abi/terminate.cc - ${REPO_ROOT_DIR}/src-ThirdParty/llvm/verbose_abort.cpp -) - set(XA_SHARED_SOURCES helpers.cc log_functions.cc new_delete.cc ) -add_clang_check_sources("${XA_SHARED_SOURCES};${XA_SHARED_CXX_ABI_SOURCES}") +add_clang_check_sources("${XA_SHARED_SOURCES};") set(XXHASH_DIR "${EXTERNAL_DIR}/xxHash") set(CONSTEXPR_XXH3_DIR "${EXTERNAL_DIR}/constexpr-xxh3") @@ -30,15 +21,6 @@ add_library(${LIB_ALIAS} ALIAS ${LIB_NAME}) set_static_library_suffix(${LIB_NAME}) -add_library( - ${LIB_NAME_NO_ABI} - STATIC - ${XA_SHARED_SOURCES} -) -add_library(${LIB_ALIAS_NO_ABI} ALIAS ${LIB_NAME_NO_ABI}) - -set_static_library_suffix(${LIB_NAME_NO_ABI}) - macro(lib_target_options TARGET_NAME) target_include_directories( ${TARGET_NAME} @@ -81,4 +63,3 @@ macro(lib_target_options TARGET_NAME) endmacro() lib_target_options(${LIB_NAME}) -lib_target_options(${LIB_NAME_NO_ABI}) diff --git a/src/native/shared/cxx-abi/string.cc b/src/native/shared/cxx-abi/string.cc deleted file mode 100644 index 30d528e14ac..00000000000 --- a/src/native/shared/cxx-abi/string.cc +++ /dev/null @@ -1,12 +0,0 @@ -// -// Defining the macro will make the the explicit instantations below truely hidden -// -#define _LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS - -#include - -_LIBCPP_BEGIN_NAMESPACE_STD - -template class __attribute__ ((__visibility__("hidden"))) basic_string; - -_LIBCPP_END_NAMESPACE_STD diff --git a/src/native/shared/cxx-abi/terminate.cc b/src/native/shared/cxx-abi/terminate.cc deleted file mode 100644 index 04dc890fb61..00000000000 --- a/src/native/shared/cxx-abi/terminate.cc +++ /dev/null @@ -1,17 +0,0 @@ -// -// Simple implementation of std::terminate() for Xamarin.Android -// -// Does NOT support terminate handlers, since we don't use them. -// -#include -#include - -#include "helpers.hh" - -namespace std { - [[noreturn]] void - terminate () noexcept - { - xamarin::android::Helpers::abort_application ("std::terminate() called. Aborting."); - } -} diff --git a/src/native/tracing/CMakeLists.txt b/src/native/tracing/CMakeLists.txt index cc91cb2fa78..558b3513659 100644 --- a/src/native/tracing/CMakeLists.txt +++ b/src/native/tracing/CMakeLists.txt @@ -62,7 +62,7 @@ target_link_options( target_link_libraries( ${LIB_NAME} PRIVATE - xa::shared-no-abi + xa::shared xa::unwind xa::runtime-base xa::java-interop From e2ad767a8930b08730a8c05a60296e99faf3a413 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Tue, 26 Nov 2024 16:05:55 +0100 Subject: [PATCH 03/54] Update apkdesc files --- .../BuildReleaseArm64SimpleDotNet.apkdesc | 28 ++--- .../BuildReleaseArm64XFormsDotNet.apkdesc | 101 +++++++++--------- 2 files changed, 66 insertions(+), 63 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleDotNet.apkdesc b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleDotNet.apkdesc index 54d10a91441..b94b94d9485 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleDotNet.apkdesc +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleDotNet.apkdesc @@ -5,34 +5,34 @@ "Size": 3036 }, "classes.dex": { - "Size": 22488 + "Size": 389632 }, "lib/arm64-v8a/lib__Microsoft.Android.Resource.Designer.dll.so": { - "Size": 18208 + "Size": 18296 }, "lib/arm64-v8a/lib_Java.Interop.dll.so": { - "Size": 86368 + "Size": 86352 }, "lib/arm64-v8a/lib_Mono.Android.dll.so": { - "Size": 115752 + "Size": 116768 }, "lib/arm64-v8a/lib_Mono.Android.Runtime.dll.so": { - "Size": 22408 + "Size": 22416 }, "lib/arm64-v8a/lib_System.Console.dll.so": { - "Size": 24384 + "Size": 24376 }, "lib/arm64-v8a/lib_System.Linq.dll.so": { "Size": 26480 }, "lib/arm64-v8a/lib_System.Private.CoreLib.dll.so": { - "Size": 633792 + "Size": 634384 }, "lib/arm64-v8a/lib_System.Runtime.dll.so": { - "Size": 20048 + "Size": 20040 }, "lib/arm64-v8a/lib_System.Runtime.InteropServices.dll.so": { - "Size": 21592 + "Size": 21584 }, "lib/arm64-v8a/lib_UnnamedProject.dll.so": { "Size": 20024 @@ -44,10 +44,10 @@ "Size": 87432 }, "lib/arm64-v8a/libmonodroid.so": { - "Size": 485800 + "Size": 903032 }, "lib/arm64-v8a/libmonosgen-2.0.so": { - "Size": 3196336 + "Size": 3196512 }, "lib/arm64-v8a/libSystem.Globalization.Native.so": { "Size": 67248 @@ -62,10 +62,10 @@ "Size": 160232 }, "lib/arm64-v8a/libxamarin-app.so": { - "Size": 17912 + "Size": 13016 }, "META-INF/BNDLTOOL.RSA": { - "Size": 1221 + "Size": 1223 }, "META-INF/BNDLTOOL.SF": { "Size": 3266 @@ -98,5 +98,5 @@ "Size": 1904 } }, - "PackageSize": 2791957 + "PackageSize": 2984469 } \ No newline at end of file diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsDotNet.apkdesc b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsDotNet.apkdesc index 43092050ff6..40a70162747 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsDotNet.apkdesc +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsDotNet.apkdesc @@ -5,7 +5,10 @@ "Size": 6652 }, "classes.dex": { - "Size": 9172800 + "Size": 9448880 + }, + "classes2.dex": { + "Size": 154180 }, "kotlin/annotation/annotation.kotlin_builtins": { "Size": 928 @@ -29,28 +32,28 @@ "Size": 2396 }, "lib/arm64-v8a/lib__Microsoft.Android.Resource.Designer.dll.so": { - "Size": 19456 + "Size": 19544 }, "lib/arm64-v8a/lib_FormsViewGroup.dll.so": { - "Size": 25424 + "Size": 25184 }, "lib/arm64-v8a/lib_Java.Interop.dll.so": { - "Size": 94768 + "Size": 94736 }, "lib/arm64-v8a/lib_Mono.Android.dll.so": { - "Size": 523568 + "Size": 522832 }, "lib/arm64-v8a/lib_Mono.Android.Runtime.dll.so": { - "Size": 22408 + "Size": 22416 }, "lib/arm64-v8a/lib_mscorlib.dll.so": { "Size": 21432 }, "lib/arm64-v8a/lib_netstandard.dll.so": { - "Size": 23080 + "Size": 23072 }, "lib/arm64-v8a/lib_System.Collections.Concurrent.dll.so": { - "Size": 29808 + "Size": 29792 }, "lib/arm64-v8a/lib_System.Collections.dll.so": { "Size": 36288 @@ -59,7 +62,7 @@ "Size": 25760 }, "lib/arm64-v8a/lib_System.Collections.Specialized.dll.so": { - "Size": 23848 + "Size": 23840 }, "lib/arm64-v8a/lib_System.ComponentModel.dll.so": { "Size": 19584 @@ -71,31 +74,31 @@ "Size": 42456 }, "lib/arm64-v8a/lib_System.Console.dll.so": { - "Size": 24424 + "Size": 24416 }, "lib/arm64-v8a/lib_System.Core.dll.so": { - "Size": 19456 + "Size": 19448 }, "lib/arm64-v8a/lib_System.Diagnostics.DiagnosticSource.dll.so": { "Size": 28440 }, "lib/arm64-v8a/lib_System.Diagnostics.TraceSource.dll.so": { - "Size": 24696 + "Size": 24688 }, "lib/arm64-v8a/lib_System.dll.so": { - "Size": 19856 + "Size": 19848 }, "lib/arm64-v8a/lib_System.Drawing.dll.so": { - "Size": 19432 + "Size": 19424 }, "lib/arm64-v8a/lib_System.Drawing.Primitives.dll.so": { - "Size": 30048 + "Size": 30040 }, "lib/arm64-v8a/lib_System.Formats.Asn1.dll.so": { - "Size": 49936 + "Size": 49928 }, "lib/arm64-v8a/lib_System.IO.Compression.Brotli.dll.so": { - "Size": 29488 + "Size": 29472 }, "lib/arm64-v8a/lib_System.IO.Compression.dll.so": { "Size": 33784 @@ -107,7 +110,7 @@ "Size": 38736 }, "lib/arm64-v8a/lib_System.Linq.Expressions.dll.so": { - "Size": 185816 + "Size": 185800 }, "lib/arm64-v8a/lib_System.Net.Http.dll.so": { "Size": 89488 @@ -116,85 +119,85 @@ "Size": 41112 }, "lib/arm64-v8a/lib_System.Net.Requests.dll.so": { - "Size": 21552 + "Size": 21544 }, "lib/arm64-v8a/lib_System.ObjectModel.dll.so": { - "Size": 27072 + "Size": 27064 }, "lib/arm64-v8a/lib_System.Private.CoreLib.dll.so": { - "Size": 956368 + "Size": 956552 }, "lib/arm64-v8a/lib_System.Private.DataContractSerialization.dll.so": { - "Size": 216688 + "Size": 216720 }, "lib/arm64-v8a/lib_System.Private.Uri.dll.so": { "Size": 62184 }, "lib/arm64-v8a/lib_System.Private.Xml.dll.so": { - "Size": 237096 + "Size": 237120 }, "lib/arm64-v8a/lib_System.Private.Xml.Linq.dll.so": { - "Size": 35592 + "Size": 35584 }, "lib/arm64-v8a/lib_System.Runtime.dll.so": { "Size": 20200 }, "lib/arm64-v8a/lib_System.Runtime.InteropServices.dll.so": { - "Size": 21592 + "Size": 21584 }, "lib/arm64-v8a/lib_System.Runtime.Numerics.dll.so": { - "Size": 54400 + "Size": 54408 }, "lib/arm64-v8a/lib_System.Runtime.Serialization.dll.so": { - "Size": 19360 + "Size": 19352 }, "lib/arm64-v8a/lib_System.Runtime.Serialization.Formatters.dll.so": { - "Size": 20336 + "Size": 20328 }, "lib/arm64-v8a/lib_System.Runtime.Serialization.Primitives.dll.so": { - "Size": 21456 + "Size": 21448 }, "lib/arm64-v8a/lib_System.Security.Cryptography.dll.so": { "Size": 80496 }, "lib/arm64-v8a/lib_System.Text.RegularExpressions.dll.so": { - "Size": 183600 + "Size": 183584 }, "lib/arm64-v8a/lib_System.Xml.dll.so": { - "Size": 19256 + "Size": 19248 }, "lib/arm64-v8a/lib_System.Xml.Linq.dll.so": { - "Size": 19272 + "Size": 19264 }, "lib/arm64-v8a/lib_UnnamedProject.dll.so": { "Size": 22096 }, "lib/arm64-v8a/lib_Xamarin.AndroidX.Activity.dll.so": { - "Size": 34960 + "Size": 34760 }, "lib/arm64-v8a/lib_Xamarin.AndroidX.AppCompat.AppCompatResources.dll.so": { - "Size": 24520 + "Size": 24296 }, "lib/arm64-v8a/lib_Xamarin.AndroidX.AppCompat.dll.so": { - "Size": 163240 + "Size": 163072 }, "lib/arm64-v8a/lib_Xamarin.AndroidX.CardView.dll.so": { "Size": 24560 }, "lib/arm64-v8a/lib_Xamarin.AndroidX.CoordinatorLayout.dll.so": { - "Size": 35912 + "Size": 35680 }, "lib/arm64-v8a/lib_Xamarin.AndroidX.Core.dll.so": { - "Size": 151408 + "Size": 151216 }, "lib/arm64-v8a/lib_Xamarin.AndroidX.CursorAdapter.dll.so": { "Size": 27168 }, "lib/arm64-v8a/lib_Xamarin.AndroidX.DrawerLayout.dll.so": { - "Size": 33944 + "Size": 33760 }, "lib/arm64-v8a/lib_Xamarin.AndroidX.Fragment.dll.so": { - "Size": 72528 + "Size": 72224 }, "lib/arm64-v8a/lib_Xamarin.AndroidX.Legacy.Support.Core.UI.dll.so": { "Size": 23896 @@ -212,16 +215,16 @@ "Size": 31592 }, "lib/arm64-v8a/lib_Xamarin.AndroidX.RecyclerView.dll.so": { - "Size": 112256 + "Size": 111896 }, "lib/arm64-v8a/lib_Xamarin.AndroidX.SavedState.dll.so": { "Size": 23144 }, "lib/arm64-v8a/lib_Xamarin.AndroidX.SwipeRefreshLayout.dll.so": { - "Size": 31952 + "Size": 31672 }, "lib/arm64-v8a/lib_Xamarin.AndroidX.ViewPager.dll.so": { - "Size": 38056 + "Size": 37752 }, "lib/arm64-v8a/lib_Xamarin.Forms.Core.dll.so": { "Size": 581000 @@ -236,7 +239,7 @@ "Size": 80632 }, "lib/arm64-v8a/lib_Xamarin.Google.Android.Material.dll.so": { - "Size": 84768 + "Size": 84400 }, "lib/arm64-v8a/libarc.bin.so": { "Size": 18776 @@ -245,10 +248,10 @@ "Size": 87432 }, "lib/arm64-v8a/libmonodroid.so": { - "Size": 485800 + "Size": 903032 }, "lib/arm64-v8a/libmonosgen-2.0.so": { - "Size": 3196336 + "Size": 3196512 }, "lib/arm64-v8a/libSystem.Globalization.Native.so": { "Size": 67248 @@ -263,7 +266,7 @@ "Size": 160232 }, "lib/arm64-v8a/libxamarin-app.so": { - "Size": 349352 + "Size": 120016 }, "META-INF/androidx.activity_activity.version": { "Size": 6 @@ -419,7 +422,7 @@ "Size": 1221 }, "META-INF/BNDLTOOL.SF": { - "Size": 98577 + "Size": 98661 }, "META-INF/com.android.tools/proguard/coroutines.pro": { "Size": 1345 @@ -446,7 +449,7 @@ "Size": 5 }, "META-INF/MANIFEST.MF": { - "Size": 98450 + "Size": 98534 }, "META-INF/maven/com.google.guava/listenablefuture/pom.properties": { "Size": 96 @@ -2486,5 +2489,5 @@ "Size": 812848 } }, - "PackageSize": 10628363 + "PackageSize": 10796357 } \ No newline at end of file From 33500bb88f53edf07a07431e15eaf72a1c67b06a Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Thu, 31 Oct 2024 19:19:59 +0100 Subject: [PATCH 04/54] Playing around with some ideas --- src/native/monodroid/debug.cc | 2 +- src/native/monodroid/embedded-assemblies.hh | 9 +++- src/native/monodroid/monodroid-glue.cc | 15 +++++-- src/native/monodroid/osbridge.cc | 23 +++++++--- src/native/monodroid/xamarin_getifaddrs.cc | 32 ++++++------- src/native/runtime-base/android-system.cc | 2 +- src/native/runtime-base/cpu-arch-detect.cc | 8 ++-- src/native/runtime-base/jni-wrappers.hh | 8 ++-- src/native/shared/cpp-util.hh | 50 ++++++++++++++++++--- 9 files changed, 107 insertions(+), 42 deletions(-) diff --git a/src/native/monodroid/debug.cc b/src/native/monodroid/debug.cc index 139e8a24aae..add61468747 100644 --- a/src/native/monodroid/debug.cc +++ b/src/native/monodroid/debug.cc @@ -603,7 +603,7 @@ Debug::enable_soft_breakpoints (void) void* xamarin::android::conn_thread (void *arg) { - abort_if_invalid_pointer_argument (arg); + abort_if_invalid_pointer_argument (arg, "arg"); int res; Debug *instance = static_cast (arg); diff --git a/src/native/monodroid/embedded-assemblies.hh b/src/native/monodroid/embedded-assemblies.hh index 1bf6b358705..cfaaf4b9e40 100644 --- a/src/native/monodroid/embedded-assemblies.hh +++ b/src/native/monodroid/embedded-assemblies.hh @@ -26,6 +26,7 @@ #include "cppcompat.hh" #include "shared-constants.hh" #include "xxhash.hh" +#include "util.hh" #include @@ -158,7 +159,13 @@ namespace xamarin::android::internal { { area = static_cast(runtime_config_data); - abort_unless (runtime_config_data_size < std::numeric_limits::max (), "Runtime config binary blob size exceeds %u bytes", std::numeric_limits::max ()); + abort_unless ( + runtime_config_data_size < std::numeric_limits::max (), + [] { + return Util::monodroid_strdup_printf ("Runtime config binary blob size exceeds %u bytes", + std::numeric_limits::max ()); + } + ); size = static_cast(runtime_config_data_size); } diff --git a/src/native/monodroid/monodroid-glue.cc b/src/native/monodroid/monodroid-glue.cc index cd8d899a35d..a4d92ba1461 100644 --- a/src/native/monodroid/monodroid-glue.cc +++ b/src/native/monodroid/monodroid-glue.cc @@ -912,7 +912,12 @@ MonodroidRuntime::init_android_runtime (JNIEnv *env, jclass runtimeClass, jobjec jnienv_register_jni_natives = reinterpret_cast(mono_method_get_unmanaged_callers_only_ftnptr (registerType, &error)); } } - abort_unless (registerType != nullptr, "INTERNAL ERROR: Unable to find Android.Runtime.JNIEnvInit.RegisterJniNatives! %s", mono_error_get_message (&error)); + abort_unless ( + registerType != nullptr, + [&error] { + return Util::monodroid_strdup_printf("INTERNAL ERROR: Unable to find Android.Runtime.JNIEnvInit.RegisterJniNatives! %s", mono_error_get_message (&error)); + } + ); jclass lrefLoaderClass = env->GetObjectClass (loader); init.Loader_loadClass = env->GetMethodID (lrefLoaderClass, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;"); @@ -937,8 +942,12 @@ MonodroidRuntime::init_android_runtime (JNIEnv *env, jclass runtimeClass, jobjec abort_unless ( initialize != nullptr, - "Failed to obtain unmanaged-callers-only pointer to the Android.Runtime.JNIEnvInit.Initialize method. %s", - mono_error_get_message (&error) + [&error] { + return Util::monodroid_strdup_printf ( + "Failed to obtain unmanaged-callers-only pointer to the Android.Runtime.JNIEnvInit.Initialize method. %s", + mono_error_get_message (&error) + ); + } ); initialize (&init); diff --git a/src/native/monodroid/osbridge.cc b/src/native/monodroid/osbridge.cc index fe68ce59d06..cc900a30906 100644 --- a/src/native/monodroid/osbridge.cc +++ b/src/native/monodroid/osbridge.cc @@ -683,7 +683,7 @@ OSBridge::target_from_jobject (jobject jobj) int OSBridge::scc_get_stashed_index (MonoGCBridgeSCC *scc) { - abort_if_invalid_pointer_argument (scc); + abort_if_invalid_pointer_argument (scc, "scc"); abort_unless (scc->num_objs < 0, "Attempted to load stashed index from an object which does not contain one."); return -scc->num_objs - 1; @@ -862,8 +862,14 @@ OSBridge::gc_cleanup_after_java_collection (JNIEnv *env, int num_sccs, MonoGCBri mono_field_get_value (obj, bridge_info->handle, &jref); if (jref) { alive++; - if (j > 0) - abort_unless (sccs [i]->is_alive, "Bridge SCC at index %d must be alive", i); + if (j > 0) { + abort_unless ( + sccs [i]->is_alive, + [&i] { + return Util::monodroid_strdup_printf ("Bridge SCC at index %d must be alive", i); + } + ); + } sccs [i]->is_alive = 1; mono_field_get_value (obj, bridge_info->refs_added, &refs_added); if (refs_added) { @@ -885,7 +891,10 @@ OSBridge::gc_cleanup_after_java_collection (JNIEnv *env, int num_sccs, MonoGCBri } } } else { - abort_unless (!sccs [i]->is_alive, "Bridge SCC at index %d must NOT be alive", i); + abort_unless ( + !sccs [i]->is_alive, + [&i] { return Util::monodroid_strdup_printf ("Bridge SCC at index %d must NOT be alive", i); } + ); } } } @@ -993,8 +1002,8 @@ OSBridge::ensure_jnienv (void) void OSBridge::initialize_on_onload (JavaVM *vm, JNIEnv *env) { - abort_if_invalid_pointer_argument (env); - abort_if_invalid_pointer_argument (vm); + abort_if_invalid_pointer_argument (env, "env"); + abort_if_invalid_pointer_argument (vm, "vm"); jvm = vm; jclass lref = env->FindClass ("java/lang/Runtime"); @@ -1018,7 +1027,7 @@ OSBridge::initialize_on_onload (JavaVM *vm, JNIEnv *env) void OSBridge::initialize_on_runtime_init (JNIEnv *env, jclass runtimeClass) { - abort_if_invalid_pointer_argument (env); + abort_if_invalid_pointer_argument (env, "env"); GCUserPeer_class = RuntimeUtil::get_class_from_runtime_field(env, runtimeClass, "mono_android_GCUserPeer", true); GCUserPeer_ctor = env->GetMethodID (GCUserPeer_class, "", "()V"); abort_unless (GCUserPeer_class != nullptr && GCUserPeer_ctor != nullptr, "Failed to load mono.android.GCUserPeer!"); diff --git a/src/native/monodroid/xamarin_getifaddrs.cc b/src/native/monodroid/xamarin_getifaddrs.cc index 17f0f8a7ba6..9f071132976 100644 --- a/src/native/monodroid/xamarin_getifaddrs.cc +++ b/src/native/monodroid/xamarin_getifaddrs.cc @@ -370,8 +370,8 @@ get_ifaddrs_impl (int (**getifaddrs_implementation) (struct _monodroid_ifaddrs * { void *libc; - abort_if_invalid_pointer_argument (getifaddrs_implementation); - abort_if_invalid_pointer_argument (freeifaddrs_implementation); + abort_if_invalid_pointer_argument (getifaddrs_implementation, "getifaddrs_implementation"); + abort_if_invalid_pointer_argument (freeifaddrs_implementation, "freeifaddrs_implementation"); libc = dlopen ("libc.so", RTLD_NOW); if (libc) { @@ -416,7 +416,7 @@ free_single_xamarin_ifaddrs (struct _monodroid_ifaddrs **ifap) static int open_netlink_session (netlink_session *session) { - abort_if_invalid_pointer_argument (session); + abort_if_invalid_pointer_argument (session, "session"); memset (session, 0, sizeof (*session)); session->sock_fd = socket (AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); @@ -488,9 +488,9 @@ send_netlink_dump_request (netlink_session *session, int type) static int append_ifaddr (struct _monodroid_ifaddrs *addr, struct _monodroid_ifaddrs **ifaddrs_head, struct _monodroid_ifaddrs **last_ifaddr) { - abort_if_invalid_pointer_argument (addr); - abort_if_invalid_pointer_argument (ifaddrs_head); - abort_if_invalid_pointer_argument (last_ifaddr); + abort_if_invalid_pointer_argument (addr, "addr"); + abort_if_invalid_pointer_argument (ifaddrs_head, "ifaddrs_head"); + abort_if_invalid_pointer_argument (last_ifaddr, "last_ifaddr"); if (!*ifaddrs_head) { *ifaddrs_head = *last_ifaddr = addr; @@ -524,9 +524,9 @@ parse_netlink_reply (netlink_session *session, struct _monodroid_ifaddrs **ifadd int ret = -1; unsigned char *response = NULL; - abort_if_invalid_pointer_argument (session); - abort_if_invalid_pointer_argument (ifaddrs_head); - abort_if_invalid_pointer_argument (last_ifaddr); + abort_if_invalid_pointer_argument (session, "session"); + abort_if_invalid_pointer_argument (ifaddrs_head, "ifaddrs_head"); + abort_if_invalid_pointer_argument (last_ifaddr, "last_ifaddr"); size_t buf_size = static_cast(getpagesize ()); log_debug (LOG_NETLINK, "receive buffer size == %d", buf_size); @@ -626,9 +626,9 @@ parse_netlink_reply (netlink_session *session, struct _monodroid_ifaddrs **ifadd static int fill_sa_address (struct sockaddr **sa, struct ifaddrmsg *net_address, void *rta_data, size_t rta_payload_length) { - abort_if_invalid_pointer_argument (sa); - abort_if_invalid_pointer_argument (net_address); - abort_if_invalid_pointer_argument (rta_data); + abort_if_invalid_pointer_argument (sa, "sa"); + abort_if_invalid_pointer_argument (net_address, "net_address"); + abort_if_invalid_pointer_argument (rta_data, "rta_data"); switch (net_address->ifa_family) { case AF_INET: { @@ -688,8 +688,8 @@ fill_sa_address (struct sockaddr **sa, struct ifaddrmsg *net_address, void *rta_ static int fill_ll_address (struct sockaddr_ll_extended **sa, struct ifinfomsg *net_interface, void *rta_data, size_t rta_payload_length) { - abort_if_invalid_pointer_argument (sa); - abort_if_invalid_pointer_argument (net_interface); + abort_if_invalid_pointer_argument (sa, "sa"); + abort_if_invalid_pointer_argument (net_interface, "net_interface"); /* Always allocate, do not free - caller may reuse the same variable */ *sa = reinterpret_cast(calloc (1, sizeof (**sa))); @@ -845,7 +845,7 @@ get_link_address (const struct nlmsghdr *message, struct _monodroid_ifaddrs **if struct sockaddr **sa; size_t payload_size; - abort_if_invalid_pointer_argument (message); + abort_if_invalid_pointer_argument (message, "message"); net_address = reinterpret_cast (NLMSG_DATA (message)); length = static_cast(IFA_PAYLOAD (message)); log_debug (LOG_NETLINK, " address data length: %u", length); @@ -995,7 +995,7 @@ get_link_info (const struct nlmsghdr *message) struct _monodroid_ifaddrs *ifa = NULL; struct sockaddr_ll_extended *sa = NULL; - abort_if_invalid_pointer_argument (message); + abort_if_invalid_pointer_argument (message, "message"); net_interface = reinterpret_cast (NLMSG_DATA (message)); length = static_cast(message->nlmsg_len - NLMSG_LENGTH (sizeof (*net_interface))); if (length <= 0) { diff --git a/src/native/runtime-base/android-system.cc b/src/native/runtime-base/android-system.cc index 025362628ae..44745a7f34f 100644 --- a/src/native/runtime-base/android-system.cc +++ b/src/native/runtime-base/android-system.cc @@ -323,7 +323,7 @@ AndroidSystem::load_dso (const char *path, unsigned int dl_flags, bool skip_exis void* AndroidSystem::load_dso_from_specified_dirs (const char **directories, size_t num_entries, const char *dso_name, unsigned int dl_flags) noexcept { - abort_if_invalid_pointer_argument (directories); + abort_if_invalid_pointer_argument (directories, "directories"); if (dso_name == nullptr) return nullptr; diff --git a/src/native/runtime-base/cpu-arch-detect.cc b/src/native/runtime-base/cpu-arch-detect.cc index d8bcb7dd5fc..7a7a47b0059 100644 --- a/src/native/runtime-base/cpu-arch-detect.cc +++ b/src/native/runtime-base/cpu-arch-detect.cc @@ -10,7 +10,7 @@ static inline constexpr size_t BUF_SIZE = 512uz; static int find_in_maps (const char *str) { - abort_if_invalid_pointer_argument (str); + abort_if_invalid_pointer_argument (str, "str"); FILE *maps = fopen ("/proc/self/maps", "r"); char *line; @@ -112,9 +112,9 @@ get_running_on_cpu (unsigned short *running_on_cpu) void _monodroid_detect_cpu_and_architecture (unsigned short *built_for_cpu, unsigned short *running_on_cpu, unsigned char *is64bit) { - abort_if_invalid_pointer_argument (built_for_cpu); - abort_if_invalid_pointer_argument (running_on_cpu); - abort_if_invalid_pointer_argument (is64bit); + abort_if_invalid_pointer_argument (built_for_cpu, "built_for_cpu"); + abort_if_invalid_pointer_argument (running_on_cpu, "running_on_cpu"); + abort_if_invalid_pointer_argument (is64bit, "is64bit"); *is64bit = is_64_bit (); get_built_for_cpu (built_for_cpu); diff --git a/src/native/runtime-base/jni-wrappers.hh b/src/native/runtime-base/jni-wrappers.hh index afe95e25b7b..e9dde0eb083 100644 --- a/src/native/runtime-base/jni-wrappers.hh +++ b/src/native/runtime-base/jni-wrappers.hh @@ -20,21 +20,21 @@ namespace xamarin::android : env (_env), jstr (nullptr) { - abort_if_invalid_pointer_argument (_env); + abort_if_invalid_pointer_argument (_env, "_env"); } explicit jstring_wrapper (JNIEnv *_env, const jobject jo) noexcept : env (_env), jstr (reinterpret_cast (jo)) { - abort_if_invalid_pointer_argument (_env); + abort_if_invalid_pointer_argument (_env, "_env"); } explicit jstring_wrapper (JNIEnv *_env, const jstring js) noexcept : env (_env), jstr (js) { - abort_if_invalid_pointer_argument (_env); + abort_if_invalid_pointer_argument (_env, "_env"); } jstring_wrapper (const jstring_wrapper&) = delete; @@ -137,7 +137,7 @@ namespace xamarin::android : env (_env), arr (_arr) { - abort_if_invalid_pointer_argument (_env); + abort_if_invalid_pointer_argument (_env, "_env"); if (_arr != nullptr) { len = static_cast(_env->GetArrayLength (_arr)); if (len > sizeof (static_wrappers) / sizeof (jstring_wrapper)) diff --git a/src/native/shared/cpp-util.hh b/src/native/shared/cpp-util.hh index 160fa844e36..8e83c409e85 100644 --- a/src/native/shared/cpp-util.hh +++ b/src/native/shared/cpp-util.hh @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -14,6 +15,7 @@ #include "helpers.hh" + static inline void do_abort_unless (const char* fmt, ...) { @@ -27,13 +29,51 @@ do_abort_unless (const char* fmt, ...) xamarin::android::Helpers::abort_application (n == -1 ? "Unable to allocate memory for abort message" : message); } -#define abort_unless(_condition_, _fmt_, ...) \ - if (!(_condition_)) [[unlikely]] { \ - do_abort_unless ("%s:%d (%s): " _fmt_, __FILE__, __LINE__, __FUNCTION__, ## __VA_ARGS__); \ +// #define abort_unless(_condition_, _fmt_, ...) \ +// if (!(_condition_)) [[unlikely]] { \ +// do_abort_unless ("%s:%d (%s): " _fmt_, __FILE__, __LINE__, __FUNCTION__, ## __VA_ARGS__); \ +// } + +template F> +[[gnu::always_inline, gnu::flatten]] +static inline void +abort_unless (bool condition, F&& get_message, std::source_location sloc = std::source_location::current ()) noexcept +{ + if (condition) [[likely]] { + return; } -#define abort_if_invalid_pointer_argument(_ptr_) abort_unless ((_ptr_) != nullptr, "Parameter '%s' must be a valid pointer", #_ptr_) -#define abort_if_negative_integer_argument(_arg_) abort_unless ((_arg_) > 0, "Parameter '%s' must be larger than 0", #_arg_) +// static_assert (std::is_same, char*>::value, "get_message must return 'char*'"); + xamarin::android::Helpers::abort_application (std::invoke (get_message), true /* log_location */, sloc); +} + +[[gnu::always_inline, gnu::flatten]] +static inline void +abort_unless (bool condition, const char *message, std::source_location sloc = std::source_location::current ()) noexcept +{ + if (condition) [[likely]] { + return; + } + xamarin::android::Helpers::abort_application (message, true /* log_location */, sloc); +} + +// #define abort_if_invalid_pointer_argument(_ptr_) abort_unless ((_ptr_) != nullptr, "Parameter '%s' must be a valid pointer", #_ptr_) +// #define abort_if_negative_integer_argument(_arg_) abort_unless ((_arg_) > 0, "Parameter '%s' must be larger than 0", #_arg_) + +template +[[gnu::always_inline, gnu::flatten]] +static inline void +abort_if_invalid_pointer_argument (T *ptr, const char *ptr_name, std::source_location sloc = std::source_location::current ()) noexcept +{ + abort_unless (ptr != nullptr, "Parameter '%s' must be a valid pointer", sloc); +} + +[[gnu::always_inline, gnu::flatten]] +static inline void +abort_if_negative_integer_argument (int arg, const char *arg_name, std::source_location sloc = std::source_location::current ()) noexcept +{ + abort_unless (arg > 0, "Parameter '%s' must be a valid pointer", sloc); +} // Helper to use in "printf debugging". Normally not used in code anywhere. No code should be shipped with any // of the calls present. From 95ecd7653c2db1182b9c06caade807b446404c49 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Mon, 4 Nov 2024 20:55:16 +0100 Subject: [PATCH 05/54] More consistent use of std::string_view + remove unused code --- src/native/monodroid/embedded-assemblies.hh | 17 +++-- src/native/monodroid/monodroid-glue.cc | 7 +- src/native/monodroid/osbridge.cc | 6 +- src/native/runtime-base/shared-constants.hh | 5 +- src/native/runtime-base/util.hh | 23 ------- src/native/shared/cpp-util.hh | 72 +++++++-------------- 6 files changed, 47 insertions(+), 83 deletions(-) diff --git a/src/native/monodroid/embedded-assemblies.hh b/src/native/monodroid/embedded-assemblies.hh index cfaaf4b9e40..6aad3fd223b 100644 --- a/src/native/monodroid/embedded-assemblies.hh +++ b/src/native/monodroid/embedded-assemblies.hh @@ -88,23 +88,28 @@ namespace xamarin::android::internal { static constexpr std::string_view zip_path_separator { "/" }; static constexpr std::string_view apk_lib_dir_name { "lib" }; + static constexpr size_t assemblies_prefix_size = calc_size(apk_lib_dir_name, zip_path_separator, SharedConstants::android_lib_abi, zip_path_separator); - static constexpr auto assemblies_prefix = concat_string_views (apk_lib_dir_name, zip_path_separator, SharedConstants::android_lib_abi, zip_path_separator); + static constexpr auto assemblies_prefix_array = concat_string_views (apk_lib_dir_name, zip_path_separator, SharedConstants::android_lib_abi, zip_path_separator); + static constexpr std::string_view assemblies_prefix { assemblies_prefix_array }; // We have two records for each assembly, for names with and without the extension static constexpr uint32_t assembly_store_index_entries_per_assembly = 2; static constexpr uint32_t number_of_assembly_store_files = 1; static constexpr std::string_view dso_suffix { ".so" }; - static constexpr auto apk_lib_prefix = assemblies_prefix; // concat_const (apk_lib_dir_name, zip_path_separator, SharedConstants::android_lib_abi, zip_path_separator); + static constexpr std::string_view apk_lib_prefix = assemblies_prefix; // concat_const (apk_lib_dir_name, zip_path_separator, SharedConstants::android_lib_abi, zip_path_separator); static constexpr std::string_view assembly_store_prefix { "libassemblies." }; static constexpr std::string_view assembly_store_extension { ".blob" }; static constexpr size_t assembly_store_file_name_size = calc_size (assembly_store_prefix, SharedConstants::android_lib_abi, assembly_store_extension, dso_suffix); - static constexpr auto assembly_store_file_name = concat_string_views (assembly_store_prefix, SharedConstants::android_lib_abi, assembly_store_extension, dso_suffix); + static constexpr auto assembly_store_file_name_array = concat_string_views (assembly_store_prefix, SharedConstants::android_lib_abi, assembly_store_extension, dso_suffix); + static constexpr std::string_view assembly_store_file_name { assembly_store_file_name_array }; static constexpr size_t assembly_store_file_path_size = calc_size(apk_lib_dir_name, zip_path_separator, SharedConstants::android_lib_abi, zip_path_separator, assembly_store_prefix, SharedConstants::android_lib_abi, assembly_store_extension, dso_suffix); - static constexpr auto assembly_store_file_path = concat_string_views (apk_lib_dir_name, zip_path_separator, SharedConstants::android_lib_abi, zip_path_separator, assembly_store_prefix, SharedConstants::android_lib_abi, assembly_store_extension, dso_suffix); + static constexpr auto assembly_store_file_path_array = concat_string_views (apk_lib_dir_name, zip_path_separator, SharedConstants::android_lib_abi, zip_path_separator, assembly_store_prefix, SharedConstants::android_lib_abi, assembly_store_extension, dso_suffix); + static constexpr std::string_view assembly_store_file_path { assembly_store_file_path_array }; + static constexpr size_t dso_size_overhead = ArchiveDSOStubConfig::PayloadSectionOffset + (ArchiveDSOStubConfig::SectionHeaderEntryCount * ArchiveDSOStubConfig::SectionHeaderEntrySize); public: @@ -162,8 +167,8 @@ namespace xamarin::android::internal { abort_unless ( runtime_config_data_size < std::numeric_limits::max (), [] { - return Util::monodroid_strdup_printf ("Runtime config binary blob size exceeds %u bytes", - std::numeric_limits::max ()); + return detail::_format_message ("Runtime config binary blob size exceeds %u bytes", + std::numeric_limits::max ()); } ); size = static_cast(runtime_config_data_size); diff --git a/src/native/monodroid/monodroid-glue.cc b/src/native/monodroid/monodroid-glue.cc index a4d92ba1461..09a4dba28f2 100644 --- a/src/native/monodroid/monodroid-glue.cc +++ b/src/native/monodroid/monodroid-glue.cc @@ -915,7 +915,10 @@ MonodroidRuntime::init_android_runtime (JNIEnv *env, jclass runtimeClass, jobjec abort_unless ( registerType != nullptr, [&error] { - return Util::monodroid_strdup_printf("INTERNAL ERROR: Unable to find Android.Runtime.JNIEnvInit.RegisterJniNatives! %s", mono_error_get_message (&error)); + return detail::_format_message ( + "INTERNAL ERROR: Unable to find Android.Runtime.JNIEnvInit.RegisterJniNatives! %s", + mono_error_get_message (&error) + ); } ); @@ -943,7 +946,7 @@ MonodroidRuntime::init_android_runtime (JNIEnv *env, jclass runtimeClass, jobjec abort_unless ( initialize != nullptr, [&error] { - return Util::monodroid_strdup_printf ( + return detail::_format_message ( "Failed to obtain unmanaged-callers-only pointer to the Android.Runtime.JNIEnvInit.Initialize method. %s", mono_error_get_message (&error) ); diff --git a/src/native/monodroid/osbridge.cc b/src/native/monodroid/osbridge.cc index cc900a30906..d2725d278e2 100644 --- a/src/native/monodroid/osbridge.cc +++ b/src/native/monodroid/osbridge.cc @@ -865,9 +865,7 @@ OSBridge::gc_cleanup_after_java_collection (JNIEnv *env, int num_sccs, MonoGCBri if (j > 0) { abort_unless ( sccs [i]->is_alive, - [&i] { - return Util::monodroid_strdup_printf ("Bridge SCC at index %d must be alive", i); - } + [&i] { return detail::_format_message ("Bridge SCC at index %d must be alive", i); } ); } sccs [i]->is_alive = 1; @@ -893,7 +891,7 @@ OSBridge::gc_cleanup_after_java_collection (JNIEnv *env, int num_sccs, MonoGCBri } else { abort_unless ( !sccs [i]->is_alive, - [&i] { return Util::monodroid_strdup_printf ("Bridge SCC at index %d must NOT be alive", i); } + [&i] { return detail::_format_message ("Bridge SCC at index %d must NOT be alive", i); } ); } } diff --git a/src/native/runtime-base/shared-constants.hh b/src/native/runtime-base/shared-constants.hh index 001a53651e9..a3355963b59 100644 --- a/src/native/runtime-base/shared-constants.hh +++ b/src/native/runtime-base/shared-constants.hh @@ -40,10 +40,13 @@ namespace xamarin::android::internal static constexpr std::string_view DLL_EXTENSION { ".dll" }; static constexpr std::string_view PDB_EXTENSION { ".pdb" }; + private: static constexpr std::string_view RUNTIME_CONFIG_BLOB_BASE_NAME { "libarc.bin" }; static constexpr size_t runtime_config_blob_name_size = calc_size (RUNTIME_CONFIG_BLOB_BASE_NAME, MANGLED_ASSEMBLY_NAME_EXT); - static constexpr auto RUNTIME_CONFIG_BLOB_NAME = concat_string_views (RUNTIME_CONFIG_BLOB_BASE_NAME, MANGLED_ASSEMBLY_NAME_EXT); + static constexpr auto RUNTIME_CONFIG_BLOB_NAME_ARRAY = concat_string_views (RUNTIME_CONFIG_BLOB_BASE_NAME, MANGLED_ASSEMBLY_NAME_EXT); + public: + static constexpr std::string_view RUNTIME_CONFIG_BLOB_NAME { RUNTIME_CONFIG_BLOB_NAME_ARRAY }; static constexpr std::string_view MONO_SGEN_SO { "libmonosgen-2.0.so" }; static constexpr std::string_view MONO_SGEN_ARCH_SO { "libmonosgen-" __BITNESS__ "-2.0.so" }; static constexpr std::string_view OVERRIDE_DIRECTORY_NAME { ".__override__" }; diff --git a/src/native/runtime-base/util.hh b/src/native/runtime-base/util.hh index 8dd7f432664..97db495dbea 100644 --- a/src/native/runtime-base/util.hh +++ b/src/native/runtime-base/util.hh @@ -47,9 +47,6 @@ namespace xamarin::android { class Util { - static constexpr std::array hex_chars = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; - static constexpr uint32_t ms_in_nsec = 1000000ULL; - public: static void initialize () noexcept; @@ -197,13 +194,6 @@ namespace xamarin::android return p != nullptr && p [N - 1] == '\0'; } - template - static bool ends_with (const char *str, helper_char_array const& end) noexcept - { - char *p = const_cast (strstr (str, end.data ())); - return p != nullptr && p [N - 1] == '\0'; - } - template static bool ends_with (internal::string_base const& str, const char (&end)[N]) noexcept { @@ -230,19 +220,6 @@ namespace xamarin::android return memcmp (str.get () + len - end_length, end.data (), end_length) == 0; } - template - static bool ends_with (internal::string_base const& str, helper_char_array const& end) noexcept - { - constexpr size_t end_length = N - 1uz; - - size_t len = str.length (); - if (len < end_length) [[unlikely]] { - return false; - } - - return memcmp (str.get () + len - end_length, end.data (), end_length) == 0; - } - template static const TChar* find_last (internal::string_base const& str, const char ch) noexcept { diff --git a/src/native/shared/cpp-util.hh b/src/native/shared/cpp-util.hh index 8e83c409e85..f893d6614e3 100644 --- a/src/native/shared/cpp-util.hh +++ b/src/native/shared/cpp-util.hh @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -15,35 +16,33 @@ #include "helpers.hh" +namespace xamarin::android::detail { + [[gnu::always_inline, gnu::flatten]] + static inline const char* + _format_message (const char *format, ...) noexcept + { + va_list ap; + va_start (ap, format); -static inline void -do_abort_unless (const char* fmt, ...) -{ - va_list ap; - - va_start (ap, fmt); - char *message = nullptr; - int n = vasprintf (&message, fmt, ap); - va_end (ap); + char *message; + int ret = vasprintf (&message, format, ap); - xamarin::android::Helpers::abort_application (n == -1 ? "Unable to allocate memory for abort message" : message); + va_end (ap); + return ret == -1 ? "Out of memory" : message; + } } -// #define abort_unless(_condition_, _fmt_, ...) \ -// if (!(_condition_)) [[unlikely]] { \ -// do_abort_unless ("%s:%d (%s): " _fmt_, __FILE__, __LINE__, __FUNCTION__, ## __VA_ARGS__); \ -// } - template F> [[gnu::always_inline, gnu::flatten]] static inline void abort_unless (bool condition, F&& get_message, std::source_location sloc = std::source_location::current ()) noexcept { + static_assert (std::is_same::type, const char*>::value, "get_message must return 'const char*'"); + if (condition) [[likely]] { return; } -// static_assert (std::is_same, char*>::value, "get_message must return 'char*'"); xamarin::android::Helpers::abort_application (std::invoke (get_message), true /* log_location */, sloc); } @@ -57,22 +56,27 @@ abort_unless (bool condition, const char *message, std::source_location sloc = s xamarin::android::Helpers::abort_application (message, true /* log_location */, sloc); } -// #define abort_if_invalid_pointer_argument(_ptr_) abort_unless ((_ptr_) != nullptr, "Parameter '%s' must be a valid pointer", #_ptr_) -// #define abort_if_negative_integer_argument(_arg_) abort_unless ((_arg_) > 0, "Parameter '%s' must be larger than 0", #_arg_) - template [[gnu::always_inline, gnu::flatten]] static inline void abort_if_invalid_pointer_argument (T *ptr, const char *ptr_name, std::source_location sloc = std::source_location::current ()) noexcept { - abort_unless (ptr != nullptr, "Parameter '%s' must be a valid pointer", sloc); + abort_unless ( + ptr != nullptr, + [&ptr_name] { return xamarin::android::detail::_format_message ("Parameter '%s' must be a valid pointer", ptr_name); }, + sloc + ); } [[gnu::always_inline, gnu::flatten]] static inline void abort_if_negative_integer_argument (int arg, const char *arg_name, std::source_location sloc = std::source_location::current ()) noexcept { - abort_unless (arg > 0, "Parameter '%s' must be a valid pointer", sloc); + abort_unless ( + arg > 0, + [&arg_name] { return xamarin::android::detail::_format_message ("Parameter '%s' must be a valid pointer", arg_name); }, + sloc + ); } // Helper to use in "printf debugging". Normally not used in code anywhere. No code should be shipped with any @@ -106,32 +110,6 @@ namespace xamarin::android template using c_unique_ptr = std::unique_ptr>; - template - struct helper_char_array final - { - constexpr char* data () noexcept - { - return _elems; - } - - constexpr const char* data () const noexcept - { - return _elems; - } - - constexpr char const& operator[] (size_t n) const noexcept - { - return _elems[n]; - } - - constexpr char& operator[] (size_t n) noexcept - { - return _elems[n]; - } - - char _elems[Size]{}; - }; - template using char_array = std::array; From 539b080dc1ee96c7e8c672d320f282a6a4a6e08b Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Thu, 7 Nov 2024 14:13:30 +0100 Subject: [PATCH 06/54] Making EmbeddedAssemblies a static type In process to remove object instances for a slightly faster startup --- .../monodroid/embedded-assemblies-zip.cc | 20 +-- src/native/monodroid/embedded-assemblies.cc | 14 +- src/native/monodroid/embedded-assemblies.hh | 140 +++++++++--------- src/native/monodroid/monodroid-glue.cc | 2 +- 4 files changed, 87 insertions(+), 89 deletions(-) diff --git a/src/native/monodroid/embedded-assemblies-zip.cc b/src/native/monodroid/embedded-assemblies-zip.cc index 3f91b71dc9a..82a56859d88 100644 --- a/src/native/monodroid/embedded-assemblies-zip.cc +++ b/src/native/monodroid/embedded-assemblies-zip.cc @@ -298,7 +298,7 @@ EmbeddedAssemblies::zip_load_assembly_store_entries (std::vector const& } void -EmbeddedAssemblies::zip_load_entries (int fd, const char *apk_name, [[maybe_unused]] monodroid_should_register should_register) +EmbeddedAssemblies::zip_load_entries (int fd, const char *apk_name, [[maybe_unused]] monodroid_should_register should_register) noexcept { uint32_t cd_offset; uint32_t cd_size; @@ -412,7 +412,7 @@ EmbeddedAssemblies::set_debug_entry_data (XamarinAndroidBundledAssembly &entry, } bool -EmbeddedAssemblies::zip_read_cd_info (int fd, uint32_t& cd_offset, uint32_t& cd_size, uint16_t& cd_entries) +EmbeddedAssemblies::zip_read_cd_info (int fd, uint32_t& cd_offset, uint32_t& cd_size, uint16_t& cd_entries) noexcept { // The simplest case - no file comment off_t ret = ::lseek (fd, -ZIP_EOCD_LEN, SEEK_END); @@ -478,7 +478,7 @@ EmbeddedAssemblies::zip_read_cd_info (int fd, uint32_t& cd_offset, uint32_t& cd_ } bool -EmbeddedAssemblies::zip_adjust_data_offset (int fd, ZipEntryLoadState &state) +EmbeddedAssemblies::zip_adjust_data_offset (int fd, ZipEntryLoadState &state) noexcept { static constexpr size_t LH_FILE_NAME_LENGTH_OFFSET = 26uz; static constexpr size_t LH_EXTRA_LENGTH_OFFSET = 28uz; @@ -530,7 +530,7 @@ EmbeddedAssemblies::zip_adjust_data_offset (int fd, ZipEntryLoadState &state) template bool -EmbeddedAssemblies::zip_extract_cd_info (std::array const& buf, uint32_t& cd_offset, uint32_t& cd_size, uint16_t& cd_entries) +EmbeddedAssemblies::zip_extract_cd_info (std::array const& buf, uint32_t& cd_offset, uint32_t& cd_size, uint16_t& cd_entries) noexcept { constexpr size_t EOCD_TOTAL_ENTRIES_OFFSET = 10uz; constexpr size_t EOCD_CD_SIZE_OFFSET = 12uz; @@ -558,7 +558,7 @@ EmbeddedAssemblies::zip_extract_cd_info (std::array const& buf template force_inline bool -EmbeddedAssemblies::zip_ensure_valid_params (T const& buf, size_t index, size_t to_read) const noexcept +EmbeddedAssemblies::zip_ensure_valid_params (T const& buf, size_t index, size_t to_read) noexcept { if (index + to_read > buf.size ()) { log_error (LOG_ASSEMBLY, "Buffer too short to read %u bytes of data", to_read); @@ -570,7 +570,7 @@ EmbeddedAssemblies::zip_ensure_valid_params (T const& buf, size_t index, size_t template bool -EmbeddedAssemblies::zip_read_field (T const& src, size_t source_index, uint16_t& dst) const noexcept +EmbeddedAssemblies::zip_read_field (T const& src, size_t source_index, uint16_t& dst) noexcept { if (!zip_ensure_valid_params (src, source_index, sizeof (dst))) { return false; @@ -583,7 +583,7 @@ EmbeddedAssemblies::zip_read_field (T const& src, size_t source_index, uint16_t& template bool -EmbeddedAssemblies::zip_read_field (T const& src, size_t source_index, uint32_t& dst) const noexcept +EmbeddedAssemblies::zip_read_field (T const& src, size_t source_index, uint32_t& dst) noexcept { if (!zip_ensure_valid_params (src, source_index, sizeof (dst))) { return false; @@ -600,7 +600,7 @@ EmbeddedAssemblies::zip_read_field (T const& src, size_t source_index, uint32_t& template bool -EmbeddedAssemblies::zip_read_field (T const& src, size_t source_index, std::array& dst_sig) const noexcept +EmbeddedAssemblies::zip_read_field (T const& src, size_t source_index, std::array& dst_sig) noexcept { if (!zip_ensure_valid_params (src, source_index, dst_sig.size ())) { return false; @@ -612,7 +612,7 @@ EmbeddedAssemblies::zip_read_field (T const& src, size_t source_index, std::arra template bool -EmbeddedAssemblies::zip_read_field (T const& buf, size_t index, size_t count, dynamic_local_string& characters) const noexcept +EmbeddedAssemblies::zip_read_field (T const& buf, size_t index, size_t count, dynamic_local_string& characters) noexcept { if (!zip_ensure_valid_params (buf, index, count)) { return false; @@ -623,7 +623,7 @@ EmbeddedAssemblies::zip_read_field (T const& buf, size_t index, size_t count, dy } bool -EmbeddedAssemblies::zip_read_entry_info (std::vector const& buf, dynamic_local_string& file_name, ZipEntryLoadState &state) +EmbeddedAssemblies::zip_read_entry_info (std::vector const& buf, dynamic_local_string& file_name, ZipEntryLoadState &state) noexcept { constexpr size_t CD_COMPRESSION_METHOD_OFFSET = 10uz; constexpr size_t CD_UNCOMPRESSED_SIZE_OFFSET = 24uz; diff --git a/src/native/monodroid/embedded-assemblies.cc b/src/native/monodroid/embedded-assemblies.cc index 6a20df0bc59..f5855dfd832 100644 --- a/src/native/monodroid/embedded-assemblies.cc +++ b/src/native/monodroid/embedded-assemblies.cc @@ -65,7 +65,7 @@ class MonoGuidString final char *guid = nullptr; }; -void EmbeddedAssemblies::set_assemblies_prefix (const char *prefix) +void EmbeddedAssemblies::set_assemblies_prefix (const char *prefix) noexcept { if (assemblies_prefix_override != nullptr) delete[] assemblies_prefix_override; @@ -912,7 +912,7 @@ EmbeddedAssemblies::md_mmap_apk_file (int fd, uint32_t offset, size_t size, cons } void -EmbeddedAssemblies::gather_bundled_assemblies_from_apk (const char* apk, monodroid_should_register should_register) +EmbeddedAssemblies::gather_bundled_assemblies_from_apk (const char* apk, monodroid_should_register should_register) noexcept { int fd; @@ -1284,12 +1284,10 @@ EmbeddedAssemblies::register_from_filesystem (const char *lib_dir_path,bool look } auto register_fn = - application_config.have_assembly_store ? std::mem_fn (&EmbeddedAssemblies::maybe_register_blob_from_filesystem) : + application_config.have_assembly_store ? &EmbeddedAssemblies::maybe_register_blob_from_filesystem : (look_for_mangled_names ? - std::mem_fn (&EmbeddedAssemblies::maybe_register_assembly_from_filesystem) : - std::mem_fn (&EmbeddedAssemblies::maybe_register_assembly_from_filesystem - ) - ); + &EmbeddedAssemblies::maybe_register_assembly_from_filesystem : + &EmbeddedAssemblies::maybe_register_assembly_from_filesystem); size_t assembly_count = 0uz; do { @@ -1334,7 +1332,7 @@ EmbeddedAssemblies::register_from_filesystem (const char *lib_dir_path,bool look } // We get `true` if it's time to terminate - if (register_fn (this, should_register, assembly_count, cur, state)) { + if (register_fn (should_register, assembly_count, cur, state)) { break; } } while (true); diff --git a/src/native/monodroid/embedded-assemblies.hh b/src/native/monodroid/embedded-assemblies.hh index 6aad3fd223b..1ac42b9d1de 100644 --- a/src/native/monodroid/embedded-assemblies.hh +++ b/src/native/monodroid/embedded-assemblies.hh @@ -130,14 +130,14 @@ namespace xamarin::android::internal { /* returns current number of *all* assemblies found from all invocations */ template - size_t register_from_apk (const char *apk_file) noexcept + static size_t register_from_apk (const char *apk_file) noexcept { static_assert (should_register_fn != nullptr, "should_register_fn is a required template parameter"); return register_from_apk (apk_file, should_register_fn); } template - size_t register_from_filesystem () noexcept + static size_t register_from_filesystem () noexcept { static_assert (should_register_fn != nullptr, "should_register_fn is a required template parameter"); return register_from_filesystem (should_register_fn); @@ -148,19 +148,19 @@ namespace xamarin::android::internal { return assemblies_prefix; } - bool get_register_debug_symbols () const + static bool get_register_debug_symbols () noexcept { return register_debug_symbols; } - void set_register_debug_symbols (bool value) + static void set_register_debug_symbols (bool value) noexcept { register_debug_symbols = value; } - void set_assemblies_prefix (const char *prefix); + static void set_assemblies_prefix (const char *prefix) noexcept; - void get_runtime_config_blob (const char *& area, uint32_t& size) const + static void get_runtime_config_blob (const char *& area, uint32_t& size) noexcept { area = static_cast(runtime_config_data); @@ -174,7 +174,7 @@ namespace xamarin::android::internal { size = static_cast(runtime_config_data_size); } - void unmap_runtime_config_blob () + static void unmap_runtime_config_blob () noexcept { if (runtime_config_blob_mmap.area == nullptr) { return; @@ -185,17 +185,17 @@ namespace xamarin::android::internal { runtime_config_blob_mmap.size = 0; } - bool have_runtime_config_blob () const noexcept + static bool have_runtime_config_blob () noexcept { return application_config.have_runtime_config_blob && runtime_config_blob_mmap.area != nullptr; } - bool keep_scanning () const noexcept + static bool keep_scanning () noexcept { return need_to_scan_more_apks; } - void ensure_valid_assembly_stores () const noexcept + static void ensure_valid_assembly_stores () noexcept { if (!application_config.have_assembly_store) { return; @@ -207,32 +207,32 @@ namespace xamarin::android::internal { private: STATIC_IN_ANDROID_RELEASE const char* typemap_managed_to_java (MonoType *type, MonoClass *klass, const uint8_t *mvid) noexcept; STATIC_IN_ANDROID_RELEASE MonoReflectionType* typemap_java_to_managed (hash_t hash, const MonoString *java_type_name) noexcept; - size_t register_from_apk (const char *apk_file, monodroid_should_register should_register) noexcept; - size_t register_from_filesystem (monodroid_should_register should_register) noexcept; - size_t register_from_filesystem (const char *dir, bool look_for_mangled_names, monodroid_should_register should_register) noexcept; + static size_t register_from_apk (const char *apk_file, monodroid_should_register should_register) noexcept; + static size_t register_from_filesystem (monodroid_should_register should_register) noexcept; + static size_t register_from_filesystem (const char *dir, bool look_for_mangled_names, monodroid_should_register should_register) noexcept; template - bool maybe_register_assembly_from_filesystem (monodroid_should_register should_register, size_t& assembly_count, const dirent* dir_entry, ZipEntryLoadState& state) noexcept; - bool maybe_register_blob_from_filesystem (monodroid_should_register should_register, size_t& assembly_count, const dirent* dir_entry, ZipEntryLoadState& state) noexcept; + static bool maybe_register_assembly_from_filesystem (monodroid_should_register should_register, size_t& assembly_count, const dirent* dir_entry, ZipEntryLoadState& state) noexcept; + static bool maybe_register_blob_from_filesystem (monodroid_should_register should_register, size_t& assembly_count, const dirent* dir_entry, ZipEntryLoadState& state) noexcept; - void gather_bundled_assemblies_from_apk (const char* apk, monodroid_should_register should_register); + static void gather_bundled_assemblies_from_apk (const char* apk, monodroid_should_register should_register) noexcept; template - MonoAssembly* individual_assemblies_open_from_bundles (dynamic_local_string& name, TLoaderData loader_data, bool ref_only) noexcept; + static MonoAssembly* individual_assemblies_open_from_bundles (dynamic_local_string& name, TLoaderData loader_data, bool ref_only) noexcept; template - MonoAssembly* assembly_store_open_from_bundles (dynamic_local_string& name, TLoaderData loader_data, bool ref_only) noexcept; + static MonoAssembly* assembly_store_open_from_bundles (dynamic_local_string& name, TLoaderData loader_data, bool ref_only) noexcept; template - MonoAssembly* open_from_bundles (MonoAssemblyName* aname, TLoaderData loader_data, MonoError *error, bool ref_only) noexcept; + static MonoAssembly* open_from_bundles (MonoAssemblyName* aname, TLoaderData loader_data, MonoError *error, bool ref_only) noexcept; template - void map_runtime_file (XamarinAndroidBundledAssembly& file) noexcept; - void map_assembly (XamarinAndroidBundledAssembly& file) noexcept; - void map_debug_data (XamarinAndroidBundledAssembly& file) noexcept; + static void map_runtime_file (XamarinAndroidBundledAssembly& file) noexcept; + static void map_assembly (XamarinAndroidBundledAssembly& file) noexcept; + static void map_debug_data (XamarinAndroidBundledAssembly& file) noexcept; template - MonoAssembly* load_bundled_assembly ( + static MonoAssembly* load_bundled_assembly ( XamarinAndroidBundledAssembly& assembly, dynamic_local_string const& name, dynamic_local_string const& abi_name, @@ -254,37 +254,37 @@ namespace xamarin::android::internal { static MonoAssembly* open_from_bundles_full (MonoAssemblyName *aname, char **assemblies_path, void *user_data); static MonoAssembly* open_from_bundles (MonoAssemblyLoadContextGCHandle alc_gchandle, MonoAssemblyName *aname, char **assemblies_path, void *user_data, MonoError *error); - void set_assembly_data_and_size (uint8_t* source_assembly_data, uint32_t source_assembly_data_size, uint8_t*& dest_assembly_data, uint32_t& dest_assembly_data_size) noexcept; - void get_assembly_data (uint8_t *data, uint32_t data_size, const char *name, uint8_t*& assembly_data, uint32_t& assembly_data_size) noexcept; - void get_assembly_data (XamarinAndroidBundledAssembly const& e, uint8_t*& assembly_data, uint32_t& assembly_data_size) noexcept; - void get_assembly_data (AssemblyStoreSingleAssemblyRuntimeData const& e, uint8_t*& assembly_data, uint32_t& assembly_data_size) noexcept; + static void set_assembly_data_and_size (uint8_t* source_assembly_data, uint32_t source_assembly_data_size, uint8_t*& dest_assembly_data, uint32_t& dest_assembly_data_size) noexcept; + static void get_assembly_data (uint8_t *data, uint32_t data_size, const char *name, uint8_t*& assembly_data, uint32_t& assembly_data_size) noexcept; + static void get_assembly_data (XamarinAndroidBundledAssembly const& e, uint8_t*& assembly_data, uint32_t& assembly_data_size) noexcept; + static void get_assembly_data (AssemblyStoreSingleAssemblyRuntimeData const& e, uint8_t*& assembly_data, uint32_t& assembly_data_size) noexcept; - void zip_load_entries (int fd, const char *apk_name, monodroid_should_register should_register); - void zip_load_individual_assembly_entries (std::vector const& buf, uint32_t num_entries, monodroid_should_register should_register, ZipEntryLoadState &state) noexcept; - void zip_load_assembly_store_entries (std::vector const& buf, uint32_t num_entries, ZipEntryLoadState &state) noexcept; - bool zip_load_entry_common (size_t entry_index, std::vector const& buf, dynamic_local_string &entry_name, ZipEntryLoadState &state) noexcept; - bool zip_read_cd_info (int fd, uint32_t& cd_offset, uint32_t& cd_size, uint16_t& cd_entries); - bool zip_adjust_data_offset (int fd, ZipEntryLoadState &state); + static void zip_load_entries (int fd, const char *apk_name, monodroid_should_register should_register) noexcept; + static void zip_load_individual_assembly_entries (std::vector const& buf, uint32_t num_entries, monodroid_should_register should_register, ZipEntryLoadState &state) noexcept; + static void zip_load_assembly_store_entries (std::vector const& buf, uint32_t num_entries, ZipEntryLoadState &state) noexcept; + static bool zip_load_entry_common (size_t entry_index, std::vector const& buf, dynamic_local_string &entry_name, ZipEntryLoadState &state) noexcept; + static bool zip_read_cd_info (int fd, uint32_t& cd_offset, uint32_t& cd_size, uint16_t& cd_entries) noexcept; + static bool zip_adjust_data_offset (int fd, ZipEntryLoadState &state) noexcept; template - bool zip_extract_cd_info (std::array const& buf, uint32_t& cd_offset, uint32_t& cd_size, uint16_t& cd_entries); + static bool zip_extract_cd_info (std::array const& buf, uint32_t& cd_offset, uint32_t& cd_size, uint16_t& cd_entries) noexcept; template - bool zip_ensure_valid_params (T const& buf, size_t index, size_t to_read) const noexcept; + static bool zip_ensure_valid_params (T const& buf, size_t index, size_t to_read) noexcept; template - bool zip_read_field (T const& src, size_t source_index, uint16_t& dst) const noexcept; + static bool zip_read_field (T const& src, size_t source_index, uint16_t& dst) noexcept; template - bool zip_read_field (T const& src, size_t source_index, uint32_t& dst) const noexcept; + static bool zip_read_field (T const& src, size_t source_index, uint32_t& dst) noexcept; template - bool zip_read_field (T const& src, size_t source_index, std::array& dst_sig) const noexcept; + static bool zip_read_field (T const& src, size_t source_index, std::array& dst_sig) noexcept; template - bool zip_read_field (T const& buf, size_t index, size_t count, dynamic_local_string& characters) const noexcept; + static bool zip_read_field (T const& buf, size_t index, size_t count, dynamic_local_string& characters) noexcept; - bool zip_read_entry_info (std::vector const& buf, dynamic_local_string& file_name, ZipEntryLoadState &state); + static bool zip_read_entry_info (std::vector const& buf, dynamic_local_string& file_name, ZipEntryLoadState &state) noexcept; [[gnu::always_inline]] static std::tuple get_wrapper_dso_payload_pointer_and_size (md_mmap_info const& map_info, const char *file_name) noexcept @@ -318,7 +318,7 @@ namespace xamarin::android::internal { } [[gnu::always_inline]] - void store_mapped_runtime_config_data (md_mmap_info const& map_info, const char *file_name) noexcept + static void store_mapped_runtime_config_data (md_mmap_info const& map_info, const char *file_name) noexcept { auto [payload_start, payload_size] = get_wrapper_dso_payload_pointer_and_size (map_info, file_name); log_debug (LOG_ASSEMBLY, "Runtime config: payload pointer %p ; size %zu", payload_start, payload_size); @@ -327,7 +327,7 @@ namespace xamarin::android::internal { runtime_config_blob_found = true; } - std::tuple get_assemblies_prefix_and_length () const noexcept + static std::tuple get_assemblies_prefix_and_length () noexcept { if (assemblies_prefix_override != nullptr) { return { assemblies_prefix_override, static_cast(strlen (assemblies_prefix_override)) }; @@ -340,7 +340,7 @@ namespace xamarin::android::internal { return {assemblies_prefix.data (), assemblies_prefix.size () - 1}; } - bool all_required_zip_entries_found () const noexcept + static bool all_required_zip_entries_found () noexcept { return number_of_mapped_assembly_stores == number_of_assembly_store_files && number_of_zip_dso_entries >= application_config.number_of_shared_libraries @@ -362,21 +362,21 @@ namespace xamarin::android::internal { static const TypeMapModuleEntry* binary_search (uint32_t key, const TypeMapModuleEntry *arr, uint32_t n) noexcept; #endif template - void set_entry_data (XamarinAndroidBundledAssembly &entry, ZipEntryLoadState const& state, dynamic_local_string const& entry_name) noexcept; - void set_assembly_entry_data (XamarinAndroidBundledAssembly &entry, ZipEntryLoadState const& state, dynamic_local_string const& entry_name) noexcept; - void set_debug_entry_data (XamarinAndroidBundledAssembly &entry, ZipEntryLoadState const& state, dynamic_local_string const& entry_name) noexcept; - void map_assembly_store (dynamic_local_string const& entry_name, ZipEntryLoadState &state) noexcept; - const AssemblyStoreIndexEntry* find_assembly_store_entry (hash_t hash, const AssemblyStoreIndexEntry *entries, size_t entry_count) noexcept; - void store_individual_assembly_data (dynamic_local_string const& entry_name, ZipEntryLoadState const& state, monodroid_should_register should_register) noexcept; - - constexpr size_t get_mangled_name_max_size_overhead () + static void set_entry_data (XamarinAndroidBundledAssembly &entry, ZipEntryLoadState const& state, dynamic_local_string const& entry_name) noexcept; + static void set_assembly_entry_data (XamarinAndroidBundledAssembly &entry, ZipEntryLoadState const& state, dynamic_local_string const& entry_name) noexcept; + static void set_debug_entry_data (XamarinAndroidBundledAssembly &entry, ZipEntryLoadState const& state, dynamic_local_string const& entry_name) noexcept; + static void map_assembly_store (dynamic_local_string const& entry_name, ZipEntryLoadState &state) noexcept; + static const AssemblyStoreIndexEntry* find_assembly_store_entry (hash_t hash, const AssemblyStoreIndexEntry *entries, size_t entry_count) noexcept; + static void store_individual_assembly_data (dynamic_local_string const& entry_name, ZipEntryLoadState const& state, monodroid_should_register should_register) noexcept; + + constexpr static size_t get_mangled_name_max_size_overhead () { return SharedConstants::MANGLED_ASSEMBLY_NAME_EXT.size() + std::max (SharedConstants::MANGLED_ASSEMBLY_REGULAR_ASSEMBLY_MARKER.size(), SharedConstants::MANGLED_ASSEMBLY_SATELLITE_ASSEMBLY_MARKER.size()) + 1; // For the extra `-` char in the culture portion of satellite assembly's name } - void configure_state_for_individual_assembly_load (ZipEntryLoadState& state) noexcept + static void configure_state_for_individual_assembly_load (ZipEntryLoadState& state) noexcept { state.bundled_assemblies_slow_path = bundled_assembly_index >= application_config.number_of_assemblies_in_apk; state.max_assembly_name_size = application_config.bundled_assembly_name_width - 1; @@ -430,13 +430,13 @@ namespace xamarin::android::internal { static inline constexpr bool UnmangleSatelliteAssembly = true; static inline constexpr bool UnmangleRegularAssembly = false; - std::vector *bundled_debug_data = nullptr; - std::vector *extra_bundled_assemblies = nullptr; + static inline std::vector *bundled_debug_data = nullptr; + static inline std::vector *extra_bundled_assemblies = nullptr; - bool register_debug_symbols; - bool have_and_want_debug_symbols; - size_t bundled_assembly_index = 0uz; - size_t number_of_found_assemblies = 0uz; + static inline bool register_debug_symbols; + static inline bool have_and_want_debug_symbols; + static inline size_t bundled_assembly_index = 0uz; + static inline size_t number_of_found_assemblies = 0uz; #if defined (DEBUG) TypeMappingInfo *java_to_managed_maps; @@ -444,18 +444,18 @@ namespace xamarin::android::internal { TypeMap *type_maps; size_t type_map_count; #endif // DEBUG - const char *assemblies_prefix_override = nullptr; - - md_mmap_info runtime_config_blob_mmap{}; - void *runtime_config_data = nullptr; - size_t runtime_config_data_size = 0uz; - bool runtime_config_blob_found = false; - uint32_t number_of_mapped_assembly_stores = 0u; - uint32_t number_of_zip_dso_entries = 0u; - bool need_to_scan_more_apks = true; - - AssemblyStoreIndexEntry *assembly_store_hashes; - xamarin::android::mutex assembly_decompress_mutex; + static inline const char *assemblies_prefix_override = nullptr; + + static inline md_mmap_info runtime_config_blob_mmap{}; + static inline void *runtime_config_data = nullptr; + static inline size_t runtime_config_data_size = 0uz; + static inline bool runtime_config_blob_found = false; + static inline uint32_t number_of_mapped_assembly_stores = 0u; + static inline uint32_t number_of_zip_dso_entries = 0u; + static inline bool need_to_scan_more_apks = true; + + static inline AssemblyStoreIndexEntry *assembly_store_hashes; + static inline xamarin::android::mutex assembly_decompress_mutex; }; } diff --git a/src/native/monodroid/monodroid-glue.cc b/src/native/monodroid/monodroid-glue.cc index 09a4dba28f2..d9eca63b7a4 100644 --- a/src/native/monodroid/monodroid-glue.cc +++ b/src/native/monodroid/monodroid-glue.cc @@ -256,7 +256,7 @@ MonodroidRuntime::gather_bundled_assemblies (jstring_array_wrapper &runtimeApks, } } - size_t cur_num_assemblies = embeddedAssemblies.register_from_apk (apk_file.get_cstr ()); + size_t cur_num_assemblies = EmbeddedAssemblies::register_from_apk (apk_file.get_cstr ()); *out_user_assemblies_count += (cur_num_assemblies - prev_num_assemblies); prev_num_assemblies = cur_num_assemblies; From 2aa6e2bed76f1b7a528f15d4e50c9b283f95af16 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Wed, 13 Nov 2024 10:39:59 -0800 Subject: [PATCH 07/54] More cleanup --- src/native/runtime-base/android-system.hh | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/native/runtime-base/android-system.hh b/src/native/runtime-base/android-system.hh index 3afe52debb3..4ff2afe982d 100644 --- a/src/native/runtime-base/android-system.hh +++ b/src/native/runtime-base/android-system.hh @@ -174,13 +174,15 @@ namespace xamarin::android::internal { static bool is_interpreter_enabled () noexcept { - return get_mono_aot_mode () == MonoAotMode::MONO_AOT_MODE_INTERP_ONLY; - } - - // Hack, see comment for `aot_mode_last_is_interpreter` at the bottom of the class declaration - static bool is_aot_mode_last_really_interpreter_mode () noexcept - { - return false; + switch (get_mono_aot_mode ()) { + case MonoAotMode::MONO_AOT_MODE_INTERP: + case MonoAotMode::MONO_AOT_MODE_INTERP_ONLY: + case MonoAotMode::MONO_AOT_MODE_INTERP_LLVMONLY: + return true; + + default: + return false; + } } static void set_running_in_emulator (bool yesno) noexcept From 07246e5ea12316197538770106bba16acc424196 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Wed, 13 Nov 2024 10:58:18 -0800 Subject: [PATCH 08/54] More move to static, more cleanup --- src/native/monodroid/debug.cc | 2 +- src/native/monodroid/embedded-assemblies.cc | 10 ++++----- src/native/monodroid/embedded-assemblies.hh | 14 ++++++------ src/native/monodroid/globals.cc | 3 --- src/native/monodroid/globals.hh | 1 - src/native/monodroid/internal-pinvokes.cc | 2 +- src/native/monodroid/monodroid-glue.cc | 24 ++++++++++----------- 7 files changed, 26 insertions(+), 30 deletions(-) diff --git a/src/native/monodroid/debug.cc b/src/native/monodroid/debug.cc index add61468747..db787268f41 100644 --- a/src/native/monodroid/debug.cc +++ b/src/native/monodroid/debug.cc @@ -515,7 +515,7 @@ Debug::start_debugging (void) if (sdb_fd == 0) return; - embeddedAssemblies.set_register_debug_symbols (true); + EmbeddedAssemblies::set_register_debug_symbols (true); char *debug_arg = Util::monodroid_strdup_printf ("--debugger-agent=transport=socket-fd,address=%d,embedding=1", sdb_fd); std::array debug_options = { diff --git a/src/native/monodroid/embedded-assemblies.cc b/src/native/monodroid/embedded-assemblies.cc index f5855dfd832..db3704f160f 100644 --- a/src/native/monodroid/embedded-assemblies.cc +++ b/src/native/monodroid/embedded-assemblies.cc @@ -493,7 +493,7 @@ MonoAssembly* EmbeddedAssemblies::open_from_bundles (MonoAssemblyLoadContextGCHandle alc_gchandle, MonoAssemblyName *aname, [[maybe_unused]] char **assemblies_path, [[maybe_unused]] void *user_data, MonoError *error) { constexpr bool ref_only = false; - return embeddedAssemblies.open_from_bundles (aname, alc_gchandle, error, ref_only); + return EmbeddedAssemblies::open_from_bundles (aname, alc_gchandle, error, ref_only); } MonoAssembly* @@ -501,17 +501,17 @@ EmbeddedAssemblies::open_from_bundles_full (MonoAssemblyName *aname, [[maybe_unu { constexpr bool ref_only = false; - return embeddedAssemblies.open_from_bundles (aname, ref_only /* loader_data */, nullptr /* error */, ref_only); + return EmbeddedAssemblies::open_from_bundles (aname, ref_only /* loader_data */, nullptr /* error */, ref_only); } void -EmbeddedAssemblies::install_preload_hooks_for_appdomains () +EmbeddedAssemblies::install_preload_hooks_for_appdomains () noexcept { mono_install_assembly_preload_hook (open_from_bundles_full, nullptr); } void -EmbeddedAssemblies::install_preload_hooks_for_alc () +EmbeddedAssemblies::install_preload_hooks_for_alc () noexcept { mono_install_assembly_preload_hook_v3 ( open_from_bundles, @@ -679,7 +679,7 @@ EmbeddedAssemblies::typemap_java_to_managed (hash_t hash, const MonoString *java } else { MonoAssemblyLoadContextGCHandle alc_gchandle = mono_alc_get_default_gchandle (); MonoError mono_error; - assm = embeddedAssemblies.open_from_bundles (assembly_name, alc_gchandle, &mono_error, false /* ref_only */); + assm = EmbeddedAssemblies::open_from_bundles (assembly_name, alc_gchandle, &mono_error, false /* ref_only */); } if (assm == nullptr) { diff --git a/src/native/monodroid/embedded-assemblies.hh b/src/native/monodroid/embedded-assemblies.hh index 1ac42b9d1de..efaa296a0a7 100644 --- a/src/native/monodroid/embedded-assemblies.hh +++ b/src/native/monodroid/embedded-assemblies.hh @@ -122,11 +122,11 @@ namespace xamarin::android::internal { {} #endif // def RELEASE - STATIC_IN_ANDROID_RELEASE const char* typemap_managed_to_java (MonoReflectionType *type, const uint8_t *mvid) noexcept; + static const char* typemap_managed_to_java (MonoReflectionType *type, const uint8_t *mvid) noexcept; - void install_preload_hooks_for_appdomains (); - void install_preload_hooks_for_alc (); - STATIC_IN_ANDROID_RELEASE MonoReflectionType* typemap_java_to_managed (MonoString *java_type) noexcept; + static void install_preload_hooks_for_appdomains () noexcept; + static void install_preload_hooks_for_alc () noexcept; + static MonoReflectionType* typemap_java_to_managed (MonoString *java_type) noexcept; /* returns current number of *all* assemblies found from all invocations */ template @@ -205,8 +205,8 @@ namespace xamarin::android::internal { } private: - STATIC_IN_ANDROID_RELEASE const char* typemap_managed_to_java (MonoType *type, MonoClass *klass, const uint8_t *mvid) noexcept; - STATIC_IN_ANDROID_RELEASE MonoReflectionType* typemap_java_to_managed (hash_t hash, const MonoString *java_type_name) noexcept; + static const char* typemap_managed_to_java (MonoType *type, MonoClass *klass, const uint8_t *mvid) noexcept; + static MonoReflectionType* typemap_java_to_managed (hash_t hash, const MonoString *java_type_name) noexcept; static size_t register_from_apk (const char *apk_file, monodroid_should_register should_register) noexcept; static size_t register_from_filesystem (monodroid_should_register should_register) noexcept; static size_t register_from_filesystem (const char *dir, bool look_for_mangled_names, monodroid_should_register should_register) noexcept; @@ -247,7 +247,7 @@ namespace xamarin::android::internal { bool typemap_load_file (int dir_fd, const char *dir_path, const char *file_path, TypeMap &module); bool typemap_load_file (BinaryTypeMapHeader &header, const char *dir_path, const char *file_path, int file_fd, TypeMap &module); static ssize_t do_read (int fd, void *buf, size_t count); - const TypeMapEntry *typemap_managed_to_java (const char *managed_type_name) noexcept; + static const TypeMapEntry *typemap_managed_to_java (const char *managed_type_name) noexcept; #endif // DEBUG static md_mmap_info md_mmap_apk_file (int fd, uint32_t offset, size_t size, const char* filename); diff --git a/src/native/monodroid/globals.cc b/src/native/monodroid/globals.cc index eb1a2c87fe4..7822952f8f0 100644 --- a/src/native/monodroid/globals.cc +++ b/src/native/monodroid/globals.cc @@ -3,10 +3,7 @@ using namespace xamarin::android; using namespace xamarin::android::internal; -Util utils; -AndroidSystem androidSystem; OSBridge osBridge; -EmbeddedAssemblies embeddedAssemblies; MonodroidRuntime monodroidRuntime; Timing *timing = nullptr; diff --git a/src/native/monodroid/globals.hh b/src/native/monodroid/globals.hh index 7717ec2ec79..6f1649d9796 100644 --- a/src/native/monodroid/globals.hh +++ b/src/native/monodroid/globals.hh @@ -11,7 +11,6 @@ extern xamarin::android::Debug debug; extern xamarin::android::internal::OSBridge osBridge; -extern xamarin::android::internal::EmbeddedAssemblies embeddedAssemblies; extern xamarin::android::internal::MonodroidRuntime monodroidRuntime; extern xamarin::android::Timing *timing; diff --git a/src/native/monodroid/internal-pinvokes.cc b/src/native/monodroid/internal-pinvokes.cc index 0df3d868715..2324084a3f7 100644 --- a/src/native/monodroid/internal-pinvokes.cc +++ b/src/native/monodroid/internal-pinvokes.cc @@ -21,7 +21,7 @@ monodroid_get_system_property (const char *name, char **value) int monodroid_embedded_assemblies_set_assemblies_prefix (const char *prefix) { - embeddedAssemblies.set_assemblies_prefix (prefix); + EmbeddedAssemblies::set_assemblies_prefix (prefix); return 0; } diff --git a/src/native/monodroid/monodroid-glue.cc b/src/native/monodroid/monodroid-glue.cc index d9eca63b7a4..d40d9b264ae 100644 --- a/src/native/monodroid/monodroid-glue.cc +++ b/src/native/monodroid/monodroid-glue.cc @@ -228,7 +228,7 @@ inline void MonodroidRuntime::gather_bundled_assemblies (jstring_array_wrapper &runtimeApks, size_t *out_user_assemblies_count, bool have_split_apks) { if (!AndroidSystem::is_embedded_dso_mode_enabled ()) { - *out_user_assemblies_count = embeddedAssemblies.register_from_filesystem (); + *out_user_assemblies_count = EmbeddedAssemblies::register_from_filesystem (); return; } @@ -261,12 +261,12 @@ MonodroidRuntime::gather_bundled_assemblies (jstring_array_wrapper &runtimeApks, *out_user_assemblies_count += (cur_num_assemblies - prev_num_assemblies); prev_num_assemblies = cur_num_assemblies; - if (!embeddedAssemblies.keep_scanning ()) { + if (!EmbeddedAssemblies::keep_scanning ()) { break; } } - embeddedAssemblies.ensure_valid_assembly_stores (); + EmbeddedAssemblies::ensure_valid_assembly_stores (); } #if defined (DEBUG) @@ -495,7 +495,7 @@ MonodroidRuntime::set_debug_options (void) if (AndroidSystem::monodroid_get_system_property (SharedConstants::DEBUG_MONO_DEBUG_PROPERTY, nullptr) == 0) return; - embeddedAssemblies.set_register_debug_symbols (true); + EmbeddedAssemblies::set_register_debug_symbols (true); mono_debug_init (MONO_DEBUG_FORMAT_MONO); } @@ -513,7 +513,7 @@ MonodroidRuntime::mono_runtime_init ([[maybe_unused]] JNIEnv *env, [[maybe_unuse } else if (options.debug && cur_time > options.timeout_time) { log_warn (LOG_DEBUGGER, "Not starting the debugger as the timeout value has been reached; current-time: %lli timeout: %lli", cur_time, options.timeout_time); } else if (options.debug && cur_time <= options.timeout_time) { - embeddedAssemblies.set_register_debug_symbols (true); + EmbeddedAssemblies::set_register_debug_symbols (true); int loglevel; if (Logger::have_debugger_log_level ()) @@ -687,7 +687,7 @@ MonodroidRuntime::mono_runtime_init ([[maybe_unused]] JNIEnv *env, [[maybe_unuse * Looking for assemblies from the update dir takes precedence over * everything else, and thus must go LAST. */ - embeddedAssemblies.install_preload_hooks_for_appdomains (); + EmbeddedAssemblies::install_preload_hooks_for_appdomains (); #ifndef RELEASE mono_install_assembly_preload_hook (open_from_update_dir, nullptr); #endif @@ -702,7 +702,7 @@ MonodroidRuntime::mono_runtime_init ([[maybe_unused]] JNIEnv *env, [[maybe_unuse void MonodroidRuntime::cleanup_runtime_config ([[maybe_unused]] MonovmRuntimeConfigArguments *args, [[maybe_unused]] void *user_data) { - embeddedAssemblies.unmap_runtime_config_blob (); + EmbeddedAssemblies::unmap_runtime_config_blob (); } MonoDomain* @@ -712,14 +712,14 @@ MonodroidRuntime::create_domain (JNIEnv *env, jstring_array_wrapper &runtimeApks gather_bundled_assemblies (runtimeApks, &user_assemblies_count, have_split_apks); - if (embeddedAssemblies.have_runtime_config_blob ()) { + if (EmbeddedAssemblies::have_runtime_config_blob ()) { size_t blob_time_index; if (FastTiming::enabled ()) [[unlikely]] { blob_time_index = internal_timing->start_event (TimingEventKind::RuntimeConfigBlob); } runtime_config_args.kind = 1; - embeddedAssemblies.get_runtime_config_blob (runtime_config_args.runtimeconfig.data.data, runtime_config_args.runtimeconfig.data.data_len); + EmbeddedAssemblies::get_runtime_config_blob (runtime_config_args.runtimeconfig.data.data, runtime_config_args.runtimeconfig.data.data_len); monovm_runtimeconfig_initialize (&runtime_config_args, cleanup_runtime_config, nullptr); if (FastTiming::enabled ()) [[unlikely]] { @@ -1267,7 +1267,7 @@ MonodroidRuntime::create_and_initialize_domain (JNIEnv* env, jclass runtimeClass default_alc = mono_alc_get_default_gchandle (); abort_unless (default_alc != nullptr, "Default AssemblyLoadContext not found"); - embeddedAssemblies.install_preload_hooks_for_alc (); + EmbeddedAssemblies::install_preload_hooks_for_alc (); log_debug (LOG_ASSEMBLY, "ALC hooks installed"); bool preload = (AndroidSystem::is_assembly_preload_enabled () || (is_running_on_desktop && force_preload_assemblies)); @@ -1289,13 +1289,13 @@ MonodroidRuntime::monodroid_unhandled_exception (MonoObject *java_exception) MonoReflectionType* MonodroidRuntime::typemap_java_to_managed (MonoString *java_type_name) noexcept { - return embeddedAssemblies.typemap_java_to_managed (java_type_name); + return EmbeddedAssemblies::typemap_java_to_managed (java_type_name); } const char* MonodroidRuntime::typemap_managed_to_java (MonoReflectionType *type, const uint8_t *mvid) noexcept { - return embeddedAssemblies.typemap_managed_to_java (type, mvid); + return EmbeddedAssemblies::typemap_managed_to_java (type, mvid); } #endif // !def RELEASE From 6649f014de3ce5a97587f1cfd6b7e6921ccc8a20 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Wed, 13 Nov 2024 14:50:37 -0800 Subject: [PATCH 09/54] MonodroidRuntime is static now --- src/native/monodroid/globals.cc | 1 - src/native/monodroid/globals.hh | 1 - src/native/monodroid/internal-pinvokes.cc | 16 +-- .../monodroid/monodroid-glue-internal.hh | 116 ++++++++---------- src/native/monodroid/monodroid-glue.cc | 74 +++++------ 5 files changed, 99 insertions(+), 109 deletions(-) diff --git a/src/native/monodroid/globals.cc b/src/native/monodroid/globals.cc index 7822952f8f0..d5fdf4d08e4 100644 --- a/src/native/monodroid/globals.cc +++ b/src/native/monodroid/globals.cc @@ -4,7 +4,6 @@ using namespace xamarin::android; using namespace xamarin::android::internal; OSBridge osBridge; -MonodroidRuntime monodroidRuntime; Timing *timing = nullptr; Debug debug; diff --git a/src/native/monodroid/globals.hh b/src/native/monodroid/globals.hh index 6f1649d9796..046a0ff770f 100644 --- a/src/native/monodroid/globals.hh +++ b/src/native/monodroid/globals.hh @@ -11,7 +11,6 @@ extern xamarin::android::Debug debug; extern xamarin::android::internal::OSBridge osBridge; -extern xamarin::android::internal::MonodroidRuntime monodroidRuntime; extern xamarin::android::Timing *timing; #endif // !__GLOBALS_H diff --git a/src/native/monodroid/internal-pinvokes.cc b/src/native/monodroid/internal-pinvokes.cc index 2324084a3f7..c61768ea173 100644 --- a/src/native/monodroid/internal-pinvokes.cc +++ b/src/native/monodroid/internal-pinvokes.cc @@ -135,13 +135,13 @@ _monodroid_gc_wait_for_bridge_processing () void monodroid_clear_gdb_wait () { - monodroidRuntime.set_monodroid_gdb_wait (false); + MonodroidRuntime::set_monodroid_gdb_wait (false); } void* _monodroid_get_identity_hash_code (JNIEnv *env, void *v) { - intptr_t rv = env->CallStaticIntMethod (monodroidRuntime.get_java_class_System (), monodroidRuntime.get_java_class_method_System_identityHashCode (), v); + intptr_t rv = env->CallStaticIntMethod (MonodroidRuntime::get_java_class_System (), MonodroidRuntime::get_java_class_method_System_identityHashCode (), v); return (void*) rv; } @@ -149,9 +149,9 @@ void* _monodroid_timezone_get_default_id () { JNIEnv *env = osBridge.ensure_jnienv (); - jmethodID getDefault = env->GetStaticMethodID (monodroidRuntime.get_java_class_TimeZone (), "getDefault", "()Ljava/util/TimeZone;"); - jmethodID getID = env->GetMethodID (monodroidRuntime.get_java_class_TimeZone (), "getID", "()Ljava/lang/String;"); - jobject d = env->CallStaticObjectMethod (monodroidRuntime.get_java_class_TimeZone (), getDefault); + jmethodID getDefault = env->GetStaticMethodID (MonodroidRuntime::get_java_class_TimeZone (), "getDefault", "()Ljava/util/TimeZone;"); + jmethodID getID = env->GetMethodID (MonodroidRuntime::get_java_class_TimeZone (), "getID", "()Ljava/lang/String;"); + jobject d = env->CallStaticObjectMethod (MonodroidRuntime::get_java_class_TimeZone (), getDefault); jstring id = reinterpret_cast (env->CallObjectMethod (d, getID)); const char *mutf8 = env->GetStringUTFChars (id, nullptr); @@ -175,7 +175,7 @@ void _monodroid_counters_dump ([[maybe_unused]] const char *format, [[maybe_unused]] va_list args) { #if !defined (NET) - monodroidRuntime.dump_counters_v (format, args); + MonodroidRuntime::dump_counters_v (format, args); #endif // ndef NET } @@ -234,7 +234,7 @@ monodroid_strdup_printf (const char *format, ...) char* monodroid_TypeManager_get_java_class_name (jclass klass) { - return monodroidRuntime.get_java_class_name_for_TypeManager (klass); + return MonodroidRuntime::get_java_class_name_for_TypeManager (klass); } int @@ -333,5 +333,5 @@ monodroid_log_traces (uint32_t kind, const char *first_line) JNIEnv *env = osBridge.ensure_jnienv (); auto tk = static_cast(kind); - monodroidRuntime.log_traces (env, tk, first_line); + MonodroidRuntime::log_traces (env, tk, first_line); } diff --git a/src/native/monodroid/monodroid-glue-internal.hh b/src/native/monodroid/monodroid-glue-internal.hh index abbd8a8d4c6..59f00ceffd2 100644 --- a/src/native/monodroid/monodroid-glue-internal.hh +++ b/src/native/monodroid/monodroid-glue-internal.hh @@ -115,45 +115,45 @@ namespace xamarin::android::internal static constexpr int XA_LOG_COUNTERS = MONO_COUNTER_JIT | MONO_COUNTER_METADATA | MONO_COUNTER_GC | MONO_COUNTER_GENERICS | MONO_COUNTER_INTERP; public: - void Java_mono_android_Runtime_register (JNIEnv *env, jstring managedType, jclass nativeClass, jstring methods); - void Java_mono_android_Runtime_initInternal (JNIEnv *env, jclass klass, jstring lang, jobjectArray runtimeApksJava, + static void Java_mono_android_Runtime_register (JNIEnv *env, jstring managedType, jclass nativeClass, jstring methods) noexcept; + static void Java_mono_android_Runtime_initInternal (JNIEnv *env, jclass klass, jstring lang, jobjectArray runtimeApksJava, jstring runtimeNativeLibDir, jobjectArray appDirs, jint localDateTimeOffset, jobject loader, jobjectArray assembliesJava, jboolean isEmulator, - jboolean haveSplitApks); + jboolean haveSplitApks) noexcept; - jint Java_JNI_OnLoad (JavaVM *vm, void *reserved); + static jint Java_JNI_OnLoad (JavaVM *vm, void *reserved) noexcept; - jclass get_java_class_System () const + static jclass get_java_class_System () noexcept { return java_System; } - jmethodID get_java_class_method_System_identityHashCode () const + static jmethodID get_java_class_method_System_identityHashCode () noexcept { return java_System_identityHashCode; } - jclass get_java_class_TimeZone () const + static jclass get_java_class_TimeZone () noexcept { return java_TimeZone; } - void set_monodroid_gdb_wait (bool yes_no) + static void set_monodroid_gdb_wait (bool yes_no) noexcept { monodroid_gdb_wait = yes_no; } - void propagate_uncaught_exception (JNIEnv *env, jobject javaThread, jthrowable javaException); - char* get_java_class_name_for_TypeManager (jclass klass); - void log_traces (JNIEnv *env, TraceKind kind, const char *first_line) noexcept; + static void propagate_uncaught_exception (JNIEnv *env, jobject javaThread, jthrowable javaException) noexcept; + static char* get_java_class_name_for_TypeManager (jclass klass) noexcept; + static void log_traces (JNIEnv *env, TraceKind kind, const char *first_line) noexcept; private: static void mono_log_handler (const char *log_domain, const char *log_level, const char *message, mono_bool fatal, void *user_data); static void mono_log_standard_streams_handler (const char *str, mono_bool is_stdout); // A reference to unique_ptr is not the best practice ever, but it's faster this way - void setup_mono_tracing (std::unique_ptr const& mono_log_mask, bool have_log_assembly, bool have_log_gc); - void install_logging_handlers (); + static void setup_mono_tracing (std::unique_ptr const& mono_log_mask, bool have_log_assembly, bool have_log_gc) noexcept; + static void install_logging_handlers () noexcept; unsigned int convert_dl_flags (int flags); @@ -174,45 +174,45 @@ namespace xamarin::android::internal fnptr = reinterpret_cast(symptr); } - void create_xdg_directory (jstring_wrapper& home, size_t home_len, std::string_view const& relative_path, std::string_view const& environment_variable_name) noexcept; - void create_xdg_directories_and_environment (jstring_wrapper &homeDir); - void lookup_bridge_info (MonoClass *klass, const OSBridge::MonoJavaGCBridgeType *type, OSBridge::MonoJavaGCBridgeInfo *info); - void lookup_bridge_info (MonoImage *image, const OSBridge::MonoJavaGCBridgeType *type, OSBridge::MonoJavaGCBridgeInfo *info); - void load_assembly (MonoDomain *domain, jstring_wrapper &assembly); - void load_assembly (MonoAssemblyLoadContextGCHandle alc_handle, jstring_wrapper &assembly); - void load_assemblies (load_assemblies_context_type ctx, bool preload, jstring_array_wrapper &assemblies); - - void set_debug_options (); - void parse_gdb_options (); - void mono_runtime_init (JNIEnv *env, dynamic_local_string& runtime_args); - void init_android_runtime (JNIEnv *env, jclass runtimeClass, jobject loader); - void set_environment_variable_for_directory (const char *name, jstring_wrapper &value, bool createDirectory, mode_t mode); - - void set_environment_variable_for_directory (const char *name, jstring_wrapper &value) + static void create_xdg_directory (jstring_wrapper& home, size_t home_len, std::string_view const& relative_path, std::string_view const& environment_variable_name) noexcept; + static void create_xdg_directories_and_environment (jstring_wrapper &homeDir) noexcept; + static void lookup_bridge_info (MonoClass *klass, const OSBridge::MonoJavaGCBridgeType *type, OSBridge::MonoJavaGCBridgeInfo *info) noexcept; + static void lookup_bridge_info (MonoImage *image, const OSBridge::MonoJavaGCBridgeType *type, OSBridge::MonoJavaGCBridgeInfo *info) noexcept; + static void load_assembly (MonoDomain *domain, jstring_wrapper &assembly) noexcept; + static void load_assembly (MonoAssemblyLoadContextGCHandle alc_handle, jstring_wrapper &assembly) noexcept; + static void load_assemblies (load_assemblies_context_type ctx, bool preload, jstring_array_wrapper &assemblies) noexcept; + + static void set_debug_options () noexcept; + static void parse_gdb_options () noexcept; + static void mono_runtime_init (JNIEnv *env, dynamic_local_string& runtime_args) noexcept; + static void init_android_runtime (JNIEnv *env, jclass runtimeClass, jobject loader) noexcept; + static void set_environment_variable_for_directory (const char *name, jstring_wrapper &value, bool createDirectory, mode_t mode) noexcept; + + static void set_environment_variable_for_directory (const char *name, jstring_wrapper &value) noexcept { set_environment_variable_for_directory (name, value, true, DEFAULT_DIRECTORY_MODE); } - void set_environment_variable (const char *name, jstring_wrapper &value) + static void set_environment_variable (const char *name, jstring_wrapper &value) noexcept { set_environment_variable_for_directory (name, value, false, 0); } static void monodroid_unhandled_exception (MonoObject *java_exception); - MonoClass* get_android_runtime_class (); + static MonoClass* get_android_runtime_class () noexcept; - MonoDomain* create_domain (JNIEnv *env, jstring_array_wrapper &runtimeApks, bool is_root_domain, bool have_split_apks); - MonoDomain* create_and_initialize_domain (JNIEnv* env, jclass runtimeClass, jstring_array_wrapper &runtimeApks, + static MonoDomain* create_domain (JNIEnv *env, jstring_array_wrapper &runtimeApks, bool is_root_domain, bool have_split_apks) noexcept; + static MonoDomain* create_and_initialize_domain (JNIEnv* env, jclass runtimeClass, jstring_array_wrapper &runtimeApks, jstring_array_wrapper &assemblies, jobjectArray assembliesBytes, jstring_array_wrapper &assembliesPaths, jobject loader, bool is_root_domain, bool force_preload_assemblies, - bool have_split_apks); + bool have_split_apks) noexcept; - void gather_bundled_assemblies (jstring_array_wrapper &runtimeApks, size_t *out_user_assemblies_count, bool have_split_apks); + static void gather_bundled_assemblies (jstring_array_wrapper &runtimeApks, size_t *out_user_assemblies_count, bool have_split_apks) noexcept; static bool should_register_file (const char *filename); - void set_trace_options (); - void set_profile_options (); + static void set_trace_options () noexcept; + static void set_profile_options () noexcept; - void log_jit_event (MonoMethod *method, const char *event_name); + static void log_jit_event (MonoMethod *method, const char *event_name) noexcept; static void jit_begin (MonoProfiler *prof, MonoMethod *method); static void jit_failed (MonoProfiler *prof, MonoMethod *method); static void jit_done (MonoProfiler *prof, MonoMethod *method, MonoJitInfo* jinfo); @@ -236,44 +236,36 @@ namespace xamarin::android::internal #endif // def RELEASE #if defined (DEBUG) - void set_debug_env_vars (void); - bool parse_runtime_args (dynamic_local_string &runtime_args, RuntimeOptions *options); - int monodroid_debug_connect (int sock, struct sockaddr_in addr); - int monodroid_debug_accept (int sock, struct sockaddr_in addr); + static inline void set_debug_env_vars (void) noexcept; + static inline bool parse_runtime_args (dynamic_local_string &runtime_args, RuntimeOptions *options) noexcept; + static inline int monodroid_debug_connect (int sock, struct sockaddr_in addr) noexcept; + static inline int monodroid_debug_accept (int sock, struct sockaddr_in addr) noexcept; #endif // DEBUG #if !defined (RELEASE) static MonoAssembly* open_from_update_dir (MonoAssemblyName *aname, char **assemblies_path, void *user_data); #endif private: - MonoMethod *registerType = nullptr; - volatile bool monodroid_gdb_wait = true; - jclass java_System; - jmethodID java_System_identityHashCode; - jmethodID Class_getName; - jclass java_TimeZone; - timing_period jit_time; - FILE *jit_log; - MonoProfilerHandle profiler_handle; + static inline MonoMethod *registerType = nullptr; + static inline bool monodroid_gdb_wait = true; + static inline jclass java_System; + static inline jmethodID java_System_identityHashCode; + static inline jmethodID Class_getName; + static inline jclass java_TimeZone; + static inline timing_period jit_time; + static inline FILE *jit_log = nullptr; + static inline MonoProfilerHandle profiler_handle; /* * If set, monodroid will spin in a loop until the debugger breaks the wait by * clearing monodroid_gdb_wait. */ - bool wait_for_gdb; - - /* The context (mapping to a Mono AppDomain) that is currently selected as the - * active context from the point of view of Java. We cannot rely on the value - * of `mono_domain_get` for this as it's stored per-thread and we want to be - * able to switch our different contexts from different threads. - */ - int current_context_id = -1; - - jnienv_register_jni_natives_fn jnienv_register_jni_natives = nullptr; - MonoAssemblyLoadContextGCHandle default_alc = nullptr; + static inline bool wait_for_gdb = false; + static inline jnienv_register_jni_natives_fn jnienv_register_jni_natives = nullptr; + static inline MonoAssemblyLoadContextGCHandle default_alc = nullptr; static MonoCoreRuntimeProperties monovm_core_properties; - MonovmRuntimeConfigArguments runtime_config_args; + static inline MonovmRuntimeConfigArguments runtime_config_args; }; } #endif diff --git a/src/native/monodroid/monodroid-glue.cc b/src/native/monodroid/monodroid-glue.cc index d40d9b264ae..a90e239e83f 100644 --- a/src/native/monodroid/monodroid-glue.cc +++ b/src/native/monodroid/monodroid-glue.cc @@ -102,7 +102,7 @@ MonodroidRuntime::thread_end ([[maybe_unused]] MonoProfiler *prof, [[maybe_unuse } inline void -MonodroidRuntime::log_jit_event (MonoMethod *method, const char *event_name) +MonodroidRuntime::log_jit_event (MonoMethod *method, const char *event_name) noexcept { jit_time.mark_end (); @@ -120,19 +120,19 @@ MonodroidRuntime::log_jit_event (MonoMethod *method, const char *event_name) void MonodroidRuntime::jit_begin ([[maybe_unused]] MonoProfiler *prof, MonoMethod *method) { - monodroidRuntime.log_jit_event (method, "begin"); + MonodroidRuntime::log_jit_event (method, "begin"); } void MonodroidRuntime::jit_failed ([[maybe_unused]] MonoProfiler *prof, MonoMethod *method) { - monodroidRuntime.log_jit_event (method, "failed"); + MonodroidRuntime::log_jit_event (method, "failed"); } void MonodroidRuntime::jit_done ([[maybe_unused]] MonoProfiler *prof, MonoMethod *method, [[maybe_unused]] MonoJitInfo* jinfo) { - monodroidRuntime.log_jit_event (method, "done"); + MonodroidRuntime::log_jit_event (method, "done"); } #ifndef RELEASE @@ -225,7 +225,7 @@ MonodroidRuntime::should_register_file ([[maybe_unused]] const char *filename) } inline void -MonodroidRuntime::gather_bundled_assemblies (jstring_array_wrapper &runtimeApks, size_t *out_user_assemblies_count, bool have_split_apks) +MonodroidRuntime::gather_bundled_assemblies (jstring_array_wrapper &runtimeApks, size_t *out_user_assemblies_count, bool have_split_apks) noexcept { if (!AndroidSystem::is_embedded_dso_mode_enabled ()) { *out_user_assemblies_count = EmbeddedAssemblies::register_from_filesystem (); @@ -271,7 +271,7 @@ MonodroidRuntime::gather_bundled_assemblies (jstring_array_wrapper &runtimeApks, #if defined (DEBUG) int -MonodroidRuntime::monodroid_debug_connect (int sock, struct sockaddr_in addr) +MonodroidRuntime::monodroid_debug_connect (int sock, struct sockaddr_in addr) noexcept { long flags = fcntl (sock, F_GETFL, nullptr); flags |= O_NONBLOCK; @@ -316,7 +316,7 @@ MonodroidRuntime::monodroid_debug_connect (int sock, struct sockaddr_in addr) } int -MonodroidRuntime::monodroid_debug_accept (int sock, struct sockaddr_in addr) +MonodroidRuntime::monodroid_debug_accept (int sock, struct sockaddr_in addr) noexcept { ssize_t res = bind (sock, (struct sockaddr *) &addr, sizeof (addr)); if (res < 0) @@ -342,7 +342,7 @@ MonodroidRuntime::monodroid_debug_accept (int sock, struct sockaddr_in addr) #endif inline jint -MonodroidRuntime::Java_JNI_OnLoad (JavaVM *vm, [[maybe_unused]] void *reserved) +MonodroidRuntime::Java_JNI_OnLoad (JavaVM *vm, [[maybe_unused]] void *reserved) noexcept { JNIEnv *env; @@ -355,7 +355,7 @@ MonodroidRuntime::Java_JNI_OnLoad (JavaVM *vm, [[maybe_unused]] void *reserved) } void -MonodroidRuntime::parse_gdb_options () +MonodroidRuntime::parse_gdb_options () noexcept { dynamic_local_string val; @@ -389,7 +389,7 @@ MonodroidRuntime::parse_gdb_options () #if defined (DEBUG) bool -MonodroidRuntime::parse_runtime_args (dynamic_local_string &runtime_args, RuntimeOptions *options) +MonodroidRuntime::parse_runtime_args (dynamic_local_string &runtime_args, RuntimeOptions *options) noexcept { if (runtime_args.length () == 0) { log_warn (LOG_DEFAULT, "runtime args empty"); @@ -490,7 +490,7 @@ MonodroidRuntime::parse_runtime_args (dynamic_local_string& runtime_args) +MonodroidRuntime::mono_runtime_init ([[maybe_unused]] JNIEnv *env, [[maybe_unused]] dynamic_local_string& runtime_args) noexcept { #if defined (DEBUG) RuntimeOptions options{}; @@ -706,7 +706,7 @@ MonodroidRuntime::cleanup_runtime_config ([[maybe_unused]] MonovmRuntimeConfigAr } MonoDomain* -MonodroidRuntime::create_domain (JNIEnv *env, jstring_array_wrapper &runtimeApks, bool is_root_domain, bool have_split_apks) +MonodroidRuntime::create_domain (JNIEnv *env, jstring_array_wrapper &runtimeApks, bool is_root_domain, bool have_split_apks) noexcept { size_t user_assemblies_count = 0uz; @@ -773,7 +773,7 @@ MonodroidRuntime::create_domain (JNIEnv *env, jstring_array_wrapper &runtimeApks } force_inline void -MonodroidRuntime::lookup_bridge_info (MonoClass *klass, const OSBridge::MonoJavaGCBridgeType *type, OSBridge::MonoJavaGCBridgeInfo *info) +MonodroidRuntime::lookup_bridge_info (MonoClass *klass, const OSBridge::MonoJavaGCBridgeType *type, OSBridge::MonoJavaGCBridgeInfo *info) noexcept { info->klass = klass; info->handle = mono_class_get_field_from_name (info->klass, const_cast ("handle")); @@ -798,7 +798,7 @@ MonodroidRuntime::lookup_bridge_info (MonoClass *klass, const OSBridge::MonoJava } force_inline void -MonodroidRuntime::lookup_bridge_info (MonoImage *image, const OSBridge::MonoJavaGCBridgeType *type, OSBridge::MonoJavaGCBridgeInfo *info) +MonodroidRuntime::lookup_bridge_info (MonoImage *image, const OSBridge::MonoJavaGCBridgeType *type, OSBridge::MonoJavaGCBridgeInfo *info) noexcept { lookup_bridge_info ( mono_class_from_name (image, type->_namespace, type->_typename), @@ -814,7 +814,7 @@ MonodroidRuntime::monodroid_debugger_unhandled_exception (MonoException *ex) } void -MonodroidRuntime::init_android_runtime (JNIEnv *env, jclass runtimeClass, jobject loader) +MonodroidRuntime::init_android_runtime (JNIEnv *env, jclass runtimeClass, jobject loader) noexcept { constexpr std::string_view icall_typemap_java_to_managed { "Java.Interop.TypeManager::monodroid_typemap_java_to_managed" }; constexpr std::string_view icall_typemap_managed_to_java { "Android.Runtime.JNIEnv::monodroid_typemap_managed_to_java" }; @@ -960,7 +960,7 @@ MonodroidRuntime::init_android_runtime (JNIEnv *env, jclass runtimeClass, jobjec } MonoClass* -MonodroidRuntime::get_android_runtime_class () +MonodroidRuntime::get_android_runtime_class () noexcept { MonoAssembly *assm = Util::monodroid_load_assembly (default_alc, SharedConstants::MONO_ANDROID_ASSEMBLY_NAME.data ()); MonoImage *image = mono_assembly_get_image (assm); @@ -968,7 +968,7 @@ MonodroidRuntime::get_android_runtime_class () } inline void -MonodroidRuntime::propagate_uncaught_exception (JNIEnv *env, jobject javaThread, jthrowable javaException) +MonodroidRuntime::propagate_uncaught_exception (JNIEnv *env, jobject javaThread, jthrowable javaException) noexcept { MonoClass *runtime = get_android_runtime_class (); MonoMethod *method = mono_class_get_method_from_name (runtime, "PropagateUncaughtException", 3); @@ -991,7 +991,7 @@ setup_gc_logging (void) } inline void -MonodroidRuntime::set_environment_variable_for_directory (const char *name, jstring_wrapper &value, bool createDirectory, mode_t mode) +MonodroidRuntime::set_environment_variable_for_directory (const char *name, jstring_wrapper &value, bool createDirectory, mode_t mode) noexcept { if (createDirectory) { int rv = Util::create_directory (value.get_cstr (), mode); @@ -1016,7 +1016,7 @@ MonodroidRuntime::create_xdg_directory (jstring_wrapper& home, size_t home_len, } inline void -MonodroidRuntime::create_xdg_directories_and_environment (jstring_wrapper &homeDir) +MonodroidRuntime::create_xdg_directories_and_environment (jstring_wrapper &homeDir) noexcept { size_t home_len = strlen (homeDir.get_cstr ()); @@ -1031,7 +1031,7 @@ MonodroidRuntime::create_xdg_directories_and_environment (jstring_wrapper &homeD #if DEBUG void -MonodroidRuntime::set_debug_env_vars (void) +MonodroidRuntime::set_debug_env_vars (void) noexcept { dynamic_local_string value; if (AndroidSystem::monodroid_get_system_property (SharedConstants::DEBUG_MONO_ENV_PROPERTY, value) == 0) @@ -1071,7 +1071,7 @@ MonodroidRuntime::set_debug_env_vars (void) #endif /* DEBUG */ inline void -MonodroidRuntime::set_trace_options (void) +MonodroidRuntime::set_trace_options (void) noexcept { dynamic_local_string value; if (AndroidSystem::monodroid_get_system_property (SharedConstants::DEBUG_MONO_TRACE_PROPERTY, value) == 0) @@ -1081,7 +1081,7 @@ MonodroidRuntime::set_trace_options (void) } inline void -MonodroidRuntime::set_profile_options () +MonodroidRuntime::set_profile_options () noexcept { // We want to avoid dynamic allocation, thus let’s create a buffer that can take both the property value and a // path without allocation @@ -1146,7 +1146,7 @@ MonodroidRuntime::set_profile_options () } inline void -MonodroidRuntime::load_assembly (MonoAssemblyLoadContextGCHandle alc_handle, jstring_wrapper &assembly) +MonodroidRuntime::load_assembly (MonoAssemblyLoadContextGCHandle alc_handle, jstring_wrapper &assembly) noexcept { size_t total_time_index; if (FastTiming::enabled ()) [[unlikely]] { @@ -1178,7 +1178,7 @@ MonodroidRuntime::load_assembly (MonoAssemblyLoadContextGCHandle alc_handle, jst } inline void -MonodroidRuntime::load_assembly (MonoDomain *domain, jstring_wrapper &assembly) +MonodroidRuntime::load_assembly (MonoDomain *domain, jstring_wrapper &assembly) noexcept { size_t total_time_index; if (FastTiming::enabled ()) [[unlikely]] { @@ -1216,7 +1216,7 @@ MonodroidRuntime::load_assembly (MonoDomain *domain, jstring_wrapper &assembly) } inline void -MonodroidRuntime::load_assemblies (load_assemblies_context_type ctx, bool preload, jstring_array_wrapper &assemblies) +MonodroidRuntime::load_assemblies (load_assemblies_context_type ctx, bool preload, jstring_array_wrapper &assemblies) noexcept { size_t total_time_index; if (FastTiming::enabled ()) [[unlikely]] { @@ -1251,7 +1251,7 @@ MonoDomain* MonodroidRuntime::create_and_initialize_domain (JNIEnv* env, jclass runtimeClass, jstring_array_wrapper &runtimeApks, jstring_array_wrapper &assemblies, [[maybe_unused]] jobjectArray assembliesBytes, [[maybe_unused]] jstring_array_wrapper &assembliesPaths, jobject loader, bool is_root_domain, - bool force_preload_assemblies, bool have_split_apks) + bool force_preload_assemblies, bool have_split_apks) noexcept { MonoDomain* domain = create_domain (env, runtimeApks, is_root_domain, have_split_apks); // Asserting this on desktop apparently breaks a Designer test @@ -1300,7 +1300,7 @@ MonodroidRuntime::typemap_managed_to_java (MonoReflectionType *type, const uint8 #endif // !def RELEASE force_inline void -MonodroidRuntime::setup_mono_tracing (std::unique_ptr const& mono_log_mask, bool have_log_assembly, bool have_log_gc) +MonodroidRuntime::setup_mono_tracing (std::unique_ptr const& mono_log_mask, bool have_log_assembly, bool have_log_gc) noexcept { constexpr std::string_view MASK_ASM { "asm" }; constexpr std::string_view MASK_DLL { "dll" }; @@ -1373,7 +1373,7 @@ MonodroidRuntime::setup_mono_tracing (std::unique_ptr const& mono_log_ma } force_inline void -MonodroidRuntime::install_logging_handlers () +MonodroidRuntime::install_logging_handlers () noexcept { mono_trace_set_log_handler (mono_log_handler, nullptr); mono_trace_set_print_handler (mono_log_standard_streams_handler); @@ -1384,7 +1384,7 @@ inline void MonodroidRuntime::Java_mono_android_Runtime_initInternal (JNIEnv *env, jclass klass, jstring lang, jobjectArray runtimeApksJava, jstring runtimeNativeLibDir, jobjectArray appDirs, jint localDateTimeOffset, jobject loader, jobjectArray assembliesJava, jboolean isEmulator, - jboolean haveSplitApks) + jboolean haveSplitApks) noexcept { char *mono_log_mask_raw = nullptr; char *mono_log_level_raw = nullptr; @@ -1558,7 +1558,7 @@ JNIEXPORT jint JNICALL JNI_OnLoad (JavaVM *vm, void *reserved) { Util::initialize (); - return monodroidRuntime.Java_JNI_OnLoad (vm, reserved); + return MonodroidRuntime::Java_JNI_OnLoad (vm, reserved); } /* !DO NOT REMOVE! Used by the Android Designer */ @@ -1568,7 +1568,7 @@ Java_mono_android_Runtime_init (JNIEnv *env, jclass klass, jstring lang, jobject [[maybe_unused]] jobjectArray externalStorageDirs, jobjectArray assembliesJava, [[maybe_unused]] jstring packageName, [[maybe_unused]] jint apiLevel, [[maybe_unused]] jobjectArray environmentVariables) { - monodroidRuntime.Java_mono_android_Runtime_initInternal ( + MonodroidRuntime::Java_mono_android_Runtime_initInternal ( env, klass, lang, @@ -1589,7 +1589,7 @@ Java_mono_android_Runtime_initInternal (JNIEnv *env, jclass klass, jstring lang, jobjectArray assembliesJava, jboolean isEmulator, jboolean haveSplitApks) { - monodroidRuntime.Java_mono_android_Runtime_initInternal ( + MonodroidRuntime::Java_mono_android_Runtime_initInternal ( env, klass, lang, @@ -1605,7 +1605,7 @@ Java_mono_android_Runtime_initInternal (JNIEnv *env, jclass klass, jstring lang, } force_inline void -MonodroidRuntime::Java_mono_android_Runtime_register (JNIEnv *env, jstring managedType, jclass nativeClass, jstring methods) +MonodroidRuntime::Java_mono_android_Runtime_register (JNIEnv *env, jstring managedType, jclass nativeClass, jstring methods) noexcept { size_t total_time_index; @@ -1649,11 +1649,11 @@ JNICALL Java_mono_android_Runtime_dumpTimingData ([[maybe_unused]] JNIEnv *env, JNIEXPORT void JNICALL Java_mono_android_Runtime_register (JNIEnv *env, [[maybe_unused]] jclass klass, jstring managedType, jclass nativeClass, jstring methods) { - monodroidRuntime.Java_mono_android_Runtime_register (env, managedType, nativeClass, methods); + MonodroidRuntime::Java_mono_android_Runtime_register (env, managedType, nativeClass, methods); } char* -MonodroidRuntime::get_java_class_name_for_TypeManager (jclass klass) +MonodroidRuntime::get_java_class_name_for_TypeManager (jclass klass) noexcept { if (klass == nullptr || Class_getName == nullptr) return nullptr; @@ -1694,5 +1694,5 @@ get_jnienv (void) JNIEXPORT void JNICALL Java_mono_android_Runtime_propagateUncaughtException (JNIEnv *env, [[maybe_unused]] jclass klass, jobject javaThread, jthrowable javaException) { - monodroidRuntime.propagate_uncaught_exception (env, javaThread, javaException); + MonodroidRuntime::propagate_uncaught_exception (env, javaThread, javaException); } From 51e007a1fe14ede04d81453699d50322fffa2f68 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Wed, 13 Nov 2024 16:33:44 -0800 Subject: [PATCH 10/54] Buglets fixed --- src/native/monodroid/embedded-assemblies-zip.cc | 4 ++-- src/native/monodroid/embedded-assemblies.hh | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/native/monodroid/embedded-assemblies-zip.cc b/src/native/monodroid/embedded-assemblies-zip.cc index 82a56859d88..f8d4811df7b 100644 --- a/src/native/monodroid/embedded-assemblies-zip.cc +++ b/src/native/monodroid/embedded-assemblies-zip.cc @@ -257,7 +257,7 @@ EmbeddedAssemblies::zip_load_assembly_store_entries (std::vector const& dynamic_local_string entry_name; bool assembly_store_found = false; - log_debug (LOG_ASSEMBLY, "Looking for assembly stores in APK ('%s)", assembly_store_file_path.data ()); + log_debug (LOG_ASSEMBLY, "Looking for assembly stores in APK ('%s')", assembly_store_file_path.data ()); for (size_t i = 0uz; i < num_entries; i++) { if (all_required_zip_entries_found ()) { need_to_scan_more_apks = false; @@ -269,7 +269,7 @@ EmbeddedAssemblies::zip_load_assembly_store_entries (std::vector const& continue; } - if (!assembly_store_found && Util::ends_with (entry_name, assembly_store_file_path)) { + if (!assembly_store_found && Util::ends_with (entry_name, assembly_store_file_path.data ())) { assembly_store_found = true; map_assembly_store (entry_name, state); continue; diff --git a/src/native/monodroid/embedded-assemblies.hh b/src/native/monodroid/embedded-assemblies.hh index efaa296a0a7..88d57c21d47 100644 --- a/src/native/monodroid/embedded-assemblies.hh +++ b/src/native/monodroid/embedded-assemblies.hh @@ -454,8 +454,8 @@ namespace xamarin::android::internal { static inline uint32_t number_of_zip_dso_entries = 0u; static inline bool need_to_scan_more_apks = true; - static inline AssemblyStoreIndexEntry *assembly_store_hashes; - static inline xamarin::android::mutex assembly_decompress_mutex; + static inline AssemblyStoreIndexEntry *assembly_store_hashes = nullptr; + static inline xamarin::android::mutex assembly_decompress_mutex {}; }; } From 497e0948df4c18890436580a0f7886d111364a71 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Thu, 21 Nov 2024 14:06:41 +0100 Subject: [PATCH 11/54] Trying to find out why AppContext.GetData doesn't appear to work --- src/native/monodroid/embedded-assemblies-zip.cc | 9 +++++++++ src/native/monodroid/embedded-assemblies.hh | 4 +++- src/native/monodroid/monodroid-glue.cc | 5 ++++- src/native/runtime-base/shared-constants.hh | 5 +++-- src/native/runtime-base/util.hh | 5 +++++ 5 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/native/monodroid/embedded-assemblies-zip.cc b/src/native/monodroid/embedded-assemblies-zip.cc index f8d4811df7b..0926b72c83c 100644 --- a/src/native/monodroid/embedded-assemblies-zip.cc +++ b/src/native/monodroid/embedded-assemblies-zip.cc @@ -46,6 +46,7 @@ EmbeddedAssemblies::zip_load_entry_common (size_t entry_index, std::vectorstart_event (TimingEventKind::RuntimeConfigBlob); @@ -720,7 +721,9 @@ MonodroidRuntime::create_domain (JNIEnv *env, jstring_array_wrapper &runtimeApks runtime_config_args.kind = 1; EmbeddedAssemblies::get_runtime_config_blob (runtime_config_args.runtimeconfig.data.data, runtime_config_args.runtimeconfig.data.data_len); - monovm_runtimeconfig_initialize (&runtime_config_args, cleanup_runtime_config, nullptr); + log_info (LOG_ASSEMBLY, " rc data == %p; rc size == %zu", runtime_config_args.runtimeconfig.data.data, runtime_config_args.runtimeconfig.data.data_len); + int ret = monovm_runtimeconfig_initialize (&runtime_config_args, cleanup_runtime_config, nullptr); + log_info (LOG_ASSEMBLY, " ret == %d", ret); if (FastTiming::enabled ()) [[unlikely]] { internal_timing->end_event (blob_time_index); diff --git a/src/native/runtime-base/shared-constants.hh b/src/native/runtime-base/shared-constants.hh index a3355963b59..963faacd1f1 100644 --- a/src/native/runtime-base/shared-constants.hh +++ b/src/native/runtime-base/shared-constants.hh @@ -40,13 +40,14 @@ namespace xamarin::android::internal static constexpr std::string_view DLL_EXTENSION { ".dll" }; static constexpr std::string_view PDB_EXTENSION { ".pdb" }; - private: +// private: static constexpr std::string_view RUNTIME_CONFIG_BLOB_BASE_NAME { "libarc.bin" }; static constexpr size_t runtime_config_blob_name_size = calc_size (RUNTIME_CONFIG_BLOB_BASE_NAME, MANGLED_ASSEMBLY_NAME_EXT); static constexpr auto RUNTIME_CONFIG_BLOB_NAME_ARRAY = concat_string_views (RUNTIME_CONFIG_BLOB_BASE_NAME, MANGLED_ASSEMBLY_NAME_EXT); public: - static constexpr std::string_view RUNTIME_CONFIG_BLOB_NAME { RUNTIME_CONFIG_BLOB_NAME_ARRAY }; + // .data() must be used otherwise string_view length will include the trailing \0 in the array + static constexpr std::string_view RUNTIME_CONFIG_BLOB_NAME { RUNTIME_CONFIG_BLOB_NAME_ARRAY.data () }; static constexpr std::string_view MONO_SGEN_SO { "libmonosgen-2.0.so" }; static constexpr std::string_view MONO_SGEN_ARCH_SO { "libmonosgen-" __BITNESS__ "-2.0.so" }; static constexpr std::string_view OVERRIDE_DIRECTORY_NAME { ".__override__" }; diff --git a/src/native/runtime-base/util.hh b/src/native/runtime-base/util.hh index 97db495dbea..554f421c510 100644 --- a/src/native/runtime-base/util.hh +++ b/src/native/runtime-base/util.hh @@ -167,6 +167,11 @@ namespace xamarin::android return false; } + log_debug (LOG_ASSEMBLY, " ends_with: '%s' -> '%s'; sv.length () == %zu", + str.get () + str.length () - sv.length (), + sv.data (), + sv.length () + ); return memcmp (str.get () + str.length () - sv.length (), sv.data (), sv.length ()) == 0; } From 00d300f484f11c2241d4940a3a165e50f1b08dda Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Thu, 21 Nov 2024 18:11:21 +0100 Subject: [PATCH 12/54] Cleanup --- src/native/monodroid/embedded-assemblies-zip.cc | 9 --------- src/native/monodroid/embedded-assemblies.hh | 11 ++++++++--- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/src/native/monodroid/embedded-assemblies-zip.cc b/src/native/monodroid/embedded-assemblies-zip.cc index 0926b72c83c..f8d4811df7b 100644 --- a/src/native/monodroid/embedded-assemblies-zip.cc +++ b/src/native/monodroid/embedded-assemblies-zip.cc @@ -46,7 +46,6 @@ EmbeddedAssemblies::zip_load_entry_common (size_t entry_index, std::vector (apk_lib_dir_name, zip_path_separator, SharedConstants::android_lib_abi, zip_path_separator); - static constexpr std::string_view assemblies_prefix { assemblies_prefix_array }; + + // .data() must be used otherwise string_view length will include the trailing \0 in the array + static constexpr std::string_view assemblies_prefix { assemblies_prefix_array.data () }; // We have two records for each assembly, for names with and without the extension static constexpr uint32_t assembly_store_index_entries_per_assembly = 2; @@ -104,11 +106,14 @@ namespace xamarin::android::internal { static constexpr size_t assembly_store_file_name_size = calc_size (assembly_store_prefix, SharedConstants::android_lib_abi, assembly_store_extension, dso_suffix); static constexpr auto assembly_store_file_name_array = concat_string_views (assembly_store_prefix, SharedConstants::android_lib_abi, assembly_store_extension, dso_suffix); - static constexpr std::string_view assembly_store_file_name { assembly_store_file_name_array }; + + // .data() must be used otherwise string_view length will include the trailing \0 in the array + static constexpr std::string_view assembly_store_file_name { assembly_store_file_name_array.data () }; static constexpr size_t assembly_store_file_path_size = calc_size(apk_lib_dir_name, zip_path_separator, SharedConstants::android_lib_abi, zip_path_separator, assembly_store_prefix, SharedConstants::android_lib_abi, assembly_store_extension, dso_suffix); static constexpr auto assembly_store_file_path_array = concat_string_views (apk_lib_dir_name, zip_path_separator, SharedConstants::android_lib_abi, zip_path_separator, assembly_store_prefix, SharedConstants::android_lib_abi, assembly_store_extension, dso_suffix); - static constexpr std::string_view assembly_store_file_path { assembly_store_file_path_array }; + // .data() must be used otherwise string_view length will include the trailing \0 in the array + static constexpr std::string_view assembly_store_file_path { assembly_store_file_path_array.data () }; static constexpr size_t dso_size_overhead = ArchiveDSOStubConfig::PayloadSectionOffset + (ArchiveDSOStubConfig::SectionHeaderEntryCount * ArchiveDSOStubConfig::SectionHeaderEntrySize); From 69a35ad48540b7e93d52994466167d25086421d6 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Mon, 25 Nov 2024 13:19:09 +0100 Subject: [PATCH 13/54] Lengths and offsets... --- src/native/monodroid/embedded-assemblies.hh | 4 ++-- src/native/monodroid/internal-pinvokes.cc | 2 +- src/native/monodroid/monodroid-glue.cc | 5 +---- src/native/runtime-base/shared-constants.hh | 2 +- src/native/runtime-base/util.hh | 10 +++++----- 5 files changed, 10 insertions(+), 13 deletions(-) diff --git a/src/native/monodroid/embedded-assemblies.hh b/src/native/monodroid/embedded-assemblies.hh index d84c3f03e19..ff153942724 100644 --- a/src/native/monodroid/embedded-assemblies.hh +++ b/src/native/monodroid/embedded-assemblies.hh @@ -341,10 +341,10 @@ namespace xamarin::android::internal { } if (application_config.have_assembly_store) { - return { apk_lib_prefix.data (), apk_lib_prefix.size () - 1 }; + return { apk_lib_prefix.data (), apk_lib_prefix.size () }; } - return {assemblies_prefix.data (), assemblies_prefix.size () - 1}; + return {assemblies_prefix.data (), assemblies_prefix.size () }; } static bool all_required_zip_entries_found () noexcept diff --git a/src/native/monodroid/internal-pinvokes.cc b/src/native/monodroid/internal-pinvokes.cc index c61768ea173..81367aaea29 100644 --- a/src/native/monodroid/internal-pinvokes.cc +++ b/src/native/monodroid/internal-pinvokes.cc @@ -22,7 +22,7 @@ int monodroid_embedded_assemblies_set_assemblies_prefix (const char *prefix) { EmbeddedAssemblies::set_assemblies_prefix (prefix); - return 0; + return 0; } void diff --git a/src/native/monodroid/monodroid-glue.cc b/src/native/monodroid/monodroid-glue.cc index 47d72442040..a90e239e83f 100644 --- a/src/native/monodroid/monodroid-glue.cc +++ b/src/native/monodroid/monodroid-glue.cc @@ -713,7 +713,6 @@ MonodroidRuntime::create_domain (JNIEnv *env, jstring_array_wrapper &runtimeApks gather_bundled_assemblies (runtimeApks, &user_assemblies_count, have_split_apks); if (EmbeddedAssemblies::have_runtime_config_blob ()) { - log_info (LOG_ASSEMBLY, "Got runtime config blob"); size_t blob_time_index; if (FastTiming::enabled ()) [[unlikely]] { blob_time_index = internal_timing->start_event (TimingEventKind::RuntimeConfigBlob); @@ -721,9 +720,7 @@ MonodroidRuntime::create_domain (JNIEnv *env, jstring_array_wrapper &runtimeApks runtime_config_args.kind = 1; EmbeddedAssemblies::get_runtime_config_blob (runtime_config_args.runtimeconfig.data.data, runtime_config_args.runtimeconfig.data.data_len); - log_info (LOG_ASSEMBLY, " rc data == %p; rc size == %zu", runtime_config_args.runtimeconfig.data.data, runtime_config_args.runtimeconfig.data.data_len); - int ret = monovm_runtimeconfig_initialize (&runtime_config_args, cleanup_runtime_config, nullptr); - log_info (LOG_ASSEMBLY, " ret == %d", ret); + monovm_runtimeconfig_initialize (&runtime_config_args, cleanup_runtime_config, nullptr); if (FastTiming::enabled ()) [[unlikely]] { internal_timing->end_event (blob_time_index); diff --git a/src/native/runtime-base/shared-constants.hh b/src/native/runtime-base/shared-constants.hh index 963faacd1f1..0b7264d5ce4 100644 --- a/src/native/runtime-base/shared-constants.hh +++ b/src/native/runtime-base/shared-constants.hh @@ -40,7 +40,7 @@ namespace xamarin::android::internal static constexpr std::string_view DLL_EXTENSION { ".dll" }; static constexpr std::string_view PDB_EXTENSION { ".pdb" }; -// private: + private: static constexpr std::string_view RUNTIME_CONFIG_BLOB_BASE_NAME { "libarc.bin" }; static constexpr size_t runtime_config_blob_name_size = calc_size (RUNTIME_CONFIG_BLOB_BASE_NAME, MANGLED_ASSEMBLY_NAME_EXT); static constexpr auto RUNTIME_CONFIG_BLOB_NAME_ARRAY = concat_string_views (RUNTIME_CONFIG_BLOB_BASE_NAME, MANGLED_ASSEMBLY_NAME_EXT); diff --git a/src/native/runtime-base/util.hh b/src/native/runtime-base/util.hh index 554f421c510..d3a8d950dbb 100644 --- a/src/native/runtime-base/util.hh +++ b/src/native/runtime-base/util.hh @@ -167,11 +167,11 @@ namespace xamarin::android return false; } - log_debug (LOG_ASSEMBLY, " ends_with: '%s' -> '%s'; sv.length () == %zu", - str.get () + str.length () - sv.length (), - sv.data (), - sv.length () - ); + // log_debug (LOG_ASSEMBLY, " ends_with: '%s' -> '%s'; sv.length () == %zu", + // str.get () + str.length () - sv.length (), + // sv.data (), + // sv.length () + // ); return memcmp (str.get () + str.length () - sv.length (), sv.data (), sv.length ()) == 0; } From 01c77c0ed4082b9d575ebcc9194c45cfb8470071 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Tue, 26 Nov 2024 09:51:09 +0100 Subject: [PATCH 14/54] Cleanup --- src/native/monodroid/embedded-assemblies-zip.cc | 2 +- src/native/runtime-base/util.hh | 5 ----- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/src/native/monodroid/embedded-assemblies-zip.cc b/src/native/monodroid/embedded-assemblies-zip.cc index f8d4811df7b..d807c633a23 100644 --- a/src/native/monodroid/embedded-assemblies-zip.cc +++ b/src/native/monodroid/embedded-assemblies-zip.cc @@ -269,7 +269,7 @@ EmbeddedAssemblies::zip_load_assembly_store_entries (std::vector const& continue; } - if (!assembly_store_found && Util::ends_with (entry_name, assembly_store_file_path.data ())) { + if (!assembly_store_found && Util::ends_with (entry_name, assembly_store_file_path)) { assembly_store_found = true; map_assembly_store (entry_name, state); continue; diff --git a/src/native/runtime-base/util.hh b/src/native/runtime-base/util.hh index d3a8d950dbb..97db495dbea 100644 --- a/src/native/runtime-base/util.hh +++ b/src/native/runtime-base/util.hh @@ -167,11 +167,6 @@ namespace xamarin::android return false; } - // log_debug (LOG_ASSEMBLY, " ends_with: '%s' -> '%s'; sv.length () == %zu", - // str.get () + str.length () - sv.length (), - // sv.data (), - // sv.length () - // ); return memcmp (str.get () + str.length () - sv.length (), sv.data (), sv.length ()) == 0; } From e0b1e57b261871231c40ebb4faa1e33262235844 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Tue, 26 Nov 2024 19:02:12 +0100 Subject: [PATCH 15/54] Start using std::format and std::string_view string literals --- .../monodroid/embedded-assemblies-zip.cc | 130 ++++++---- src/native/monodroid/embedded-assemblies.cc | 243 ++++++++++-------- src/native/monodroid/embedded-assemblies.hh | 7 +- src/native/shared/CMakeLists.txt | 1 - src/native/shared/helpers.hh | 25 ++ src/native/shared/log_types.hh | 127 +++++++++ src/native/shared/new_delete.cc | 87 ------- 7 files changed, 370 insertions(+), 250 deletions(-) delete mode 100644 src/native/shared/new_delete.cc diff --git a/src/native/monodroid/embedded-assemblies-zip.cc b/src/native/monodroid/embedded-assemblies-zip.cc index d807c633a23..6d47ba7c042 100644 --- a/src/native/monodroid/embedded-assemblies-zip.cc +++ b/src/native/monodroid/embedded-assemblies-zip.cc @@ -1,6 +1,7 @@ #include #include #include +#include #include #include @@ -21,12 +22,12 @@ EmbeddedAssemblies::zip_load_entry_common (size_t entry_index, std::vector= application_config.number_of_assemblies_in_apk || state.bundled_assemblies_slow_path) [[unlikely]] { if (!state.bundled_assemblies_slow_path && bundled_assembly_index == application_config.number_of_assemblies_in_apk) { - log_warn (LOG_ASSEMBLY, "Number of assemblies stored at build time (%u) was incorrect, switching to slow bundling path.", application_config.number_of_assemblies_in_apk); + log_warn ( + LOG_ASSEMBLY, + std::format ( + "Number of assemblies stored at build time ({}) was incorrect, switching to slow bundling path.", + application_config.number_of_assemblies_in_apk + ) + ); } if (extra_bundled_assemblies == nullptr) { @@ -132,9 +139,9 @@ EmbeddedAssemblies::store_individual_assembly_data (dynamic_local_string if (number_of_mapped_assembly_stores > number_of_assembly_store_files) { Helpers::abort_application ( LOG_ASSEMBLY, - Util::monodroid_strdup_printf ( - "Too many assembly stores. Expected at most %u", + std::format ( + "Too many assembly stores. Expected at most {}", number_of_assembly_store_files ) ); @@ -189,7 +196,7 @@ EmbeddedAssemblies::map_assembly_store (dynamic_local_string int fd; bool close_fd; if (!AndroidSystem::is_embedded_dso_mode_enabled ()) { - log_debug (LOG_ASSEMBLY, "Mapping assembly blob file from filesystem"); + log_debug (LOG_ASSEMBLY, "Mapping assembly blob file from filesystem"sv); close_fd = true; // state.file_fd refers to the directory where our files live @@ -209,14 +216,14 @@ EmbeddedAssemblies::map_assembly_store (dynamic_local_string } auto [payload_start, payload_size] = get_wrapper_dso_payload_pointer_and_size (assembly_store_map, entry_name.get ()); - log_debug (LOG_ASSEMBLY, "Adjusted assembly store pointer: %p; size: %zu", payload_start, payload_size); + log_debug (LOG_ASSEMBLY, std::format ("Adjusted assembly store pointer: {:p}; size: {}", payload_start, payload_size)); auto header = static_cast(payload_start); if (header->magic != ASSEMBLY_STORE_MAGIC) { Helpers::abort_application ( LOG_ASSEMBLY, - Util::monodroid_strdup_printf ( - "Assembly store '%s' is not a valid .NET for Android assembly store file", + std::format ( + "Assembly store '{}' is not a valid .NET for Android assembly store file", entry_name.get () ) ); @@ -225,8 +232,8 @@ EmbeddedAssemblies::map_assembly_store (dynamic_local_string if (header->version != ASSEMBLY_STORE_FORMAT_VERSION) { Helpers::abort_application ( LOG_ASSEMBLY, - Util::monodroid_strdup_printf ( - "Assembly store '%s' uses format version 0x%x, instead of the expected 0x%x", + std::format ( + "Assembly store '{}' uses format version {:x}, instead of the expected {:x}", entry_name.get (), header->version, ASSEMBLY_STORE_FORMAT_VERSION @@ -257,7 +264,7 @@ EmbeddedAssemblies::zip_load_assembly_store_entries (std::vector const& dynamic_local_string entry_name; bool assembly_store_found = false; - log_debug (LOG_ASSEMBLY, "Looking for assembly stores in APK ('%s')", assembly_store_file_path.data ()); + log_debug (LOG_ASSEMBLY, std::format ("Looking for assembly stores in APK ('{}')", assembly_store_file_path.data ())); for (size_t i = 0uz; i < num_entries; i++) { if (all_required_zip_entries_found ()) { need_to_scan_more_apks = false; @@ -291,7 +298,17 @@ EmbeddedAssemblies::zip_load_assembly_store_entries (std::vector const& apk_entry->offset = state.data_offset; apk_entry->fd = state.file_fd; - log_debug (LOG_ASSEMBLY, "Found a shared library entry %s (index: %u; name: %s; hash: 0x%llx; apk offset: %u)", entry_name.get (), number_of_zip_dso_entries, name, apk_entry->name_hash, apk_entry->offset); + log_debug ( + LOG_ASSEMBLY, + std::format ( + "Found a shared library entry {} (index: {}; name: {}; hash: {:x}; apk offset: {})", + entry_name.get (), + number_of_zip_dso_entries, + name, + apk_entry->name_hash, + apk_entry->offset + ) + ); number_of_zip_dso_entries++; } } @@ -307,7 +324,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)) { Helpers::abort_application ( LOG_ASSEMBLY, - Util::monodroid_strdup_printf ( + std::format ( "Failed to read the EOCD record from APK file %s", apk_name ) @@ -322,8 +339,8 @@ EmbeddedAssemblies::zip_load_entries (int fd, const char *apk_name, [[maybe_unus if (retval < 0) { Helpers::abort_application ( LOG_ASSEMBLY, - Util::monodroid_strdup_printf ( - "Failed to seek to central directory position in APK: %s. retval=%d errno=%d, File=%s", + std::format ( + "Failed to seek to central directory position in APK: {}. retval={} errno={}, File={}", std::strerror (errno), retval, errno, @@ -353,8 +370,8 @@ EmbeddedAssemblies::zip_load_entries (int fd, const char *apk_name, [[maybe_unus if (static_cast(nread) != cd_size) { Helpers::abort_application ( LOG_ASSEMBLY, - Util::monodroid_strdup_printf ( - "Failed to read Central Directory from APK: %s. nread=%d errno=%d File=%s", + std::format ( + "Failed to read Central Directory from APK: {}. nread={} errno={} File={}", std::strerror (errno), nread, errno, @@ -394,8 +411,9 @@ EmbeddedAssemblies::set_entry_data (XamarinAndroidBundledAssembly &entry, ZipEnt log_debug ( LOG_ASSEMBLY, - "Set bundled assembly entry data. file name: '%s'; entry name: '%s'; data size: %u", - entry.file_name, entry.name, entry.data_size + std::format ("Set bundled assembly entry data. file name: '{}'; entry name: '{}'; data size: {}", + entry.file_name, entry.name, entry.data_size + ) ); } @@ -417,14 +435,14 @@ EmbeddedAssemblies::zip_read_cd_info (int fd, uint32_t& cd_offset, uint32_t& cd_ // The simplest case - no file comment off_t ret = ::lseek (fd, -ZIP_EOCD_LEN, SEEK_END); if (ret < 0) { - log_error (LOG_ASSEMBLY, "Unable to seek into the APK to find ECOD: %s (ret: %d; errno: %d)", std::strerror (errno), ret, errno); + log_error (LOG_ASSEMBLY, std::format ("Unable to seek into the APK to find ECOD: {} (ret: {}; errno: {})", std::strerror (errno), ret, errno)); return false; } std::array eocd; ssize_t nread = ::read (fd, eocd.data (), eocd.size ()); if (nread < 0 || nread != eocd.size ()) { - log_error (LOG_ASSEMBLY, "Failed to read EOCD from the APK: %s (nread: %d; errno: %d)", std::strerror (errno), nread, errno); + log_error (LOG_ASSEMBLY, std::format ("Failed to read EOCD from the APK: {} (nread: {}; errno: {})", std::strerror (errno), nread, errno)); return false; } @@ -432,7 +450,7 @@ EmbeddedAssemblies::zip_read_cd_info (int fd, uint32_t& cd_offset, uint32_t& cd_ std::array signature; if (!zip_read_field (eocd, index, signature)) { - log_error (LOG_ASSEMBLY, "Failed to read EOCD signature"); + log_error (LOG_ASSEMBLY, "Failed to read EOCD signature"sv); return false; } @@ -444,7 +462,7 @@ EmbeddedAssemblies::zip_read_cd_info (int fd, uint32_t& cd_offset, uint32_t& cd_ constexpr size_t alloc_size = 65535uz + ZIP_EOCD_LEN; // 64k is the biggest comment size allowed ret = ::lseek (fd, static_cast(-alloc_size), SEEK_END); if (ret < 0) { - log_error (LOG_ASSEMBLY, "Unable to seek into the file to find ECOD before APK comment: %s (ret: %d; errno: %d)", std::strerror (errno), ret, errno); + log_error (LOG_ASSEMBLY, std::format ("Unable to seek into the file to find ECOD before APK comment: {} (ret: {}; errno: {})", std::strerror (errno), ret, errno)); return false; } @@ -453,7 +471,7 @@ EmbeddedAssemblies::zip_read_cd_info (int fd, uint32_t& cd_offset, uint32_t& cd_ nread = ::read (fd, buf.data (), buf.size ()); if (nread < 0 || static_cast(nread) != alloc_size) { - log_error (LOG_ASSEMBLY, "Failed to read EOCD and comment from the APK: %s (nread: %d; errno: %d)", std::strerror (errno), nread, errno); + log_error (LOG_ASSEMBLY, std::format ("Failed to read EOCD and comment from the APK: {} (nread: {}; errno: {})", std::strerror (errno), nread, errno)); return false; } @@ -470,7 +488,7 @@ EmbeddedAssemblies::zip_read_cd_info (int fd, uint32_t& cd_offset, uint32_t& cd_ } if (!found) { - log_error (LOG_ASSEMBLY, "Unable to find EOCD in the APK (with comment)"); + log_error (LOG_ASSEMBLY, "Unable to find EOCD in the APK (with comment)"sv); return false; } @@ -485,7 +503,13 @@ EmbeddedAssemblies::zip_adjust_data_offset (int fd, ZipEntryLoadState &state) no off_t result = ::lseek (fd, static_cast(state.local_header_offset), SEEK_SET); if (result < 0) { - log_error (LOG_ASSEMBLY, "Failed to seek to archive entry local header at offset %u. %s (result: %d; errno: %d)", state.local_header_offset, result, errno); + log_error ( + LOG_ASSEMBLY, + std::format ( + "Failed to seek to archive entry local header at offset {}. {} (result: {}; errno: {})", + state.local_header_offset, std::strerror (errno), result, errno + ) + ); return false; } @@ -494,32 +518,32 @@ EmbeddedAssemblies::zip_adjust_data_offset (int fd, ZipEntryLoadState &state) no ssize_t nread = ::read (fd, local_header.data (), local_header.size ()); if (nread < 0 || nread != ZIP_LOCAL_LEN) { - log_error (LOG_ASSEMBLY, "Failed to read local header at offset %u: %s (nread: %d; errno: %d)", state.local_header_offset, std::strerror (errno), nread, errno); + log_error (LOG_ASSEMBLY, std::format ("Failed to read local header at offset {}: {} (nread: {}; errno: {})", state.local_header_offset, std::strerror (errno), nread, errno)); return false; } size_t index = 0; if (!zip_read_field (local_header, index, signature)) { - log_error (LOG_ASSEMBLY, "Failed to read Local Header entry signature at offset %u", state.local_header_offset); + log_error (LOG_ASSEMBLY, std::format ("Failed to read Local Header entry signature at offset {}", state.local_header_offset)); return false; } if (memcmp (signature.data (), ZIP_LOCAL_MAGIC.data (), signature.size ()) != 0) { - log_error (LOG_ASSEMBLY, "Invalid Local Header entry signature at offset %u", state.local_header_offset); + log_error (LOG_ASSEMBLY, std::format ("Invalid Local Header entry signature at offset {}", state.local_header_offset)); return false; } uint16_t file_name_length; index = LH_FILE_NAME_LENGTH_OFFSET; if (!zip_read_field (local_header, index, file_name_length)) { - log_error (LOG_ASSEMBLY, "Failed to read Local Header 'file name length' field at offset %u", (state.local_header_offset + index)); + log_error (LOG_ASSEMBLY, std::format ("Failed to read Local Header 'file name length' field at offset {}", (state.local_header_offset + index))); return false; } uint16_t extra_field_length; index = LH_EXTRA_LENGTH_OFFSET; if (!zip_read_field (local_header, index, extra_field_length)) { - log_error (LOG_ASSEMBLY, "Failed to read Local Header 'extra field length' field at offset %u", (state.local_header_offset + index)); + log_error (LOG_ASSEMBLY, std::format ("Failed to read Local Header 'extra field length' field at offset {}", (state.local_header_offset + index))); return false; } @@ -539,17 +563,17 @@ EmbeddedAssemblies::zip_extract_cd_info (std::array const& buf static_assert (BufSize >= ZIP_EOCD_LEN, "Buffer too short for EOCD"); if (!zip_read_field (buf, EOCD_TOTAL_ENTRIES_OFFSET, cd_entries)) { - log_error (LOG_ASSEMBLY, "Failed to read EOCD 'total number of entries' field"); + log_error (LOG_ASSEMBLY, "Failed to read EOCD 'total number of entries' field"sv); return false; } if (!zip_read_field (buf, EOCD_CD_START_OFFSET, cd_offset)) { - log_error (LOG_ASSEMBLY, "Failed to read EOCD 'central directory size' field"); + log_error (LOG_ASSEMBLY, "Failed to read EOCD 'central directory size' field"sv); return false; } if (!zip_read_field (buf, EOCD_CD_SIZE_OFFSET, cd_size)) { - log_error (LOG_ASSEMBLY, "Failed to read EOCD 'central directory offset' field"); + log_error (LOG_ASSEMBLY, "Failed to read EOCD 'central directory offset' field"sv); return false; } @@ -561,7 +585,7 @@ force_inline bool EmbeddedAssemblies::zip_ensure_valid_params (T const& buf, size_t index, size_t to_read) noexcept { if (index + to_read > buf.size ()) { - log_error (LOG_ASSEMBLY, "Buffer too short to read %u bytes of data", to_read); + log_error (LOG_ASSEMBLY, std::format ("Buffer too short to read {} bytes of data", to_read)); return false; } @@ -637,51 +661,51 @@ EmbeddedAssemblies::zip_read_entry_info (std::vector const& buf, dynami std::array signature; if (!zip_read_field (buf, index, signature)) { - log_error (LOG_ASSEMBLY, "Failed to read Central Directory entry signature"); + log_error (LOG_ASSEMBLY, "Failed to read Central Directory entry signature"sv); return false; } if (memcmp (signature.data (), ZIP_CENTRAL_MAGIC.data (), signature.size ()) != 0) { - log_error (LOG_ASSEMBLY, "Invalid Central Directory entry signature"); + log_error (LOG_ASSEMBLY, "Invalid Central Directory entry signature"sv); return false; } index = state.buf_offset + CD_COMPRESSION_METHOD_OFFSET; if (!zip_read_field (buf, index, state.compression_method)) { - log_error (LOG_ASSEMBLY, "Failed to read Central Directory entry 'compression method' field"); + log_error (LOG_ASSEMBLY, "Failed to read Central Directory entry 'compression method' field"sv); return false; } index = state.buf_offset + CD_UNCOMPRESSED_SIZE_OFFSET;; if (!zip_read_field (buf, index, state.file_size)) { - log_error (LOG_ASSEMBLY, "Failed to read Central Directory entry 'uncompressed size' field"); + log_error (LOG_ASSEMBLY, "Failed to read Central Directory entry 'uncompressed size' field"sv); return false; } uint16_t file_name_length; index = state.buf_offset + CD_FILENAME_LENGTH_OFFSET; if (!zip_read_field (buf, index, file_name_length)) { - log_error (LOG_ASSEMBLY, "Failed to read Central Directory entry 'file name length' field"); + log_error (LOG_ASSEMBLY, "Failed to read Central Directory entry 'file name length' field"sv); return false; } uint16_t extra_field_length; index = state.buf_offset + CD_EXTRA_LENGTH_OFFSET; if (!zip_read_field (buf, index, extra_field_length)) { - log_error (LOG_ASSEMBLY, "Failed to read Central Directory entry 'extra field length' field"); + log_error (LOG_ASSEMBLY, "Failed to read Central Directory entry 'extra field length' field"sv); return false; } uint16_t comment_length; index = state.buf_offset + CD_COMMENT_LENGTH_OFFSET; if (!zip_read_field (buf, index, comment_length)) { - log_error (LOG_ASSEMBLY, "Failed to read Central Directory entry 'file comment length' field"); + log_error (LOG_ASSEMBLY, "Failed to read Central Directory entry 'file comment length' field"sv); return false; } index = state.buf_offset + CD_LOCAL_HEADER_POS_OFFSET; if (!zip_read_field (buf, index, state.local_header_offset)) { - log_error (LOG_ASSEMBLY, "Failed to read Central Directory entry 'relative offset of local header' field"); + log_error (LOG_ASSEMBLY, "Failed to read Central Directory entry 'relative offset of local header' field"sv); return false; } index += sizeof(state.local_header_offset); @@ -689,7 +713,7 @@ EmbeddedAssemblies::zip_read_entry_info (std::vector const& buf, dynami if (file_name_length == 0) { file_name.clear (); } else if (!zip_read_field (buf, index, file_name_length, file_name)) { - log_error (LOG_ASSEMBLY, "Failed to read Central Directory entry 'file name' field"); + log_error (LOG_ASSEMBLY, "Failed to read Central Directory entry 'file name' field"sv); return false; } diff --git a/src/native/monodroid/embedded-assemblies.cc b/src/native/monodroid/embedded-assemblies.cc index db3704f160f..cf056bbb7b3 100644 --- a/src/native/monodroid/embedded-assemblies.cc +++ b/src/native/monodroid/embedded-assemblies.cc @@ -86,13 +86,13 @@ EmbeddedAssemblies::get_assembly_data (uint8_t *data, uint32_t data_size, [[mayb auto header = reinterpret_cast(data); if (header->magic == COMPRESSED_DATA_MAGIC) { if (compressed_assemblies.descriptors == nullptr) [[unlikely]] { - Helpers::abort_application (LOG_ASSEMBLY, "Compressed assembly found but no descriptor defined"); + Helpers::abort_application (LOG_ASSEMBLY, "Compressed assembly found but no descriptor defined"sv); } if (header->descriptor_index >= compressed_assemblies.count) [[unlikely]] { Helpers::abort_application ( LOG_ASSEMBLY, - Util::monodroid_strdup_printf ( - "Invalid compressed assembly descriptor index %u", + std::format ( + "Invalid compressed assembly descriptor index {}", header->descriptor_index ) ); @@ -111,8 +111,8 @@ EmbeddedAssemblies::get_assembly_data (uint8_t *data, uint32_t data_size, [[mayb if (cad.data == nullptr) [[unlikely]] { Helpers::abort_application ( LOG_ASSEMBLY, - Util::monodroid_strdup_printf ( - "Invalid compressed assembly descriptor at %u: no data", + std::format ( + "Invalid compressed assembly descriptor at {}: no data", header->descriptor_index ) ); @@ -122,15 +122,15 @@ EmbeddedAssemblies::get_assembly_data (uint8_t *data, uint32_t data_size, [[mayb if (header->uncompressed_length > cad.uncompressed_file_size) { Helpers::abort_application ( LOG_ASSEMBLY, - Util::monodroid_strdup_printf ( - "Compressed assembly '%s' is larger than when the application was built (expected at most %u, got %u). Assemblies don't grow just like that!", + std::format ( + "Compressed assembly '{}' is larger than when the application was built (expected at most {}, got {}). Assemblies don't grow just like that!", name, cad.uncompressed_file_size, header->uncompressed_length ) ); } else { - log_debug (LOG_ASSEMBLY, "Compressed assembly '%s' is smaller than when the application was built. Adjusting accordingly.", name); + log_debug (LOG_ASSEMBLY, std::format ("Compressed assembly '{}' is smaller than when the application was built. Adjusting accordingly.", name)); } cad.uncompressed_file_size = header->uncompressed_length; } @@ -141,8 +141,8 @@ EmbeddedAssemblies::get_assembly_data (uint8_t *data, uint32_t data_size, [[mayb if (ret < 0) { Helpers::abort_application ( LOG_ASSEMBLY, - Util::monodroid_strdup_printf ( - "Decompression of assembly %s failed with code %d", + std::format ( + "Decompression of assembly {} failed with code {}", name, ret ) @@ -152,8 +152,8 @@ EmbeddedAssemblies::get_assembly_data (uint8_t *data, uint32_t data_size, [[mayb if (static_cast(ret) != cad.uncompressed_file_size) { Helpers::abort_application ( LOG_ASSEMBLY, - Util::monodroid_strdup_printf ( - "Decompression of assembly %s yielded a different size (expected %lu, got %u)", + std::format ( + "Decompression of assembly {} yielded a different size (expected {}, got {})", name, cad.uncompressed_file_size, static_cast(ret) @@ -190,7 +190,7 @@ EmbeddedAssemblies::map_runtime_file (XamarinAndroidBundledAssembly& file) noexc int fd; bool close_fd; if (!AndroidSystem::is_embedded_dso_mode_enabled ()) { - log_debug (LOG_ASSEMBLY, "Mapping a runtime file from filesystem"); + log_debug (LOG_ASSEMBLY, "Mapping a runtime file from filesystem"sv); close_fd = true; // file.file_fd refers to the directory where our files live @@ -228,7 +228,7 @@ EmbeddedAssemblies::map_runtime_file (XamarinAndroidBundledAssembly& file) noexc ); if (already_mapped) { - log_debug (LOG_ASSEMBLY, "Assembly %s already mmapped by another thread, unmapping our copy", file.name); + log_debug (LOG_ASSEMBLY, std::format ("Assembly {} already mmapped by another thread, unmapping our copy", file.name)); munmap (map_info.area, file.data_size); map_info.area = nullptr; } @@ -243,8 +243,19 @@ EmbeddedAssemblies::map_runtime_file (XamarinAndroidBundledAssembly& file) noexc header[j] = isprint (p [j]) ? p [j] : '.'; header [header.size () - 1] = '\0'; - log_info_nocheck (LOG_ASSEMBLY, "file-offset: % 8x start: %08p end: %08p len: % 12i zip-entry: %s name: %s [%s]", - (int) file.data_offset, file.data, file.data + file.data_size, (int) file.data_size, file.name, file.name, header.data ()); + log_info_nocheck ( + LOG_ASSEMBLY, + std::format ( + "file-offset: {:<8x} start: {:<8p} end: {:<8p} len: {:<12} zip-entry: {} name: {} [{}]", + file.data_offset, + static_cast(file.data), + reinterpret_cast(file.data + file.data_size), + file.data_size, + file.name, + file.name, + header.data () + ) + ); } } } @@ -278,7 +289,7 @@ EmbeddedAssemblies::load_bundled_assembly ( if (strcmp (assembly.name, abi_name.get ()) != 0) { return nullptr; } else { - log_debug (LOG_ASSEMBLY, "open_from_bundles: found architecture-specific: '%s'", abi_name.get ()); + log_debug (LOG_ASSEMBLY, std::format ("open_from_bundles: found architecture-specific: '{}'", abi_name.get ())); } } @@ -312,7 +323,7 @@ EmbeddedAssemblies::load_bundled_assembly ( if (debug_file.data != nullptr) { if (debug_file.data_size > std::numeric_limits::max ()) { - log_warn (LOG_ASSEMBLY, "Debug info file '%s' is too big for Mono to consume", debug_file.name); + log_warn (LOG_ASSEMBLY, std::format ("Debug info file '{}' is too big for Mono to consume", debug_file.name)); } else { mono_debug_open_image_from_memory (image, reinterpret_cast(debug_file.data), static_cast(debug_file.data_size)); } @@ -324,7 +335,7 @@ EmbeddedAssemblies::load_bundled_assembly ( MonoImageOpenStatus status; MonoAssembly *a = mono_assembly_load_from_full (image, name.get (), &status, ref_only); if (a == nullptr || status != MonoImageOpenStatus::MONO_IMAGE_OK) { - log_warn (LOG_ASSEMBLY, "Failed to load managed assembly '%s'. %s", name.get (), mono_image_strerror (status)); + log_warn (LOG_ASSEMBLY, std::format ("Failed to load managed assembly '{}'. {}", name.get (), mono_image_strerror (status))); return nullptr; } @@ -339,7 +350,7 @@ EmbeddedAssemblies::individual_assemblies_open_from_bundles (dynamic_local_strin name.append (SharedConstants::DLL_EXTENSION); } - log_debug (LOG_ASSEMBLY, "individual_assemblies_open_from_bundles: looking for bundled name: '%s'", name.get ()); + log_debug (LOG_ASSEMBLY, std::format ("individual_assemblies_open_from_bundles: looking for bundled name: '{}'", name.get ())); dynamic_local_string abi_name; abi_name @@ -386,19 +397,19 @@ force_inline MonoAssembly* EmbeddedAssemblies::assembly_store_open_from_bundles (dynamic_local_string& name, TLoaderData loader_data, bool ref_only) noexcept { hash_t name_hash = xxhash::hash (name.get (), name.length ()); - log_debug (LOG_ASSEMBLY, "assembly_store_open_from_bundles: looking for bundled name: '%s' (hash 0x%zx)", name.get (), name_hash); + log_debug (LOG_ASSEMBLY, std::format ("assembly_store_open_from_bundles: looking for bundled name: '{}' (hash {:x})", name.get (), name_hash)); const AssemblyStoreIndexEntry *hash_entry = find_assembly_store_entry (name_hash, assembly_store_hashes, assembly_store.index_entry_count); if (hash_entry == nullptr) { - log_warn (LOG_ASSEMBLY, "Assembly '%s' (hash 0x%zx) not found", name.get (), name_hash); + log_warn (LOG_ASSEMBLY, std::format ("Assembly '{}' (hash {:x}) not found", name.get (), name_hash)); return nullptr; } if (hash_entry->descriptor_index >= assembly_store.assembly_count) { Helpers::abort_application ( LOG_ASSEMBLY, - Util::monodroid_strdup_printf ( - "Invalid assembly descriptor index %u, exceeds the maximum value of %u", + std::format ( + "Invalid assembly descriptor index {}, exceeds the maximum value of {}", hash_entry->descriptor_index, assembly_store.assembly_count - 1 ) @@ -419,15 +430,16 @@ EmbeddedAssemblies::assembly_store_open_from_bundles (dynamic_local_stringdata_size, - assembly_runtime_info.descriptor->debug_data_size, - assembly_runtime_info.descriptor->config_data_size, - name.get () + std::format ("Mapped: image_data == {:p}; debug_info_data == {:p}; config_data == {:p}; descriptor == {:p}; data size == {}; debug data size == {}; config data size == {}; name == '{}'", + static_cast(assembly_runtime_info.image_data), + static_cast(assembly_runtime_info.debug_info_data), + static_cast(assembly_runtime_info.config_data), + static_cast(assembly_runtime_info.descriptor), + assembly_runtime_info.descriptor->data_size, + assembly_runtime_info.descriptor->debug_data_size, + assembly_runtime_info.descriptor->config_data_size, + name.get () + ) ); } @@ -437,7 +449,7 @@ EmbeddedAssemblies::assembly_store_open_from_bundles (dynamic_local_string 0) { @@ -611,26 +623,26 @@ EmbeddedAssemblies::typemap_java_to_managed ([[maybe_unused]] hash_t hash, const entry = binary_search (java_type_name.get (), type_map.java_to_managed, type_map.entry_count); if (entry == nullptr) [[unlikely]] { - log_info (LOG_ASSEMBLY, "typemap: unable to find mapping to a managed type from Java type '%s'", java_type_name.get ()); + log_info (LOG_ASSEMBLY, std::format ("typemap: unable to find mapping to a managed type from Java type '{}'", java_type_name.get ())); return nullptr; } const char *managed_type_name = entry->to; if (managed_type_name == nullptr) { - log_debug (LOG_ASSEMBLY, "typemap: Java type '%s' maps either to an open generic type or an interface type.", java_type_name.get ()); + log_debug (LOG_ASSEMBLY, std::format ("typemap: Java type '{}' maps either to an open generic type or an interface type.", java_type_name.get ())); return nullptr; } - log_debug (LOG_DEFAULT, "typemap: Java type '%s' corresponds to managed type '%s'", java_type_name.get (), managed_type_name); + log_debug (LOG_DEFAULT, std::format ("typemap: Java type '{}' corresponds to managed type '{}'", java_type_name.get (), managed_type_name)); MonoType *type = mono_reflection_type_from_name (const_cast(managed_type_name), nullptr); if (type == nullptr) [[unlikely]] { - log_info (LOG_ASSEMBLY, "typemap: managed type '%s' (mapped from Java type '%s') could not be loaded", managed_type_name, java_type_name.get ()); + log_info (LOG_ASSEMBLY, std::format ("typemap: managed type '{}' (mapped from Java type '{}') could not be loaded", managed_type_name, java_type_name.get ())); return nullptr; } MonoReflectionType *ret = mono_type_get_object (Util::get_current_domain (), type); if (ret == nullptr) [[unlikely]] { - log_warn (LOG_ASSEMBLY, "typemap: unable to instantiate managed type '%s'", managed_type_name); + log_warn (LOG_ASSEMBLY, std::format ("typemap: unable to instantiate managed type '{}'", managed_type_name)); return nullptr; } @@ -650,16 +662,16 @@ EmbeddedAssemblies::typemap_java_to_managed (hash_t hash, const MonoString *java TypeMapModule *module = java_entry != nullptr && java_entry->module_index < map_module_count ? &map_modules[java_entry->module_index] : nullptr; if (module == nullptr) { if (java_entry == nullptr) { - log_info (LOG_ASSEMBLY, "typemap: unable to find mapping to a managed type from Java type '%s' (hash 0x%zx)", to_utf8 (java_type_name).get (), hash); + log_info (LOG_ASSEMBLY, std::format ("typemap: unable to find mapping to a managed type from Java type '{}' (hash {:x})", to_utf8 (java_type_name).get (), hash)); } else { - log_warn (LOG_ASSEMBLY, "typemap: mapping from Java type '%s' to managed type has invalid module index %u", to_utf8 (java_type_name).get (), java_entry->module_index); + log_warn (LOG_ASSEMBLY, std::format ("typemap: mapping from Java type '{}' to managed type has invalid module index {}", to_utf8 (java_type_name).get (), java_entry->module_index)); } return nullptr; } const TypeMapModuleEntry *entry = binary_search (java_entry->type_token_id, module->map, module->entry_count); if (entry == nullptr) { - log_info (LOG_ASSEMBLY, "typemap: unable to find mapping from Java type '%s' to managed type with token ID %u in module [%s]", to_utf8 (java_type_name).get (), java_entry->type_token_id, MonoGuidString (module->module_uuid).get ()); + log_info (LOG_ASSEMBLY, std::format ("typemap: unable to find mapping from Java type '{}' to managed type with token ID {} in module [{}]", to_utf8 (java_type_name).get (), java_entry->type_token_id, MonoGuidString (module->module_uuid).get ())); return nullptr; } @@ -667,14 +679,14 @@ EmbeddedAssemblies::typemap_java_to_managed (hash_t hash, const MonoString *java module->image = mono_image_loaded (module->assembly_name); if (module->image == nullptr) { - log_debug (LOG_ASSEMBLY, "typemap: assembly '%s' hasn't been loaded yet, attempting a full load", module->assembly_name); + log_debug (LOG_ASSEMBLY, std::format ("typemap: assembly '{}' hasn't been loaded yet, attempting a full load", module->assembly_name)); // Fake a request from MonoVM to load the assembly. MonoAssemblyName *assembly_name = mono_assembly_name_new (module->assembly_name); MonoAssembly *assm; if (assembly_name == nullptr) { - log_error (LOG_ASSEMBLY, "typemap: failed to create Mono assembly name for '%s'", module->assembly_name); + log_error (LOG_ASSEMBLY, std::format ("typemap: failed to create Mono assembly name for '{}'", module->assembly_name)); assm = nullptr; } else { MonoAssemblyLoadContextGCHandle alc_gchandle = mono_alc_get_default_gchandle (); @@ -683,22 +695,22 @@ EmbeddedAssemblies::typemap_java_to_managed (hash_t hash, const MonoString *java } if (assm == nullptr) { - log_warn (LOG_ASSEMBLY, "typemap: failed to load managed assembly '%s'", module->assembly_name); + log_warn (LOG_ASSEMBLY, std::format ("typemap: failed to load managed assembly '{}'", module->assembly_name)); } else { module->image = mono_assembly_get_image (assm); } } if (module->image == nullptr) { - log_error (LOG_ASSEMBLY, "typemap: unable to load assembly '%s' when looking up managed type corresponding to Java type '%s'", module->assembly_name, to_utf8 (java_type_name).get ()); + log_error (LOG_ASSEMBLY, std::format ("typemap: unable to load assembly '{}' when looking up managed type corresponding to Java type '{}'", module->assembly_name, to_utf8 (java_type_name).get ())); return nullptr; } } - log_debug (LOG_ASSEMBLY, "typemap: java type '%s' corresponds to managed token id %u (0x%x)", to_utf8 (java_type_name).get (), java_entry->type_token_id, java_entry->type_token_id); + log_debug (LOG_ASSEMBLY, std::format ("typemap: java type '{}' corresponds to managed token id {} ({:x})", to_utf8 (java_type_name).get (), java_entry->type_token_id, java_entry->type_token_id)); MonoClass *klass = mono_class_get (module->image, java_entry->type_token_id); if (klass == nullptr) [[unlikely]] { - log_error (LOG_ASSEMBLY, "typemap: unable to find managed type with token ID %u in assembly '%s', corresponding to Java type '%s'", java_entry->type_token_id, module->assembly_name, to_utf8 (java_type_name).get ()); + log_error (LOG_ASSEMBLY, std::format ("typemap: unable to find managed type with token ID {} in assembly '{}', corresponding to Java type '{}'", java_entry->type_token_id, module->assembly_name, to_utf8 (java_type_name).get ())); return nullptr; } @@ -709,7 +721,7 @@ EmbeddedAssemblies::typemap_java_to_managed (hash_t hash, const MonoString *java MonoReflectionType *ret = mono_type_get_object (domain, mono_class_get_type (klass)); if (ret == nullptr) { - log_warn (LOG_ASSEMBLY, "typemap: unable to instantiate managed type with token ID %u in assembly '%s', corresponding to Java type '%s'", java_entry->type_token_id, module->assembly_name, to_utf8 (java_type_name).get ()); + log_warn (LOG_ASSEMBLY, std::format ("typemap: unable to instantiate managed type with token ID {} in assembly '{}', corresponding to Java type '{}'", java_entry->type_token_id, module->assembly_name, to_utf8 (java_type_name).get ())); return nullptr; } @@ -727,7 +739,7 @@ EmbeddedAssemblies::typemap_java_to_managed (MonoString *java_type) noexcept } if (java_type == nullptr) [[unlikely]]{ - log_warn (LOG_ASSEMBLY, "typemap: null 'java_type' passed to 'typemap_java_to_managed'"); + log_warn (LOG_ASSEMBLY, "typemap: null 'java_type' passed to 'typemap_java_to_managed'"sv); return nullptr; } @@ -735,7 +747,7 @@ EmbeddedAssemblies::typemap_java_to_managed (MonoString *java_type) noexcept // number of bytes. int name_len = mono_string_length (java_type) << 1; if (name_len <= 0) [[unlikely]] { - log_warn (LOG_ASSEMBLY, "typemap: empty 'java_type' passed to 'typemap_java_to_managed'"); + log_warn (LOG_ASSEMBLY, "typemap: empty 'java_type' passed to 'typemap_java_to_managed'"sv); return nullptr; } @@ -774,7 +786,7 @@ EmbeddedAssemblies::typemap_managed_to_java ([[maybe_unused]] MonoType *type, Mo const TypeMapEntry *entry = typemap_managed_to_java (full_name.get ()); if (entry == nullptr) [[unlikely]] { - log_info (LOG_ASSEMBLY, "typemap: unable to find mapping to a Java type from managed type '%s'", full_name.get ()); + log_info (LOG_ASSEMBLY, std::format ("typemap: unable to find mapping to a Java type from managed type '{}'", full_name.get ())); return nullptr; } @@ -793,58 +805,59 @@ EmbeddedAssemblies::typemap_managed_to_java ([[maybe_unused]] MonoType *type, Mo const TypeMapModule *match = mvid != nullptr ? binary_search (mvid, map_modules, map_module_count) : nullptr; if (match == nullptr) { if (mvid == nullptr) { - log_warn (LOG_ASSEMBLY, "typemap: no mvid specified in call to typemap_managed_to_java"); + log_warn (LOG_ASSEMBLY, "typemap: no mvid specified in call to typemap_managed_to_java"sv); } else { - log_info (LOG_ASSEMBLY, "typemap: module matching MVID [%s] not found.", MonoGuidString (mvid).get ()); + log_info (LOG_ASSEMBLY, std::format ("typemap: module matching MVID [{}] not found.", MonoGuidString (mvid).get ())); } return nullptr; } uint32_t token = mono_class_get_type_token (klass); - log_debug (LOG_ASSEMBLY, "typemap: MVID [%s] maps to assembly %s, looking for token %d (0x%x), table index %d", MonoGuidString (mvid).get (), match->assembly_name, token, token, token & 0x00FFFFFF); + log_debug (LOG_ASSEMBLY, std::format ("typemap: MVID [{}] maps to assembly {}, looking for token {} ({:x}), table index {}", MonoGuidString (mvid).get (), match->assembly_name, token, token, token & 0x00FFFFFF)); // Each map entry is a pair of 32-bit integers: [TypeTokenID][JavaMapArrayIndex] const TypeMapModuleEntry *entry = match->map != nullptr ? binary_search (token, match->map, match->entry_count) : nullptr; if (entry == nullptr) { if (match->map == nullptr) { - log_warn (LOG_ASSEMBLY, "typemap: module with mvid [%s] has no associated type map.", MonoGuidString (mvid).get ()); + log_warn (LOG_ASSEMBLY, std::format ("typemap: module with MVID [{}] has no associated type map.", MonoGuidString (mvid).get ())); return nullptr; } if (match->duplicate_count > 0 && match->duplicate_map != nullptr) { - log_debug (LOG_ASSEMBLY, "typemap: searching module [%s] duplicate map for token %u (0x%x)", MonoGuidString (mvid).get (), token, token); + log_debug (LOG_ASSEMBLY, std::format ("typemap: searching module [{}] duplicate map for token {} ({:x})", MonoGuidString (mvid).get (), token, token)); entry = binary_search (token, match->duplicate_map, match->duplicate_count); } if (entry == nullptr) { - log_info (LOG_ASSEMBLY, "typemap: type with token %d (0x%x) in module {%s} (%s) not found.", token, token, MonoGuidString (mvid).get (), match->assembly_name); + log_info (LOG_ASSEMBLY, std::format ("typemap: type with token {} ({:x}) in module [{}] ({}) not found.", token, token, MonoGuidString (mvid).get (), match->assembly_name)); return nullptr; } } if (entry->java_map_index >= java_type_count) [[unlikely]] { - log_warn (LOG_ASSEMBLY, "typemap: type with token %d (0x%x) in module {%s} (%s) has invalid Java type index %u", token, token, MonoGuidString (mvid).get (), match->assembly_name, entry->java_map_index); + log_warn (LOG_ASSEMBLY, std::format ("typemap: type with token {} ({:x}) in module [{}] ({}) has invalid Java type index {}", token, token, MonoGuidString (mvid).get (), match->assembly_name, entry->java_map_index)); return nullptr; } TypeMapJava const& java_entry = map_java[entry->java_map_index]; if (java_entry.java_name_index >= java_type_count) [[unlikely]] { - log_warn (LOG_ASSEMBLY, "typemap: type with token %d (0x%x) in module {%s} (%s) points to invalid Java type at index %u (invalid type name index %u)", token, token, MonoGuidString (mvid).get (), match->assembly_name, entry->java_map_index, java_entry.java_name_index); + log_warn (LOG_ASSEMBLY, std::format ("typemap: type with token {} ({:x}) in module [{}] ({}) points to invalid Java type at index {} (invalid type name index {})", token, token, MonoGuidString (mvid).get (), match->assembly_name, entry->java_map_index, java_entry.java_name_index)); return nullptr; } const char *ret = java_type_names[java_entry.java_name_index]; if (ret == nullptr) [[unlikely]] { - log_warn (LOG_ASSEMBLY, "typemap: empty Java type name returned for entry at index %u", entry->java_map_index); + log_warn (LOG_ASSEMBLY, std::format ("typemap: empty Java type name returned for entry at index {}", entry->java_map_index)); } log_debug ( LOG_ASSEMBLY, - "typemap: type with token %d (0x%x) in module {%s} (%s) corresponds to Java type '%s'", - token, - token, - MonoGuidString (mvid).get (), - match->assembly_name, - ret + std::format ("typemap: type with token {} ({:x}) in module [{}] ({}) corresponds to Java type '{}'", + token, + token, + MonoGuidString (mvid).get (), + match->assembly_name, + ret + ) ); return ret; @@ -862,7 +875,7 @@ EmbeddedAssemblies::typemap_managed_to_java (MonoReflectionType *reflection_type MonoType *type = mono_reflection_type_get_type (reflection_type); if (type == nullptr) { - log_warn (LOG_ASSEMBLY, "Failed to map reflection type to MonoType"); + log_warn (LOG_ASSEMBLY, "Failed to map reflection type to MonoType"sv); return nullptr; } @@ -891,8 +904,8 @@ EmbeddedAssemblies::md_mmap_apk_file (int fd, uint32_t offset, size_t size, cons if (mmap_info.area == MAP_FAILED) { Helpers::abort_application ( LOG_ASSEMBLY, - Util::monodroid_strdup_printf ( - "Could not mmap APK fd %d: %s; File=%s", + std::format ( + "Could not mmap APK fd {}: {}; File={}", fd, strerror (errno), filename @@ -904,9 +917,19 @@ EmbeddedAssemblies::md_mmap_apk_file (int fd, uint32_t offset, size_t size, cons file_info.area = (void*)((const char*)mmap_info.area + offsetFromPage); file_info.size = size; - log_info (LOG_ASSEMBLY, " mmap_start: %08p mmap_end: %08p mmap_len: % 12u file_start: %08p file_end: %08p file_len: % 12u apk descriptor: %d file: %s", - mmap_info.area, reinterpret_cast (mmap_info.area) + mmap_info.size, mmap_info.size, - file_info.area, reinterpret_cast (file_info.area) + file_info.size, file_info.size, fd, filename); + log_info ( + LOG_ASSEMBLY, + std::format (" mmap_start: {:<8p}; mmap_end: {:<8p} mmap_len: {:<12} file_start: {:<8p} file_end: {:<8p} file_len: {:<12} apk descriptor: {} file: {}", + mmap_info.area, + reinterpret_cast(reinterpret_cast (mmap_info.area) + mmap_info.size), + mmap_info.size, + file_info.area, + reinterpret_cast(reinterpret_cast (file_info.area) + file_info.size), + file_info.size, + fd, + filename + ) + ); return file_info; } @@ -919,13 +942,13 @@ EmbeddedAssemblies::gather_bundled_assemblies_from_apk (const char* apk, monodro if ((fd = open (apk, O_RDONLY)) < 0) { Helpers::abort_application ( LOG_ASSEMBLY, - Util::monodroid_strdup_printf ( - "ERROR: Unable to load application package %s.", + std::format ( + "ERROR: Unable to load application package {}.", apk ) ); } - log_debug (LOG_ASSEMBLY, "APK %s FD: %d", apk, fd); + log_debug (LOG_ASSEMBLY, std::format ("APK {} FD: {}", apk, fd)); zip_load_entries (fd, apk, should_register); } @@ -952,40 +975,40 @@ EmbeddedAssemblies::typemap_read_header ([[maybe_unused]] int dir_fd, const char struct stat sbuf; int res = fstatat (dir_fd, file_path, &sbuf, 0); if (res < 0) { - log_error (LOG_ASSEMBLY, "typemap: failed to stat %s file '%s/%s': %s", file_type, dir_path, file_path, strerror (errno)); + log_error (LOG_ASSEMBLY, std::format ("typemap: failed to stat {} file '{}/{}': {}", file_type, dir_path, file_path, strerror (errno))); return false; } file_size = static_cast(sbuf.st_size); if (file_size < sizeof (header)) { - log_error (LOG_ASSEMBLY, "typemap: %s file '%s/%s' is too small (must be at least %u bytes)", file_type, dir_path, file_path, sizeof (header)); + log_error (LOG_ASSEMBLY, std::format ("typemap: {} file '{}/{}' is too small (must be at least {} bytes)", file_type, dir_path, file_path, sizeof (header))); return false; } fd = openat (dir_fd, file_path, O_RDONLY); if (fd < 0) { - log_error (LOG_ASSEMBLY, "typemap: failed to open %s file %s/%s for reading: %s", file_type, dir_path, file_path, strerror (errno)); + log_error (LOG_ASSEMBLY, std::format ("typemap: failed to open {} file {}/{} for reading: {}", file_type, dir_path, file_path, strerror (errno))); return false; } ssize_t nread = do_read (fd, &header, sizeof (header)); if (nread <= 0) { if (nread < 0) { - log_error (LOG_ASSEMBLY, "typemap: failed to read %s file header from '%s/%s': %s", file_type, dir_path, file_path, strerror (errno)); + log_error (LOG_ASSEMBLY, std::format ("typemap: failed to read {} file header from '{}/{}': {}", file_type, dir_path, file_path, strerror (errno))); } else { - log_error (LOG_ASSEMBLY, "typemap: end of file while reading %s file header from '%s/%s'", file_type, dir_path, file_path); + log_error (LOG_ASSEMBLY, std::format ("typemap: end of file while reading {} file header from '{}/{}'", file_type, dir_path, file_path)); } return false; } if (header.magic != expected_magic) { - log_error (LOG_ASSEMBLY, "typemap: invalid magic value in the %s file header from '%s/%s': expected 0x%X, got 0x%X", file_type, dir_path, file_path, expected_magic, header.magic); + log_error (LOG_ASSEMBLY, std::format ("typemap: invalid magic value in the {} file header from '{}/{}': expected {:x}, got {:x}", file_type, dir_path, file_path, expected_magic, header.magic)); return false; } if (header.version != MODULE_FORMAT_VERSION) { - log_error (LOG_ASSEMBLY, "typemap: incompatible %s format version. This build supports only version %u, file '%s/%s' uses version %u", file_type, MODULE_FORMAT_VERSION, dir_path, file_path, header.version); + log_error (LOG_ASSEMBLY, std::format ("typemap: incompatible {} format version. This build supports only version {}, file '{}/{}' uses version {}", file_type, MODULE_FORMAT_VERSION, dir_path, file_path, header.version)); return false; } @@ -998,14 +1021,14 @@ EmbeddedAssemblies::typemap_load_index (TypeMapIndexHeader &header, size_t file_ size_t entry_size = header.module_file_name_width; size_t data_size = entry_size * type_map_count; if (sizeof(header) + data_size > file_size) { - log_error (LOG_ASSEMBLY, "typemap: index file is too small, expected %u, found %u bytes", data_size + sizeof(header), file_size); + log_error (LOG_ASSEMBLY, std::format ("typemap: index file is too small, expected {}, found {} bytes", data_size + sizeof(header), file_size)); return nullptr; } auto data = std::make_unique (data_size); ssize_t nread = do_read (index_fd, data.get (), data_size); if (nread != static_cast(data_size)) { - log_error (LOG_ASSEMBLY, "typemap: failed to read %u bytes from index file. %s", data_size, strerror (errno)); + log_error (LOG_ASSEMBLY, std::format ("typemap: failed to read {} bytes from index file. {}", data_size, strerror (errno))); return nullptr; } @@ -1021,7 +1044,7 @@ EmbeddedAssemblies::typemap_load_index (TypeMapIndexHeader &header, size_t file_ std::unique_ptr EmbeddedAssemblies::typemap_load_index (int dir_fd, const char *dir_path, const char *index_path) { - log_debug (LOG_ASSEMBLY, "typemap: loading TypeMap index file '%s/%s'", dir_path, index_path); + log_debug (LOG_ASSEMBLY, std::format ("typemap: loading TypeMap index file '{}/{}'", dir_path, index_path)); TypeMapIndexHeader header; size_t file_size; @@ -1048,7 +1071,7 @@ EmbeddedAssemblies::typemap_load_file (BinaryTypeMapHeader &header, const char * ssize_t nread = do_read (file_fd, module.assembly_name, header.assembly_name_length); if (nread != static_cast(header.assembly_name_length)) { - log_error (LOG_ASSEMBLY, "tyemap: failed to read map assembly name from '%s/%s': %s", dir_path, file_path, strerror (errno)); + log_error (LOG_ASSEMBLY, std::format ("typemap: failed to read map assembly name from '{}/{}': {}", dir_path, file_path, strerror (errno))); return false; } @@ -1057,8 +1080,16 @@ EmbeddedAssemblies::typemap_load_file (BinaryTypeMapHeader &header, const char * log_debug ( LOG_ASSEMBLY, - "typemap: '%s/%s':: entry count == %u; Java name field width == %u; Managed name width == %u; assembly name length == %u; assembly name == %s", - dir_path, file_path, header.entry_count, header.java_name_width, header.managed_name_width, header.assembly_name_length, module.assembly_name + std::format ( + "typemap: '{}/{}':: entry count == {}; Java name field width == {}; Managed name width == {}; assembly name length == {}; assembly name == {}", + dir_path, + file_path, + header.entry_count, + header.java_name_width, + header.managed_name_width, + header.assembly_name_length, + module.assembly_name + ) ); // [name][index] @@ -1072,7 +1103,7 @@ EmbeddedAssemblies::typemap_load_file (BinaryTypeMapHeader &header, const char * module.data = new uint8_t [data_size]; nread = do_read (file_fd, module.data, data_size); if (nread != static_cast(data_size)) { - log_error (LOG_ASSEMBLY, "tyemap: failed to read map data from '%s/%s': %s", dir_path, file_path, strerror (errno)); + log_error (LOG_ASSEMBLY, std::format ("typemap: failed to read map data from '{}/{}': {}", dir_path, file_path, strerror (errno))); return false; } @@ -1116,7 +1147,7 @@ EmbeddedAssemblies::typemap_load_file (BinaryTypeMapHeader &header, const char * bool EmbeddedAssemblies::typemap_load_file (int dir_fd, const char *dir_path, const char *file_path, TypeMap &module) { - log_debug (LOG_ASSEMBLY, "typemap: loading TypeMap file '%s/%s'", dir_path, file_path); + log_debug (LOG_ASSEMBLY, std::format ("typemap: loading TypeMap file '{}/{}'", dir_path, file_path)); bool ret = true; BinaryTypeMapHeader header; @@ -1155,7 +1186,7 @@ EmbeddedAssemblies::register_from_apk (const char *apk_file, monodroid_should_re gather_bundled_assemblies_from_apk (apk_file, should_register); - log_info (LOG_ASSEMBLY, "Package '%s' contains %i assemblies", apk_file, number_of_found_assemblies - prev); + log_info (LOG_ASSEMBLY, std::format ("Package '{}' contains {} assemblies", apk_file, number_of_found_assemblies - prev)); return number_of_found_assemblies; } @@ -1259,10 +1290,10 @@ EmbeddedAssemblies::maybe_register_blob_from_filesystem ( force_inline size_t EmbeddedAssemblies::register_from_filesystem (const char *lib_dir_path,bool look_for_mangled_names, monodroid_should_register should_register) noexcept { - log_debug (LOG_ASSEMBLY, "Looking for assemblies in '%s'", lib_dir_path); + log_debug (LOG_ASSEMBLY, std::format ("Looking for assemblies in '{}'", lib_dir_path)); DIR *lib_dir = opendir (lib_dir_path); // TODO: put it in a scope guard at some point if (lib_dir == nullptr) { - log_warn (LOG_ASSEMBLY, "Unable to open app library directory '%s': %s", lib_dir_path, std::strerror (errno)); + log_warn (LOG_ASSEMBLY, std::format ("Unable to open app library directory '{}': {}", lib_dir_path, std::strerror (errno))); return 0; } @@ -1271,14 +1302,14 @@ EmbeddedAssemblies::register_from_filesystem (const char *lib_dir_path,bool look int dir_fd = dirfd (lib_dir); if (dir_fd < 0) [[unlikely]] { - log_warn (LOG_ASSEMBLY, "Unable to obtain file descriptor for directory '%s': %s", lib_dir_path, std::strerror (errno)); + log_warn (LOG_ASSEMBLY, std::format ("Unable to obtain file descriptor for directory '{}': {}", lib_dir_path, std::strerror (errno))); closedir (lib_dir); return 0; } state.file_fd = dup (dir_fd); if (state.file_fd < 0) [[unlikely]] { - log_warn (LOG_ASSEMBLY, "Unable to duplicate file descriptor %d for directory '%s': %s", dir_fd, lib_dir_path, std::strerror (errno)); + log_warn (LOG_ASSEMBLY, std::format ("Unable to duplicate file descriptor {} for directory '{}': {}", dir_fd, lib_dir_path, std::strerror (errno))); closedir (lib_dir); return 0; } @@ -1295,7 +1326,7 @@ EmbeddedAssemblies::register_from_filesystem (const char *lib_dir_path,bool look dirent *cur = readdir (lib_dir); if (cur == nullptr) { if (errno != 0) { - log_warn (LOG_ASSEMBLY, "Failed to open a directory entry from '%s': %s", lib_dir_path, std::strerror (errno)); + log_warn (LOG_ASSEMBLY, std::format ("Failed to open a directory entry from '{}': {}", lib_dir_path, std::strerror (errno))); continue; // keep going, no harm } break; // No more entries, we're done @@ -1315,7 +1346,7 @@ EmbeddedAssemblies::register_from_filesystem (const char *lib_dir_path,bool look // ...and we can handle the runtime config entry if (!runtime_config_blob_found && std::strncmp (cur->d_name, SharedConstants::RUNTIME_CONFIG_BLOB_NAME.data (), SharedConstants::RUNTIME_CONFIG_BLOB_NAME.size ()) == 0) { - log_debug (LOG_ASSEMBLY, "Mapping runtime config blob from '%s'", cur->d_name); + log_debug (LOG_ASSEMBLY, std::format ("Mapping runtime config blob from '{}'", cur->d_name)); auto file_size = Util::get_file_size_at (state.file_fd, cur->d_name); if (!file_size) { continue; @@ -1344,7 +1375,7 @@ EmbeddedAssemblies::register_from_filesystem (const char *lib_dir_path,bool look size_t EmbeddedAssemblies::register_from_filesystem (monodroid_should_register should_register) noexcept { - log_debug (LOG_ASSEMBLY, "Registering assemblies from the filesystem"); + log_debug (LOG_ASSEMBLY, "Registering assemblies from the filesystem"sv); constexpr bool LookForMangledNames = true; size_t assembly_count = register_from_filesystem ( AndroidSystem::app_lib_directories[0], @@ -1362,6 +1393,6 @@ EmbeddedAssemblies::register_from_filesystem (monodroid_should_register should_r ); #endif - log_debug (LOG_ASSEMBLY, "Found %zu assemblies on the filesystem", assembly_count); + log_debug (LOG_ASSEMBLY, std::format ("Found {} assemblies on the filesystem", assembly_count)); return assembly_count; } diff --git a/src/native/monodroid/embedded-assemblies.hh b/src/native/monodroid/embedded-assemblies.hh index ff153942724..21fc0de80b8 100644 --- a/src/native/monodroid/embedded-assemblies.hh +++ b/src/native/monodroid/embedded-assemblies.hh @@ -20,6 +20,7 @@ #include #include "archive-dso-stub-config.hh" +#include "log_types.hh" #include "strings.hh" #include "xamarin-app.hh" #include "cpp-util.hh" @@ -309,7 +310,7 @@ namespace xamarin::android::internal { elf_header->e_ident[EI_MAG1] != ELFMAG1 || elf_header->e_ident[EI_MAG2] != ELFMAG2 || elf_header->e_ident[EI_MAG3] != ELFMAG3) { - log_debug (LOG_ASSEMBLY, "Not an ELF image: %s", file_name); + log_debug (LOG_ASSEMBLY, std::format ("Not an ELF image: {}", file_name)); // Not an ELF image, just return what we mmapped before return { map_info.area, map_info.size }; } @@ -328,7 +329,7 @@ namespace xamarin::android::internal { static void store_mapped_runtime_config_data (md_mmap_info const& map_info, const char *file_name) noexcept { auto [payload_start, payload_size] = get_wrapper_dso_payload_pointer_and_size (map_info, file_name); - log_debug (LOG_ASSEMBLY, "Runtime config: payload pointer %p ; size %zu", payload_start, payload_size); + log_debug (LOG_ASSEMBLY, std::format ("Runtime config: payload pointer {:p} ; size {}", payload_start, payload_size)); runtime_config_data = payload_start; runtime_config_data_size = payload_size; runtime_config_blob_found = true; @@ -430,7 +431,7 @@ namespace xamarin::android::internal { } } } - log_debug (LOG_ASSEMBLY, "Unmangled name to '%s'", name.get ()); + log_debug (LOG_ASSEMBLY, std::format ("Unmangled name to '{}'", name.get ())); }; private: diff --git a/src/native/shared/CMakeLists.txt b/src/native/shared/CMakeLists.txt index 4a3bb7ece18..75f4b0c4616 100644 --- a/src/native/shared/CMakeLists.txt +++ b/src/native/shared/CMakeLists.txt @@ -4,7 +4,6 @@ set(LIB_ALIAS xa::shared) set(XA_SHARED_SOURCES helpers.cc log_functions.cc - new_delete.cc ) add_clang_check_sources("${XA_SHARED_SOURCES};") diff --git a/src/native/shared/helpers.hh b/src/native/shared/helpers.hh index 3c6c16ca6a3..3a2bc67dfb5 100644 --- a/src/native/shared/helpers.hh +++ b/src/native/shared/helpers.hh @@ -3,9 +3,14 @@ #include #include +#include +#include #include #include "platform-compat.hh" +#include "log_types.hh" + +using namespace std::string_view_literals; namespace xamarin::android { @@ -46,10 +51,30 @@ namespace xamarin::android [[noreturn]] static void abort_application (LogCategories category, const char *message, bool log_location = true, std::source_location sloc = std::source_location::current ()) noexcept; + [[noreturn]] static void abort_application (LogCategories category, std::string const& message, bool log_location = true, std::source_location sloc = std::source_location::current ()) noexcept + { + abort_application (category, message.c_str (), log_location, sloc); + } + + [[noreturn]] static void abort_application (LogCategories category, std::string_view const& message, bool log_location = true, std::source_location sloc = std::source_location::current ()) noexcept + { + abort_application (category, message.data (), log_location, sloc); + } + [[noreturn]] static void abort_application (const char *message, bool log_location = true, std::source_location sloc = std::source_location::current ()) noexcept { abort_application (LOG_DEFAULT, message, log_location, sloc); } + + [[noreturn]] static void abort_application (std::string const& message, bool log_location = true, std::source_location sloc = std::source_location::current ()) noexcept + { + abort_application (LOG_DEFAULT, message.c_str (), log_location, sloc); + } + + [[noreturn]] static void abort_application (std::string_view const& message, bool log_location = true, std::source_location sloc = std::source_location::current ()) noexcept + { + abort_application (LOG_DEFAULT, message.data (), log_location, sloc); + } }; } #endif // __HELPERS_HH diff --git a/src/native/shared/log_types.hh b/src/native/shared/log_types.hh index b0ed20018d9..f6fb1142597 100644 --- a/src/native/shared/log_types.hh +++ b/src/native/shared/log_types.hh @@ -2,10 +2,34 @@ #define LOG_LEVEL_HH #include +#include +#include +#include #include "java-interop-logger.h" +// We redeclare macros as real functions here +#if defined(DO_LOG) +#undef DO_LOG +#endif + +#if defined(log_debug) +#undef log_debug +#endif + +#if defined(log_info) +#undef log_info +#endif + namespace xamarin::android { + namespace detail { + [[gnu::always_inline]] + static inline bool _category_is_enabled (LogCategories category) noexcept + { + return (log_categories & category) == category; + } + } + enum class LogTimingCategories : uint32_t { Default = 0, @@ -30,6 +54,109 @@ namespace xamarin::android { // A slightly faster alternative to other log functions as it doesn't parse the message // for format placeholders nor it uses variable arguments void log_write (LogCategories category, LogLevel level, const char *message) noexcept; + + template [[gnu::always_inline]] + static inline constexpr void log_debug (LogCategories category, const char *format, Args&& ...args) noexcept + { + if (detail::_category_is_enabled (category)) { + ::log_debug_nocheck (category, format, std::forward(args)...); + } + } + + template [[gnu::always_inline]] + static inline constexpr void log_debug (LogCategories category, std::string_view const& format, Args&& ...args) noexcept + { + if (detail::_category_is_enabled (category)) { + ::log_debug_nocheck (category, format.data (), std::forward(args)...); + } + } + + static inline constexpr void log_debug (LogCategories category, std::string const& message) noexcept + { + if (detail::_category_is_enabled (category)) { + ::log_debug_nocheck (category, message.c_str ()); + } + } + + // + // This will be enabled once all log_* calls are converted to std::format format + // + // template [[gnu::always_inline]] + // static inline constexpr void log_debug (LogCategories category, std::format_string fmt, Args&& ...args) + // { + // if (detail::_category_is_enabled (category)) { + + // log_debug_nocheck (category, std::format (fmt, std::forward(args)...).c_str ()); + // } + // } + + template [[gnu::always_inline]] + static inline constexpr void log_info (LogCategories category, const char *format, Args&& ...args) noexcept + { + if (detail::_category_is_enabled (category)) { + ::log_info_nocheck (category, format, std::forward(args)...); + } + } + + template [[gnu::always_inline]] + static inline constexpr void log_info (LogCategories category, std::string_view const& format, Args&& ...args) noexcept + { + if (detail::_category_is_enabled (category)) { + ::log_info_nocheck (category, format.data (), std::forward(args)...); + } + } + + [[gnu::always_inline]] + static inline constexpr void log_info (LogCategories category, std::string const& message) noexcept + { + if (detail::_category_is_enabled (category)) { + ::log_info_nocheck (category, message.c_str ()); + } + } + + [[gnu::always_inline]] + static inline constexpr void log_info_nocheck (LogCategories category, std::string const& message) noexcept + { + if (detail::_category_is_enabled (category)) { + ::log_info_nocheck (category, message.c_str ()); + } + } + + [[gnu::always_inline]] + static inline constexpr void log_warn (LogCategories category, std::string const& message) noexcept + { + ::log_warn (category, message.c_str ()); + } + + [[gnu::always_inline]] + static inline constexpr void log_warn (LogCategories category, std::string_view const& message) noexcept + { + ::log_warn (category, message.data ()); + } + + [[gnu::always_inline]] + static inline constexpr void log_error (LogCategories category, std::string const& message) noexcept + { + ::log_error (category, message.c_str ()); + } + + [[gnu::always_inline]] + static inline constexpr void log_error (LogCategories category, std::string_view const& message) noexcept + { + ::log_error (category, message.data ()); + } + + [[gnu::always_inline]] + static inline constexpr void log_fatal (LogCategories category, std::string const& message) noexcept + { + ::log_fatal (category, message.c_str ()); + } + + [[gnu::always_inline]] + static inline constexpr void log_fatal (LogCategories category, std::string_view const& message) noexcept + { + ::log_fatal (category, message.data ()); + } } extern unsigned int log_categories; #endif // ndef LOG_LEVEL_HH diff --git a/src/native/shared/new_delete.cc b/src/native/shared/new_delete.cc deleted file mode 100644 index 2293dddca10..00000000000 --- a/src/native/shared/new_delete.cc +++ /dev/null @@ -1,87 +0,0 @@ -#include - -#include "helpers.hh" - -namespace std -{ - struct nothrow_t {}; - extern const nothrow_t nothrow; -} - -#include "java-interop-util.h" - -static void* -do_alloc (size_t size) -{ - return ::malloc (size == 0 ? 1 : size); -} - -__attribute__((__weak__)) -void* -operator new (size_t size) -{ - void* p = do_alloc (size); - if (p == nullptr) { - xamarin::android::Helpers::abort_application ("Out of memory in the `new` operator"); - } - - return p; -} - -void* -operator new (size_t size, const std::nothrow_t&) noexcept -{ - return do_alloc (size); -} - -__attribute__((__weak__)) -void* -operator new[] (size_t size) -{ - return ::operator new (size); -} - -void* -operator new[] (size_t size, const std::nothrow_t&) noexcept -{ - return do_alloc (size); -} - -__attribute__((__weak__)) -void -operator delete (void* ptr) noexcept -{ - if (ptr) - ::free (ptr); -} - -void -operator delete (void* ptr, const std::nothrow_t&) -{ - ::operator delete (ptr); -} - -void -operator delete (void* ptr, size_t) noexcept -{ - ::operator delete (ptr); -} - -__attribute__((__weak__)) -void -operator delete[] (void* ptr) noexcept -{ - ::operator delete (ptr); -} - -void -operator delete[] (void* ptr, const std::nothrow_t&) noexcept -{ - ::operator delete[] (ptr); -} - -void -operator delete[] (void* ptr, size_t) noexcept -{ - ::operator delete[] (ptr); -} From 15ace79634063c8614d7bd47f2b905a3627a7622 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Tue, 26 Nov 2024 22:55:24 +0100 Subject: [PATCH 16/54] A bit less of reinterpret_cast<> --- src/native/monodroid/embedded-assemblies.cc | 18 +++++++++--------- src/native/shared/helpers.hh | 12 ++++++++++++ 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/src/native/monodroid/embedded-assemblies.cc b/src/native/monodroid/embedded-assemblies.cc index cf056bbb7b3..d03e99cc44e 100644 --- a/src/native/monodroid/embedded-assemblies.cc +++ b/src/native/monodroid/embedded-assemblies.cc @@ -135,7 +135,7 @@ EmbeddedAssemblies::get_assembly_data (uint8_t *data, uint32_t data_size, [[mayb cad.uncompressed_file_size = header->uncompressed_length; } - const char *data_start = reinterpret_cast(data + sizeof(CompressedAssemblyHeader)); + const char *data_start = pointer_add(data, sizeof(CompressedAssemblyHeader)); int ret = LZ4_decompress_safe (data_start, reinterpret_cast(cad.data), static_cast(assembly_data_size), static_cast(cad.uncompressed_file_size)); if (ret < 0) { @@ -249,7 +249,7 @@ EmbeddedAssemblies::map_runtime_file (XamarinAndroidBundledAssembly& file) noexc "file-offset: {:<8x} start: {:<8p} end: {:<8p} len: {:<12} zip-entry: {} name: {} [{}]", file.data_offset, static_cast(file.data), - reinterpret_cast(file.data + file.data_size), + pointer_add (file.data, file.data_size), file.data_size, file.name, file.name, @@ -560,7 +560,7 @@ EmbeddedAssemblies::binary_search (const Key *key, const Entry *base, size_t nme while (nmemb > 0) { const Entry *ret; if constexpr (use_precalculated_size) { - ret = reinterpret_cast(reinterpret_cast(base) + (precalculated_size * (nmemb / 2))); + ret = pointer_add(reinterpret_cast(base), precalculated_size * (nmemb / 2)); } else { ret = base + (nmemb / 2); } @@ -570,7 +570,7 @@ EmbeddedAssemblies::binary_search (const Key *key, const Entry *base, size_t nme nmemb /= 2; } else if (result > 0) { if constexpr (use_precalculated_size) { - base = reinterpret_cast(reinterpret_cast(ret) + precalculated_size); + base = pointer_add(reinterpret_cast(ret), precalculated_size); } else { base = ret + 1; } @@ -914,17 +914,17 @@ EmbeddedAssemblies::md_mmap_apk_file (int fd, uint32_t offset, size_t size, cons } mmap_info.size = offsetSize; - file_info.area = (void*)((const char*)mmap_info.area + offsetFromPage); + file_info.area = pointer_add (mmap_info.area, offsetFromPage); file_info.size = size; log_info ( LOG_ASSEMBLY, std::format (" mmap_start: {:<8p}; mmap_end: {:<8p} mmap_len: {:<12} file_start: {:<8p} file_end: {:<8p} file_len: {:<12} apk descriptor: {} file: {}", mmap_info.area, - reinterpret_cast(reinterpret_cast (mmap_info.area) + mmap_info.size), + pointer_add (mmap_info.area, mmap_info.size), mmap_info.size, file_info.area, - reinterpret_cast(reinterpret_cast (file_info.area) + file_info.size), + pointer_add (file_info.area, file_info.size), file_info.size, fd, filename @@ -1126,7 +1126,7 @@ EmbeddedAssemblies::typemap_load_file (BinaryTypeMapHeader &header, const char * // integer from unaligned memory memcpy (&idx, java_pos + header.java_name_width, sizeof (idx)); if (idx < INVALID_TYPE_INDEX) { - cur->to = reinterpret_cast(managed_start + (managed_entry_size * idx)); + cur->to = pointer_add(managed_start, managed_entry_size * idx); } else { // Ignore the type mapping cur->to = nullptr; @@ -1137,7 +1137,7 @@ EmbeddedAssemblies::typemap_load_file (BinaryTypeMapHeader &header, const char * cur->from = reinterpret_cast(managed_pos); memcpy (&idx, managed_pos + header.managed_name_width, sizeof (idx)); - cur->to = reinterpret_cast(java_start + (java_entry_size * idx)); + cur->to = pointer_add(java_start, java_entry_size * idx); managed_pos += managed_entry_size; } diff --git a/src/native/shared/helpers.hh b/src/native/shared/helpers.hh index 3a2bc67dfb5..078da3afac0 100644 --- a/src/native/shared/helpers.hh +++ b/src/native/shared/helpers.hh @@ -2,6 +2,7 @@ #define __HELPERS_HH #include +#include #include #include #include @@ -14,6 +15,11 @@ using namespace std::string_view_literals; namespace xamarin::android { + namespace detail { + template + concept TPointer = requires { std::is_pointer_v; }; + } + class [[gnu::visibility("hidden")]] Helpers { public: @@ -76,5 +82,11 @@ namespace xamarin::android abort_application (LOG_DEFAULT, message.data (), log_location, sloc); } }; + + template [[gnu::always_inline]] + static inline constexpr auto pointer_add (TPtr ptr, size_t offset) noexcept -> TRet + { + return reinterpret_cast(reinterpret_cast(ptr) + offset); + } } #endif // __HELPERS_HH From 28c6439f92e5125374ef04520d3e81e2a7d6d898 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Wed, 27 Nov 2024 13:13:47 +0100 Subject: [PATCH 17/54] Conversion to std::format continues Build is broken atm --- src/native/monodroid/debug.cc | 76 ++++---- .../monodroid/embedded-assemblies-zip.cc | 6 +- src/native/monodroid/monodroid-glue.cc | 137 ++++++------- src/native/monodroid/osbridge.cc | 172 ++++++++++------- src/native/monodroid/xamarin_getifaddrs.cc | 109 ++++++----- .../pinvoke-override-api-impl.hh | 22 +-- src/native/pinvoke-override/precompiled.cc | 12 +- src/native/runtime-base/android-system.cc | 72 +++---- src/native/runtime-base/monodroid-dl.hh | 14 +- src/native/shared/log_types.hh | 180 +++++++----------- 10 files changed, 404 insertions(+), 396 deletions(-) diff --git a/src/native/monodroid/debug.cc b/src/native/monodroid/debug.cc index db787268f41..7aa2ec6abb2 100644 --- a/src/native/monodroid/debug.cc +++ b/src/native/monodroid/debug.cc @@ -95,9 +95,11 @@ Debug::monodroid_profiler_load (const char *libmono_path, const char *desc, cons if (!found) log_warn (LOG_DEFAULT, - "The '%s' profiler wasn't found in the main executable nor could it be loaded from '%s'.", - mname.get (), - libname.get ()); + std::format ("The '{}' profiler wasn't found in the main executable nor could it be loaded from '{}'.", + mname.get (), + libname.get () + ) + ); } /* Profiler support cribbed from mono/metadata/profiler.c */ @@ -108,7 +110,7 @@ bool Debug::load_profiler (void *handle, const char *desc, const char *symbol) { ProfilerInitializer func = reinterpret_cast (java_interop_lib_symbol (handle, symbol, nullptr)); - log_warn (LOG_DEFAULT, "Looking for profiler init symbol '%s'? %p", symbol, func); + log_warn (LOG_DEFAULT, std::format ("Looking for profiler init symbol '{}'? {:p}", symbol, reinterpret_cast(func))); if (func != nullptr) { func (desc); @@ -138,7 +140,7 @@ Debug::parse_options (char *options, ConnOptions *opts) { char **args, **ptr; - log_info (LOG_DEFAULT, "Connection options: '%s'", options); + log_info (LOG_DEFAULT, std::format ("Connection options: '{}'", options)); args = Util::monodroid_strsplit (options, ",", 0); @@ -148,21 +150,21 @@ Debug::parse_options (char *options, ConnOptions *opts) if (strstr (arg, "port=") == arg) { int port = atoi (arg + strlen ("port=")); if (port < 0 || port > std::numeric_limits::max ()) { - log_error (LOG_DEFAULT, "Invalid debug port value %d", port); + log_error (LOG_DEFAULT, std::format ("Invalid debug port value {}", port)); continue; } conn_port = static_cast(port); - log_info (LOG_DEFAULT, "XS port = %d", conn_port); + log_info (LOG_DEFAULT, std::format ("XS port = {}", conn_port)); } else if (strstr (arg, "timeout=") == arg) { char *endp; arg += strlen ("timeout="); opts->timeout_time = strtoll (arg, &endp, 10); if ((endp == arg) || (*endp != '\0')) - log_error (LOG_DEFAULT, "Invalid --timeout argument."); + log_error (LOG_DEFAULT, "Invalid --timeout argument."sv); } else { - log_info (LOG_DEFAULT, "Unknown connection option: '%s'", arg); + log_info (LOG_DEFAULT, std::format ("Unknown connection option: '{}'", arg)); } } } @@ -186,7 +188,7 @@ Debug::start_connection (char *options) cur_time = time (nullptr); if (opts.timeout_time && cur_time > opts.timeout_time) { - log_warn (LOG_DEBUGGER, "Not connecting to IDE as the timeout value has been reached; current-time: %lli timeout: %lli", cur_time, opts.timeout_time); + log_warn (LOG_DEBUGGER, std::format ("Not connecting to IDE as the timeout value has been reached; current-time: {} timeout: {}", cur_time, opts.timeout_time)); return DebuggerConnectionStatus::Unconnected; } @@ -197,7 +199,7 @@ Debug::start_connection (char *options) res = pthread_create (&conn_thread_id, nullptr, xamarin::android::conn_thread, this); if (res) { - log_error (LOG_DEFAULT, "Failed to create connection thread: %s", strerror (errno)); + log_error (LOG_DEFAULT, std::format ("Failed to create connection thread: {}", strerror (errno))); return DebuggerConnectionStatus::Error; } @@ -218,8 +220,8 @@ Debug::start_debugging_and_profiling () if (res == DebuggerConnectionStatus::Error) { Helpers::abort_application ( LOG_DEBUGGER, - Util::monodroid_strdup_printf ( - "Connection to debugger failed. Args: %s", + std::format ( + "Connection to debugger failed. Args: {}", connect_args ) ); @@ -257,24 +259,24 @@ Debug::process_connection (int fd) ssize_t rv = Util::recv_uninterrupted (fd, &cmd_len, sizeof(cmd_len)); if (rv == 0) { - log_info (LOG_DEFAULT, "EOF on socket.\n"); + log_info (LOG_DEFAULT, "EOF on socket."sv); return false; } if (rv <= 0) { - log_info (LOG_DEFAULT, "Error while receiving command from XS (%s)\n", strerror (errno)); + log_info (LOG_DEFAULT, std::format ("Error while receiving command from XS ({})", strerror (errno))); return false; } rv = Util::recv_uninterrupted (fd, command, cmd_len); if (rv <= 0) { - log_info (LOG_DEFAULT, "Error while receiving command from XS (%s)\n", strerror (errno)); + log_info (LOG_DEFAULT, std::format ("Error while receiving command from XS ({})", strerror (errno))); return false; } // null-terminate command [cmd_len] = 0; - log_info (LOG_DEFAULT, "Received cmd: '%s'.", command); + log_info (LOG_DEFAULT, std::format ("Received cmd: '{}'.", command)); if (process_cmd (fd, command)) return true; @@ -286,14 +288,14 @@ Debug::handle_server_connection (void) { int listen_socket = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP); if (listen_socket == -1) { - log_info (LOG_DEFAULT, "Could not create socket for XS to connect to: %s", strerror (errno)); + log_info (LOG_DEFAULT, std::format ("Could not create socket for XS to connect to: {}", strerror (errno))); return 1; } int flags = 1; int rv = setsockopt (listen_socket, SOL_SOCKET, SO_REUSEADDR, &flags, sizeof (flags)); if (rv == -1 && Util::should_log (LOG_DEFAULT)) { - log_info_nocheck (LOG_DEFAULT, "Could not set SO_REUSEADDR on the listening socket (%s)", strerror (errno)); + log_info_nocheck (LOG_DEFAULT, std::format ("Could not set SO_REUSEADDR on the listening socket ({})", strerror (errno))); // not a fatal failure } @@ -307,7 +309,7 @@ Debug::handle_server_connection (void) listen_addr.sin_addr.s_addr = INADDR_ANY; rv = bind (listen_socket, (struct sockaddr *) &listen_addr, sizeof (listen_addr)); if (rv == -1) { - log_info (LOG_DEFAULT, "Could not bind to address: %s", strerror (errno)); + log_info (LOG_DEFAULT, std::format ("Could not bind to address: {}", strerror (errno))); rv = 2; goto cleanup; } @@ -319,7 +321,7 @@ Debug::handle_server_connection (void) rv = listen (listen_socket, 1); if (rv == -1) { - log_info (LOG_DEFAULT, "Could not listen for XS: %s", strerror (errno)); + log_info (LOG_DEFAULT, std::format ("Could not listen for XS: {}", strerror (errno))); rv = 2; goto cleanup; } @@ -362,14 +364,14 @@ Debug::handle_server_connection (void) if ((rv = select (listen_socket + 1, &rset, nullptr, nullptr, &tv)) == 0) { // timeout hit, no connections available. - log_info (LOG_DEFAULT, "Listened2 for connections from XS for 2 seconds, nobody connected.\n"); + log_info (LOG_DEFAULT, "Listened2 for connections from XS for 2 seconds, nobody connected."sv); rv = 3; goto cleanup; } } while (rv == -1 && errno == EINTR); if (rv == -1) { - log_info (LOG_DEFAULT, "Failed while waiting for XS to connect: %s", strerror (errno)); + log_info (LOG_DEFAULT, std::format ("Failed while waiting for XS to connect: {}", strerror (errno))); rv = 2; goto cleanup; } @@ -377,23 +379,23 @@ Debug::handle_server_connection (void) socklen_t len = sizeof (struct sockaddr_in); int fd = accept (listen_socket, (struct sockaddr *) &listen_addr, &len); if (fd == -1) { - log_info (LOG_DEFAULT, "Failed to accept connection from XS: %s", strerror (errno)); + log_info (LOG_DEFAULT, std::format ("Failed to accept connection from XS: {}", strerror (errno))); rv = 3; goto cleanup; } flags = 1; if (setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, (char *) &flags, sizeof (flags)) < 0) { - log_info (LOG_DEFAULT, "Could not set TCP_NODELAY on socket (%s)", strerror (errno)); + log_info (LOG_DEFAULT, std::format ("Could not set TCP_NODELAY on socket ({})", strerror (errno))); // not a fatal failure } - log_info (LOG_DEFAULT, "Successfully received connection from XS on port %i, fd: %i\n", listen_port, fd); + log_info (LOG_DEFAULT, std::format ("Successfully received connection from XS on port {}, fd: {}", listen_port, fd)); need_new_conn = process_connection (fd); } - log_info (LOG_DEFAULT, "Successfully talked to XS. Will continue startup now.\n"); + log_info (LOG_DEFAULT, "Successfully talked to XS. Will continue startup now."sv); rv = 0; @@ -440,13 +442,13 @@ Debug::process_cmd (int fd, char *cmd) constexpr std::string_view PONG_REPLY { "pong" }; if (strcmp (cmd, PING_CMD.data ()) == 0) { if (!Util::send_uninterrupted (fd, const_cast (reinterpret_cast (PONG_REPLY.data ())), 5)) - log_error (LOG_DEFAULT, "Got keepalive request from XS, but could not send response back (%s)\n", strerror (errno)); + log_error (LOG_DEFAULT, std::format ("Got keepalive request from XS, but could not send response back ({})", strerror (errno))); return false; } constexpr std::string_view EXIT_PROCESS_CMD { "exit process" }; if (strcmp (cmd, EXIT_PROCESS_CMD.data ()) == 0) { - log_info (LOG_DEFAULT, "Debugger requested an exit, will exit immediately.\n"); + log_info (LOG_DEFAULT, "Debugger requested an exit, will exit immediately."sv); fflush (stdout); fflush (stderr); exit (0); @@ -486,7 +488,7 @@ Debug::process_cmd (int fd, char *cmd) profiler_fd = fd; profiler_description = Util::monodroid_strdup_printf ("%s,output=#%i", prof, profiler_fd); } else { - log_error (LOG_DEFAULT, "Unknown profiler: '%s'", prof); + log_error (LOG_DEFAULT, std::format ("Unknown profiler: '{}'", prof)); } /* Notify the main thread (start_profiling ()) */ profiler_configured = true; @@ -495,7 +497,7 @@ Debug::process_cmd (int fd, char *cmd) pthread_mutex_unlock (&process_cmd_mutex); return use_fd; } else { - log_error (LOG_DEFAULT, "Unsupported command: '%s'", cmd); + log_error (LOG_DEFAULT, std::format ("Unsupported command: '{}'", cmd)); } return false; @@ -525,7 +527,7 @@ Debug::start_debugging (void) // this text is used in unit tests to check the debugger started // do not change it without updating the test. - log_warn (LOG_DEBUGGER, "Trying to initialize the debugger with options: %s", debug_arg); + log_warn (LOG_DEBUGGER, std::format ("Trying to initialize the debugger with options: {}", debug_arg)); if (enable_soft_breakpoints ()) { constexpr std::string_view soft_breakpoints { "--soft-breakpoints" }; @@ -552,7 +554,7 @@ Debug::start_profiling () if (!profiler_description) return; - log_info (LOG_DEFAULT, "Loading profiler: '%s'", profiler_description); + log_info (LOG_DEFAULT, std::format ("Loading profiler: '{}'", profiler_description)); monodroid_profiler_load (AndroidSystem::get_runtime_libdir (), profiler_description, nullptr); } @@ -572,7 +574,7 @@ Debug::enable_soft_breakpoints (void) uname (&name); for (const char** ptr = soft_breakpoint_kernel_list; *ptr; ptr++) { if (strcmp (name.release, *ptr) == 0) { - log_info (LOG_DEBUGGER, "soft breakpoints enabled due to kernel version match (%s)", name.release); + log_info (LOG_DEBUGGER, std::format ("soft breakpoints enabled due to kernel version match ({})", name.release)); return 1; } } @@ -580,17 +582,17 @@ Debug::enable_soft_breakpoints (void) char *value; /* Soft breakpoints are enabled by default */ if (AndroidSystem::monodroid_get_system_property (SharedConstants::DEBUG_MONO_SOFT_BREAKPOINTS, &value) <= 0) { - log_info (LOG_DEBUGGER, "soft breakpoints enabled by default (%s property not defined)", SharedConstants::DEBUG_MONO_SOFT_BREAKPOINTS.data ()); + log_info (LOG_DEBUGGER, std::format ("soft breakpoints enabled by default ({} property not defined)", SharedConstants::DEBUG_MONO_SOFT_BREAKPOINTS.data ())); return 1; } bool ret; if (strcmp ("0", value) == 0) { ret = false; - log_info (LOG_DEBUGGER, "soft breakpoints disabled (%s property set to %s)", SharedConstants::DEBUG_MONO_SOFT_BREAKPOINTS.data (), value); + log_info (LOG_DEBUGGER, std::format ("soft breakpoints disabled ({} property set to {})", SharedConstants::DEBUG_MONO_SOFT_BREAKPOINTS.data (), value)); } else { ret = true; - log_info (LOG_DEBUGGER, "soft breakpoints enabled (%s property set to %s)", SharedConstants::DEBUG_MONO_SOFT_BREAKPOINTS.data (), value); + log_info (LOG_DEBUGGER, std::format ("soft breakpoints enabled ({} property set to {})", SharedConstants::DEBUG_MONO_SOFT_BREAKPOINTS.data (), value)); } delete[] value; return ret; diff --git a/src/native/monodroid/embedded-assemblies-zip.cc b/src/native/monodroid/embedded-assemblies-zip.cc index 6d47ba7c042..16b2c817b64 100644 --- a/src/native/monodroid/embedded-assemblies-zip.cc +++ b/src/native/monodroid/embedded-assemblies-zip.cc @@ -331,9 +331,9 @@ EmbeddedAssemblies::zip_load_entries (int fd, const char *apk_name, [[maybe_unus ); } #ifdef DEBUG - log_info (LOG_ASSEMBLY, "Central directory offset: %u", cd_offset); - log_info (LOG_ASSEMBLY, "Central directory size: %u", cd_size); - log_info (LOG_ASSEMBLY, "Central directory entries: %u", cd_entries); + log_info (LOG_ASSEMBLY, std::format ("Central directory offset: {}", cd_offset)); + log_info (LOG_ASSEMBLY, std::format ("Central directory size: {}", cd_size)); + log_info (LOG_ASSEMBLY, std::format ("Central directory entries: {}", cd_entries)); #endif off_t retval = ::lseek (fd, static_cast(cd_offset), SEEK_SET); if (retval < 0) { diff --git a/src/native/monodroid/monodroid-glue.cc b/src/native/monodroid/monodroid-glue.cc index a90e239e83f..25c10b07660 100644 --- a/src/native/monodroid/monodroid-glue.cc +++ b/src/native/monodroid/monodroid-glue.cc @@ -95,7 +95,7 @@ MonodroidRuntime::thread_end ([[maybe_unused]] MonoProfiler *prof, [[maybe_unuse if (r != JNI_OK) { #if DEBUG /* - log_fatal (LOG_DEFAULT, "ERROR: Unable to detach current thread from the Java VM!"); + log_fatal (LOG_DEFAULT, "ERROR: Unable to detach current thread from the Java VM!"sv); */ #endif } @@ -174,15 +174,15 @@ MonodroidRuntime::open_from_update_dir (MonoAssemblyName *aname, [[maybe_unused] fullpath.append (SharedConstants::DLL_EXTENSION); } - log_debug (LOG_ASSEMBLY, "open_from_update_dir: trying to open assembly: %s\n", fullpath.get ()); + log_debug (LOG_ASSEMBLY, std::format ("open_from_update_dir: trying to open assembly: {}", fullpath.get ())); if (Util::file_exists (fullpath.get ())) { MonoImageOpenStatus status{}; result = mono_assembly_open_full (fullpath.get (), &status, 0); if (result == nullptr || status != MonoImageOpenStatus::MONO_IMAGE_OK) { - log_warn (LOG_ASSEMBLY, "Failed to load managed assembly '%s'. %s", fullpath.get (), mono_image_strerror (status)); + log_warn (LOG_ASSEMBLY, std::format ("Failed to load managed assembly '{}'. {}", fullpath.get (), mono_image_strerror (status))); } } else { - log_warn (LOG_ASSEMBLY, "open_from_update_dir: assembly file DOES NOT EXIST"); + log_warn (LOG_ASSEMBLY, "open_from_update_dir: assembly file DOES NOT EXIST"sv); } if (result != nullptr) { // TODO: register .mdb, .pdb file @@ -191,7 +191,7 @@ MonodroidRuntime::open_from_update_dir (MonoAssemblyName *aname, [[maybe_unused] } if (result != nullptr && Util::should_log (LOG_ASSEMBLY)) { - log_info_nocheck (LOG_ASSEMBLY, "open_from_update_dir: loaded assembly: %p\n", result); + log_info_nocheck (LOG_ASSEMBLY, std::format ("open_from_update_dir: loaded assembly: {:p}", reinterpret_cast(result))); } return result; } @@ -378,7 +378,7 @@ MonodroidRuntime::parse_gdb_options () noexcept time_t secs = time (nullptr); if (v + 10 < secs) { - log_warn (LOG_DEFAULT, "Found stale %s property with value '%s', not waiting.", SharedConstants::DEBUG_MONO_GDB_PROPERTY.data (), val.get ()); + log_warn (LOG_DEFAULT, std::format ("Found stale {} property with value '{}', not waiting.", SharedConstants::DEBUG_MONO_GDB_PROPERTY.data (), val.get ())); do_wait = false; } } @@ -392,7 +392,7 @@ bool MonodroidRuntime::parse_runtime_args (dynamic_local_string &runtime_args, RuntimeOptions *options) noexcept { if (runtime_args.length () == 0) { - log_warn (LOG_DEFAULT, "runtime args empty"); + log_warn (LOG_DEFAULT, "runtime args empty"sv); return true; } @@ -422,7 +422,7 @@ MonodroidRuntime::parse_runtime_args (dynamic_local_string std::numeric_limits::max ()) { - log_error (LOG_DEFAULT, "Invalid SDB port value %d", sdb_port); + log_error (LOG_DEFAULT, std::format ("Invalid SDB port value {}", sdb_port)); ret = false; continue; } if (out_port > std::numeric_limits::max ()) { - log_error (LOG_DEFAULT, "Invalid output port value %d", out_port); + log_error (LOG_DEFAULT, std::format ("Invalid output port value {}", out_port)); ret = false; continue; } @@ -468,19 +468,19 @@ MonodroidRuntime::parse_runtime_args (dynamic_local_stringout_port = out_port == -1 ? 0 : static_cast(out_port); } else if (token.starts_with (ARG_TIMEOUT)) { if (!token.to_integer (options->timeout_time, ARG_TIMEOUT.length ())) { - log_error (LOG_DEFAULT, "Invalid --timeout argument."); + log_error (LOG_DEFAULT, "Invalid --timeout argument."sv); ret = false; } } else if (token.starts_with (ARG_SERVER)) { options->server = token.has_at ('y', ARG_SERVER.length ()) || token.has_at ('Y', ARG_SERVER.length ()); } else if (token.starts_with (ARG_LOGLEVEL)) { if (!token.to_integer (options->loglevel, ARG_LOGLEVEL.length ())) { - log_error (LOG_DEFAULT, "Invalid --loglevel argument."); + log_error (LOG_DEFAULT, "Invalid --loglevel argument."sv); ret = false; } } else { static_local_string arg (token); - log_error (LOG_DEFAULT, "Unknown runtime argument: '%s'", arg.get ()); + log_error (LOG_DEFAULT, std::format ("Unknown runtime argument: '{}'", arg.get ())); ret = false; } } @@ -509,9 +509,9 @@ MonodroidRuntime::mono_runtime_init ([[maybe_unused]] JNIEnv *env, [[maybe_unuse cur_time = time (nullptr); if (!parse_runtime_args (runtime_args, &options)) { - log_error (LOG_DEFAULT, "Failed to parse runtime args: '%s'", runtime_args.get ()); + log_error (LOG_DEFAULT, std::format ("Failed to parse runtime args: '{}'", runtime_args.get ())); } else if (options.debug && cur_time > options.timeout_time) { - log_warn (LOG_DEBUGGER, "Not starting the debugger as the timeout value has been reached; current-time: %lli timeout: %lli", cur_time, options.timeout_time); + log_warn (LOG_DEBUGGER, std::format ("Not starting the debugger as the timeout value has been reached; current-time: {}; timeout: {}", cur_time, options.timeout_time)); } else if (options.debug && cur_time <= options.timeout_time) { EmbeddedAssemblies::set_register_debug_symbols (true); @@ -537,15 +537,15 @@ MonodroidRuntime::mono_runtime_init ([[maybe_unused]] JNIEnv *env, [[maybe_unuse // this text is used in unit tests to check the debugger started // do not change it without updating the test. - log_warn (LOG_DEBUGGER, "Trying to initialize the debugger with options: %s", debug_arg); + log_warn (LOG_DEBUGGER, std::format ("Trying to initialize the debugger with options: {}", debug_arg)); if (options.out_port > 0) { int sock = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP); if (sock < 0) { Helpers::abort_application ( LOG_DEBUGGER, - Util::monodroid_strdup_printf ( - "Could not construct a socket for stdout and stderr; does your app have the android.permission.INTERNET permission? %s", + std::format ( + "Could not construct a socket for stdout and stderr; does your app have the android.permission.INTERNET permission? {}", strerror (errno) ) ); @@ -561,21 +561,21 @@ MonodroidRuntime::mono_runtime_init ([[maybe_unused]] JNIEnv *env, [[maybe_unuse if ((r = inet_pton (AF_INET, options.host, &addr.sin_addr)) != 1) { Helpers::abort_application ( LOG_DEBUGGER, - Util::monodroid_strdup_printf ( - "Could not setup a socket for stdout and stderr: %s", - r == -1 ? strerror (errno) : "address not parseable in the specified address family" + std::format ( + "Could not setup a socket for stdout and stderr: {}", + r == -1 ? strerror (errno) : "address not parseable in the specified address family"sv ) ); } if (options.server) { int accepted = monodroid_debug_accept (sock, addr); - log_warn (LOG_DEBUGGER, "Accepted stdout connection: %d", accepted); + log_warn (LOG_DEBUGGER, std::format ("Accepted stdout connection: {}", accepted)); if (accepted < 0) { Helpers::abort_application ( LOG_DEBUGGER, - Util::monodroid_strdup_printf ( - "Error accepting stdout and stderr (%s:%d): %s", + std::format ( + "Error accepting stdout and stderr ({}:{}): {}", options.host, options.out_port, strerror (errno) @@ -589,8 +589,8 @@ MonodroidRuntime::mono_runtime_init ([[maybe_unused]] JNIEnv *env, [[maybe_unuse if (monodroid_debug_connect (sock, addr) != 1) { Helpers::abort_application ( LOG_DEBUGGER, - Util::monodroid_strdup_printf ( - "Error connecting stdout and stderr (%s:%d): %s", + std::format ( + "Error connecting stdout and stderr ({}:{}): {}", options.host, options.out_port, strerror (errno) @@ -651,7 +651,7 @@ MonodroidRuntime::mono_runtime_init ([[maybe_unused]] JNIEnv *env, [[maybe_unuse parse_gdb_options (); if (wait_for_gdb) { - log_warn (LOG_DEFAULT, "Waiting for gdb to attach..."); + log_warn (LOG_DEFAULT, "Waiting for gdb to attach..."sv); while (monodroid_gdb_wait) { sleep (1); } @@ -662,7 +662,7 @@ MonodroidRuntime::mono_runtime_init ([[maybe_unused]] JNIEnv *env, [[maybe_unuse if (AndroidSystem::monodroid_get_system_property (SharedConstants::DEBUG_MONO_RUNTIME_ARGS_PROPERTY, prop_val) > 0) { char **ptr; - log_warn (LOG_DEBUGGER, "passing '%s' as extra arguments to the runtime.\n", prop_val.get ()); + log_warn (LOG_DEBUGGER, std::format ("passing '{}' as extra arguments to the runtime.", prop_val.get ())); char **args = Util::monodroid_strsplit (prop_val.get (), " ", 0); int argc = 0; @@ -729,16 +729,20 @@ MonodroidRuntime::create_domain (JNIEnv *env, jstring_array_wrapper &runtimeApks if (user_assemblies_count == 0 && AndroidSystem::count_override_assemblies () == 0 && !is_running_on_desktop) { #if defined (DEBUG) - log_fatal (LOG_DEFAULT, "No assemblies found in '%s' or '%s'. Assuming this is part of Fast Deployment. Exiting...", - AndroidSystem::override_dirs [0], - (AndroidSystem::override_dirs.size () > 1 && AndroidSystem::override_dirs [1] != nullptr) ? AndroidSystem::override_dirs [1] : ""); + log_fatal (LOG_DEFAULT, + std::format ( + "No assemblies found in '{}' or '{}'. Assuming this is part of Fast Deployment. Exiting...", + AndroidSystem::override_dirs [0], + (AndroidSystem::override_dirs.size () > 1 && AndroidSystem::override_dirs [1] != nullptr) ? AndroidSystem::override_dirs [1] : ""sv + ) + ); #else - log_fatal (LOG_DEFAULT, "No assemblies (or assembly blobs) were found in the application APK file(s) or on the filesystem"); + log_fatal (LOG_DEFAULT, "No assemblies (or assembly blobs) were found in the application APK file(s) or on the filesystem"sv); #endif constexpr const char *assemblies_prefix = EmbeddedAssemblies::get_assemblies_prefix ().data (); Helpers::abort_application ( - Util::monodroid_strdup_printf ( - "ALL entries in APK named `%s` MUST be STORED. Gradle's minification may COMPRESS such entries.", + std::format ( + "ALL entries in APK named `{}` MUST be STORED. Gradle's minification may COMPRESS such entries.", assemblies_prefix ) ); @@ -854,7 +858,7 @@ MonodroidRuntime::init_android_runtime (JNIEnv *env, jclass runtimeClass, jobjec // GC threshold is 90% of the max GREF count init.grefGcThreshold = static_cast(AndroidSystem::get_gref_gc_threshold ()); - log_info (LOG_GC, "GREF GC Threshold: %i", init.grefGcThreshold); + log_info (LOG_GC, std::format ("GREF GC Threshold: {}", init.grefGcThreshold)); init.grefClass = RuntimeUtil::get_class_from_runtime_field (env, runtimeClass, "java_lang_Class", true); Class_getName = env->GetMethodID (init.grefClass, "getName", "()Ljava/lang/String;"); @@ -931,7 +935,7 @@ MonodroidRuntime::init_android_runtime (JNIEnv *env, jclass runtimeClass, jobjec osBridge.initialize_on_runtime_init (env, runtimeClass); - log_debug (LOG_DEFAULT, "Calling into managed runtime init"); + log_debug (LOG_DEFAULT, "Calling into managed runtime init"sv); size_t native_to_managed_index; if (FastTiming::enabled ()) [[unlikely]] { @@ -940,7 +944,7 @@ MonodroidRuntime::init_android_runtime (JNIEnv *env, jclass runtimeClass, jobjec auto initialize = reinterpret_cast (mono_method_get_unmanaged_callers_only_ftnptr (method, &error)); if (initialize == nullptr) { - log_fatal (LOG_DEFAULT, "Failed to get pointer to Initialize. Mono error: %s", mono_error_get_message (&error)); + log_fatal (LOG_DEFAULT, std::format ("Failed to get pointer to Initialize. Mono error: {}", mono_error_get_message (&error))); } abort_unless ( @@ -996,7 +1000,7 @@ MonodroidRuntime::set_environment_variable_for_directory (const char *name, jstr if (createDirectory) { int rv = Util::create_directory (value.get_cstr (), mode); if (rv < 0 && errno != EEXIST) - log_warn (LOG_DEFAULT, "Failed to create directory for environment variable %s. %s", name, strerror (errno)); + log_warn (LOG_DEFAULT, std::format ("Failed to create directory for environment variable {}. {}", name, strerror (errno))); } setenv (name, value.get_cstr (), 1); } @@ -1006,10 +1010,10 @@ MonodroidRuntime::create_xdg_directory (jstring_wrapper& home, size_t home_len, { static_local_string dir (home_len + relative_path.length ()); Util::path_combine (dir, home.get_cstr (), home_len, relative_path.data (), relative_path.length ()); - log_debug (LOG_DEFAULT, "Creating XDG directory: %s", dir.get ()); + log_debug (LOG_DEFAULT, std::format ("Creating XDG directory: {}", dir.get ())); int rv = Util::create_directory (dir.get (), DEFAULT_DIRECTORY_MODE); if (rv < 0 && errno != EEXIST) - log_warn (LOG_DEFAULT, "Failed to create XDG directory %s. %s", dir.get (), strerror (errno)); + log_warn (LOG_DEFAULT, std::format ("Failed to create XDG directory {}. {}", dir.get (), strerror (errno))); if (!environment_variable_name.empty ()) { setenv (environment_variable_name.data (), dir.get (), 1); } @@ -1038,7 +1042,7 @@ MonodroidRuntime::set_debug_env_vars (void) noexcept return; auto log_envvar = [](const char *name, const char *v) { - log_debug (LOG_DEFAULT, "Env variable '%s' set to '%s'.", name, v); + log_debug (LOG_DEFAULT, std::format ("Env variable '{}' set to '{}'.", name, v)); }; string_segment arg_token; @@ -1058,7 +1062,7 @@ MonodroidRuntime::set_debug_env_vars (void) noexcept log_envvar (arg.get (), one.data ()); } else if (index == 0) { // ’=value’ - log_warn (LOG_DEFAULT, "Attempt to set environment variable without specifying name: '%s'", arg.get ()); + log_warn (LOG_DEFAULT, std::format ("Attempt to set environment variable without specifying name: '{}'", arg.get ())); } else { // ’name=value’ arg[index] = '\0'; @@ -1138,10 +1142,10 @@ MonodroidRuntime::set_profile_options () noexcept .append (output_path.get (), output_path.length ()); } if (Util::create_directory (AndroidSystem::override_dirs[0], 0) < 0) { - log_warn (LOG_DEFAULT, "Failed to create directory '%s'. %s", AndroidSystem::override_dirs[0], std::strerror (errno)); + log_warn (LOG_DEFAULT, std::format ("Failed to create directory '{}'. {}", AndroidSystem::override_dirs[0], std::strerror (errno))); } - log_warn (LOG_DEFAULT, "Initializing profiler with options: %s", value.get ()); + log_warn (LOG_DEFAULT, std::format ("Initializing profiler with options: {}", value.get ())); debug.monodroid_profiler_load (AndroidSystem::get_runtime_libdir (), value.get (), output_path.get ()); } @@ -1155,7 +1159,7 @@ MonodroidRuntime::load_assembly (MonoAssemblyLoadContextGCHandle alc_handle, jst const char *assm_name = assembly.get_cstr (); if (assm_name == nullptr) [[unlikely]] { - log_warn (LOG_ASSEMBLY, "Unable to load assembly into ALC, name is null"); + log_warn (LOG_ASSEMBLY, "Unable to load assembly into ALC, name is null"sv); return; } @@ -1187,7 +1191,7 @@ MonodroidRuntime::load_assembly (MonoDomain *domain, jstring_wrapper &assembly) const char *assm_name = assembly.get_cstr (); if (assm_name == nullptr) [[unlikely]] { - log_warn (LOG_ASSEMBLY, "Unable to load assembly into AppDomain, name is null"); + log_warn (LOG_ASSEMBLY, "Unable to load assembly into AppDomain, name is null"sv); return; } @@ -1268,7 +1272,7 @@ MonodroidRuntime::create_and_initialize_domain (JNIEnv* env, jclass runtimeClass abort_unless (default_alc != nullptr, "Default AssemblyLoadContext not found"); EmbeddedAssemblies::install_preload_hooks_for_alc (); - log_debug (LOG_ASSEMBLY, "ALC hooks installed"); + log_debug (LOG_ASSEMBLY, "ALC hooks installed"sv); bool preload = (AndroidSystem::is_assembly_preload_enabled () || (is_running_on_desktop && force_preload_assemblies)); @@ -1466,7 +1470,7 @@ MonodroidRuntime::Java_mono_android_Runtime_initInternal (JNIEnv *env, jclass kl if (runtimeNativeLibDir != nullptr) { jstr = runtimeNativeLibDir; AndroidSystem::set_runtime_libdir (strdup (jstr.get_cstr ())); - log_debug (LOG_DEFAULT, "Using runtime path: %s", AndroidSystem::get_runtime_libdir ()); + log_debug (LOG_DEFAULT, std::format ("Using runtime path: {}", AndroidSystem::get_runtime_libdir ())); } AndroidSystem::setup_process_args (runtimeApks); @@ -1480,25 +1484,25 @@ MonodroidRuntime::Java_mono_android_Runtime_initInternal (JNIEnv *env, jclass kl debug.start_debugging_and_profiling (); #endif - log_debug (LOG_DEFAULT, "Probing for Mono AOT mode\n"); + log_debug (LOG_DEFAULT, "Probing for Mono AOT mode"sv); MonoAotMode mode = MonoAotMode::MONO_AOT_MODE_NONE; if (AndroidSystem::is_mono_aot_enabled ()) { mode = AndroidSystem::get_mono_aot_mode (); if (mode != MonoAotMode::MONO_AOT_MODE_INTERP_ONLY) { - log_debug (LOG_DEFAULT, "Enabling AOT mode in Mono"); + log_debug (LOG_DEFAULT, "Enabling AOT mode in Mono"sv); } else { - log_debug (LOG_DEFAULT, "Enabling Mono Interpreter"); + log_debug (LOG_DEFAULT, "Enabling Mono Interpreter"sv); } } mono_jit_set_aot_mode (mode); - log_debug (LOG_DEFAULT, "Probing if we should use LLVM\n"); + log_debug (LOG_DEFAULT, "Probing if we should use LLVM"sv); if (AndroidSystem::is_mono_llvm_enabled ()) { char *args [1]; args[0] = const_cast ("--llvm"); - log_debug (LOG_DEFAULT, "Enabling LLVM mode in Mono\n"); + log_debug (LOG_DEFAULT, "Enabling LLVM mode in Mono"sv); mono_jit_parse_options (1, args); mono_set_use_llvm (true); } @@ -1531,14 +1535,15 @@ MonodroidRuntime::Java_mono_android_Runtime_initInternal (JNIEnv *env, jclass kl if (Util::should_log (LOG_DEFAULT)) [[unlikely]] { log_info_nocheck ( LOG_DEFAULT, - ".NET for Android version: %s (%s; %s); built on %s; NDK version: %s; API level: %s; MonoVM version: %s", - BuildInfo::xa_version.data (), - BuildInfo::architecture.data (), - BuildInfo::kind.data (), - BuildInfo::date.data (), - BuildInfo::ndk_version.data (), - BuildInfo::ndk_api_level.data (), - mono_get_runtime_build_info () + std::format (".NET for Android version: {} ({}; {}); built on {}; NDK version: {}; API level: {}; MonoVM version: {}", + BuildInfo::xa_version.data (), + BuildInfo::architecture.data (), + BuildInfo::kind.data (), + BuildInfo::date.data (), + BuildInfo::ndk_version.data (), + BuildInfo::ndk_api_level.data (), + mono_get_runtime_build_info () + ) ); } @@ -1661,13 +1666,13 @@ MonodroidRuntime::get_java_class_name_for_TypeManager (jclass klass) noexcept JNIEnv *env = osBridge.ensure_jnienv (); jstring name = reinterpret_cast (env->CallObjectMethod (klass, Class_getName)); if (name == nullptr) { - log_error (LOG_DEFAULT, "Failed to obtain Java class name for object at %p", klass); + log_error (LOG_DEFAULT, std::format ("Failed to obtain Java class name for object at {:p}", reinterpret_cast(klass))); return nullptr; } const char *mutf8 = env->GetStringUTFChars (name, nullptr); if (mutf8 == nullptr) { - log_error (LOG_DEFAULT, "Failed to convert Java class name to UTF8 (out of memory?)"); + log_error (LOG_DEFAULT, "Failed to convert Java class name to UTF8 (out of memory?)"sv); env->DeleteLocalRef (name); return nullptr; } diff --git a/src/native/monodroid/osbridge.cc b/src/native/monodroid/osbridge.cc index d2725d278e2..94e0317d3e9 100644 --- a/src/native/monodroid/osbridge.cc +++ b/src/native/monodroid/osbridge.cc @@ -188,7 +188,7 @@ OSBridge::_write_stack_trace (FILE *to, char *from, LogCategories category) *end = '\0'; if ((category == LOG_GREF && gref_to_logcat) || (category == LOG_LREF && lref_to_logcat)) { - log_debug (category, "%s", m); + log_debug (category, std::format ("{}", m)); } if (to != nullptr) { fprintf (to, "%s\n", m); @@ -202,7 +202,7 @@ void OSBridge::_monodroid_gref_log (const char *message) { if (gref_to_logcat) { - log_debug (LOG_GREF, "%s", message); + log_debug (LOG_GREF, std::format ("{}", message)); } if (!gref_log) return; @@ -216,20 +216,23 @@ OSBridge::_monodroid_gref_log_new (jobject curHandle, char curType, jobject newH int c = _monodroid_gref_inc (); if ((log_categories & LOG_GREF) == 0) return c; - log_info (LOG_GREF, "+g+ grefc %i gwrefc %i obj-handle %p/%c -> new-handle %p/%c from thread '%s'(%i)", - c, - gc_weak_gref_count, - curHandle, - curType, - newHandle, - newType, - threadName, - threadId); + log_info (LOG_GREF, + std::format ("+g+ grefc {} gwrefc {} obj-handle {:p}/{} -> new-handle {:p}/{} from thread '{}'({})", + c, + gc_weak_gref_count, + reinterpret_cast(curHandle), + curType, + reinterpret_cast(newHandle), + newType, + threadName, + threadId + ) + ); if (gref_to_logcat) { if (from_writable) { _write_stack_trace (nullptr, const_cast(from), LOG_GREF); } else { - log_info (LOG_GREF, "%s", from); + log_info (LOG_GREF, std::format ("{}", from)); } } if (!gref_log) @@ -259,18 +262,21 @@ OSBridge::_monodroid_gref_log_delete (jobject handle, char type, const char *thr int c = _monodroid_gref_dec (); if ((log_categories & LOG_GREF) == 0) return; - log_info (LOG_GREF, "-g- grefc %i gwrefc %i handle %p/%c from thread '%s'(%i)", - c, - gc_weak_gref_count, - handle, - type, - threadName, - threadId); + log_info (LOG_GREF, + std::format ("-g- grefc {} gwrefc {} handle {:p}/{} from thread '{}'({})", + c, + gc_weak_gref_count, + reinterpret_cast(handle), + type, + threadName, + threadId + ) + ); if (gref_to_logcat) { if (from_writable) { _write_stack_trace (nullptr, const_cast(from), LOG_GREF); } else { - log_info (LOG_GREF, "%s", from); + log_info (LOG_GREF, std::format ("{}", from)); } } if (!gref_log) @@ -296,20 +302,23 @@ OSBridge::_monodroid_weak_gref_new (jobject curHandle, char curType, jobject new ++gc_weak_gref_count; if ((log_categories & LOG_GREF) == 0) return; - log_info (LOG_GREF, "+w+ grefc %i gwrefc %i obj-handle %p/%c -> new-handle %p/%c from thread '%s'(%i)", - gc_gref_count, - gc_weak_gref_count, - curHandle, - curType, - newHandle, - newType, - threadName, - threadId); + log_info (LOG_GREF, + std::format ("+w+ grefc {} gwrefc {} obj-handle {:p}/{} -> new-handle {:p}/{} from thread '{}'({})", + gc_gref_count, + gc_weak_gref_count, + reinterpret_cast(curHandle), + curType, + reinterpret_cast(newHandle), + newType, + threadName, + threadId + ) + ); if (gref_to_logcat) { if (from_writable) { _write_stack_trace (nullptr, const_cast(from), LOG_GREF); } else { - log_info (LOG_GREF, "%s", from); + log_info (LOG_GREF, std::format ("{}", from)); } } if (!gref_log) @@ -337,18 +346,21 @@ OSBridge::_monodroid_weak_gref_delete (jobject handle, char type, const char *th --gc_weak_gref_count; if ((log_categories & LOG_GREF) == 0) return; - log_info (LOG_GREF, "-w- grefc %i gwrefc %i handle %p/%c from thread '%s'(%i)", - gc_gref_count, - gc_weak_gref_count, - handle, - type, - threadName, - threadId); + log_info (LOG_GREF, + std::format ("-w- grefc {} gwrefc {} handle {:p}/{} from thread '{}'({})", + gc_gref_count, + gc_weak_gref_count, + reinterpret_cast(handle), + type, + threadName, + threadId + ) + ); if (gref_to_logcat) { if (from_writable) { _write_stack_trace (nullptr, const_cast(from), LOG_GREF); } else { - log_info (LOG_GREF, "%s", from); + log_info (LOG_GREF, std::format ("{}", from)); } } if (!gref_log) @@ -373,17 +385,20 @@ OSBridge::_monodroid_lref_log_new (int lrefc, jobject handle, char type, const c { if ((log_categories & LOG_LREF) == 0) return; - log_info (LOG_LREF, "+l+ lrefc %i handle %p/%c from thread '%s'(%i)", - lrefc, - handle, - type, - threadName, - threadId); + log_info (LOG_LREF, + std::format ("+l+ lrefc {} handle {:p}/{} from thread '{}'({})", + lrefc, + reinterpret_cast(handle), + type, + threadName, + threadId + ) + ); if (lref_to_logcat) { if (from_writable) { _write_stack_trace (nullptr, const_cast(from), LOG_GREF); } else { - log_info (LOG_GREF, "%s", from); + log_info (LOG_GREF, std::format ("{}", from)); } } if (!lref_log) @@ -407,17 +422,20 @@ OSBridge::_monodroid_lref_log_delete (int lrefc, jobject handle, char type, cons { if ((log_categories & LOG_LREF) == 0) return; - log_info (LOG_LREF, "-l- lrefc %i handle %p/%c from thread '%s'(%i)", - lrefc, - handle, - type, - threadName, - threadId); + log_info (LOG_LREF, + std::format ("-l- lrefc {} handle {:p}/{} from thread '{}'({})", + lrefc, + reinterpret_cast(handle), + type, + threadName, + threadId + ) + ); if (lref_to_logcat) { if (from_writable) { _write_stack_trace (nullptr, const_cast(from), LOG_GREF); } else { - log_info (LOG_GREF, "%s", from); + log_info (LOG_GREF, std::format ("{}", from)); } } if (!lref_log) @@ -529,9 +547,13 @@ OSBridge::gc_bridge_class_kind (MonoClass *klass) i = get_gc_bridge_index (klass); if (i == static_cast (-NUM_GC_BRIDGE_TYPES)) { - log_info (LOG_GC, "asked if a class %s.%s is a bridge before we inited java.lang.Object", - mono_class_get_namespace (klass), - mono_class_get_name (klass)); + log_info (LOG_GC, + std::format ( + "asked if a class {}.{} is a bridge before we inited java.lang.Object", + mono_class_get_namespace (klass), + mono_class_get_name (klass) + ) + ); return MonoGCBridgeObjectKind::GC_BRIDGE_TRANSPARENT_CLASS; } @@ -555,9 +577,13 @@ OSBridge::gc_is_bridge_object (MonoObject *object) if (handle == nullptr) { #if DEBUG MonoClass *mclass = mono_object_get_class (object); - log_info (LOG_GC, "object of class %s.%s with null handle", + log_info (LOG_GC, + std::format ( + "object of class {}.{} with null handle", mono_class_get_namespace (mclass), - mono_class_get_name (mclass)); + mono_class_get_name (mclass) + ) + ); #endif return 0; } @@ -643,9 +669,9 @@ OSBridge::add_reference (JNIEnv *env, OSBridge::AddReferenceTarget target, OSBri *reffed_description = describe_target (reffed_target); if (success) - log_warn (LOG_GC, "Added reference for %s to %s", description, reffed_description); + log_warn (LOG_GC, std::format ("Added reference for {} to {}", description, reffed_description)); else - log_error (LOG_GC, "Missing monodroidAddReference method for %s", description); + log_error (LOG_GC, std::format ("Missing monodroidAddReference method for {}", description)); free (description); free (reffed_description); @@ -881,9 +907,13 @@ OSBridge::gc_cleanup_after_java_collection (JNIEnv *env, int num_sccs, MonoGCBri #if DEBUG if (Logger::gc_spew_enabled ()) { klass = mono_object_get_class (obj); - log_error (LOG_GC, "Missing monodroidClearReferences method for object of class %s.%s", + log_error (LOG_GC, + std::format ( + "Missing monodroidClearReferences method for object of class {}.{}", mono_class_get_namespace (klass), - mono_class_get_name (klass)); + mono_class_get_name (klass) + ) + ); } #endif } @@ -897,7 +927,7 @@ OSBridge::gc_cleanup_after_java_collection (JNIEnv *env, int num_sccs, MonoGCBri } } #if DEBUG - log_info (LOG_GC, "GC cleanup summary: %d objects tested - resurrecting %d.", total, alive); + log_info (LOG_GC, std::format ("GC cleanup summary: {} objects tested - resurrecting {}.", total, alive)); #endif } @@ -927,10 +957,10 @@ OSBridge::gc_cross_references (int num_sccs, MonoGCBridgeSCC **sccs, int num_xre if (Logger::gc_spew_enabled ()) { int i, j; - log_info (LOG_GC, "cross references callback invoked with %d sccs and %d xrefs.", num_sccs, num_xrefs); + log_info (LOG_GC, std::format ("cross references callback invoked with {} sccs and {} xrefs.", num_sccs, num_xrefs)); for (i = 0; i < num_sccs; ++i) { - log_info (LOG_GC, "group %d with %d objects", i, sccs [i]->num_objs); + log_info (LOG_GC, std::format ("group {} with {} objects", i, sccs [i]->num_objs)); for (j = 0; j < sccs [i]->num_objs; ++j) { MonoObject *obj = sccs [i]->objs [j]; @@ -944,18 +974,22 @@ OSBridge::gc_cross_references (int num_sccs, MonoGCBridgeSCC **sccs, int num_xre } } MonoClass *klass = mono_object_get_class (obj); - log_info (LOG_GC, "\tobj %p [%s::%s] handle %p key_handle %p", - obj, + log_info (LOG_GC, + std::format ( + "\tobj {:p} [{}::{}] handle {:p} key_handle {:p}", + reinterpret_cast(obj), mono_class_get_namespace (klass), mono_class_get_name (klass), - handle, - key_handle); + reinterpret_cast(handle), + key_handle + ) + ); } } if (Util::should_log (LOG_GC)) { for (i = 0; i < num_xrefs; ++i) - log_info_nocheck (LOG_GC, "xref [%d] %d -> %d", i, xrefs [i].src_scc_index, xrefs [i].dst_scc_index); + log_info_nocheck (LOG_GC, std::format ("xref [{}] {} -> {}", i, xrefs [i].src_scc_index, xrefs [i].dst_scc_index)); } } diff --git a/src/native/monodroid/xamarin_getifaddrs.cc b/src/native/monodroid/xamarin_getifaddrs.cc index 9f071132976..99ba01039e6 100644 --- a/src/native/monodroid/xamarin_getifaddrs.cc +++ b/src/native/monodroid/xamarin_getifaddrs.cc @@ -381,9 +381,9 @@ get_ifaddrs_impl (int (**getifaddrs_implementation) (struct _monodroid_ifaddrs * } if (!*getifaddrs_implementation) { - log_info (LOG_NET, "This libc does not have getifaddrs/freeifaddrs, using Xamarin's\n"); + log_info (LOG_NET, "This libc does not have getifaddrs/freeifaddrs, using Xamarin's"sv); } else { - log_info (LOG_NET, "This libc has getifaddrs/freeifaddrs\n"); + log_info (LOG_NET, "This libc has getifaddrs/freeifaddrs"sv); } } @@ -421,7 +421,7 @@ open_netlink_session (netlink_session *session) memset (session, 0, sizeof (*session)); session->sock_fd = socket (AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); if (session->sock_fd == -1) { - log_warn (LOG_NETLINK, "Failed to create a netlink socket. %s\n", strerror (errno)); + log_warn (LOG_NETLINK, std::format ("Failed to create a netlink socket. {}", strerror (errno))); return -1; } @@ -440,7 +440,7 @@ open_netlink_session (netlink_session *session) session->them.nl_family = AF_NETLINK; if (bind (session->sock_fd, (struct sockaddr *)&session->us, sizeof (session->us)) < 0) { - log_warn (LOG_NETLINK, "Failed to bind to the netlink socket. %s\n", strerror (errno)); + log_warn (LOG_NETLINK, std::format ("Failed to bind to the netlink socket. {}", strerror (errno))); return -1; } @@ -478,7 +478,7 @@ send_netlink_dump_request (netlink_session *session, int type) session->message_header.msg_iov = &session->payload_vector; if (sendmsg (session->sock_fd, (const struct msghdr*)&session->message_header, 0) < 0) { - log_warn (LOG_NETLINK, "Failed to send netlink message. %s\n", strerror (errno)); + log_warn (LOG_NETLINK, std::format ("Failed to send netlink message. {}", strerror (errno))); return -1; } @@ -529,7 +529,7 @@ parse_netlink_reply (netlink_session *session, struct _monodroid_ifaddrs **ifadd abort_if_invalid_pointer_argument (last_ifaddr, "last_ifaddr"); size_t buf_size = static_cast(getpagesize ()); - log_debug (LOG_NETLINK, "receive buffer size == %d", buf_size); + log_debug (LOG_NETLINK, std::format ("receive buffer size == {}", buf_size)); size_t alloc_size = Helpers::multiply_with_overflow_check (sizeof(*response), buf_size); response = (unsigned char*)malloc (alloc_size); @@ -551,29 +551,29 @@ parse_netlink_reply (netlink_session *session, struct _monodroid_ifaddrs **ifadd netlink_reply.msg_iov = &reply_vector; length = recvmsg (session->sock_fd, &netlink_reply, 0); - log_debug (LOG_NETLINK, " length == %d\n", (int)length); + log_debug (LOG_NETLINK, std::format (" length == {}", (int)length)); if (length < 0) { - log_debug (LOG_NETLINK, "Failed to receive reply from netlink. %s\n", strerror (errno)); + log_debug (LOG_NETLINK, std::format ("Failed to receive reply from netlink. {}", strerror (errno))); goto cleanup; } #if DEBUG if (Util::should_log (LOG_NETLINK)) { - log_debug_nocheck (LOG_NETLINK, "response flags:"); + log_debug_nocheck (LOG_NETLINK, "response flags:"sv); if (netlink_reply.msg_flags == 0) - log_debug_nocheck (LOG_NETLINK, " [NONE]"); + log_debug_nocheck (LOG_NETLINK, " [NONE]"sv); else { if (netlink_reply.msg_flags & MSG_EOR) - log_debug_nocheck (LOG_NETLINK, " MSG_EOR"); + log_debug_nocheck (LOG_NETLINK, " MSG_EOR"sv); if (netlink_reply.msg_flags & MSG_TRUNC) - log_debug_nocheck (LOG_NETLINK, " MSG_TRUNC"); + log_debug_nocheck (LOG_NETLINK, " MSG_TRUNC"sv); if (netlink_reply.msg_flags & MSG_CTRUNC) - log_debug_nocheck (LOG_NETLINK, " MSG_CTRUNC"); + log_debug_nocheck (LOG_NETLINK, " MSG_CTRUNC"sv); if (netlink_reply.msg_flags & MSG_OOB) - log_debug_nocheck (LOG_NETLINK, " MSG_OOB"); + log_debug_nocheck (LOG_NETLINK, " MSG_OOB"sv); if (netlink_reply.msg_flags & MSG_ERRQUEUE) - log_debug_nocheck (LOG_NETLINK, " MSG_ERRQUEUE"); + log_debug_nocheck (LOG_NETLINK, " MSG_ERRQUEUE"sv); } } #endif @@ -582,21 +582,21 @@ parse_netlink_reply (netlink_session *session, struct _monodroid_ifaddrs **ifadd break; for (current_message = (struct nlmsghdr*)response; current_message && NLMSG_OK (current_message, static_cast(length)); current_message = NLMSG_NEXT (current_message, length)) { - log_debug (LOG_NETLINK, "next message... (type: %u)\n", current_message->nlmsg_type); + log_debug (LOG_NETLINK, std::format ("next message... (type: {})", current_message->nlmsg_type)); switch (current_message->nlmsg_type) { /* See rtnetlink.h */ case RTM_NEWLINK: - log_debug (LOG_NETLINK, " dumping link...\n"); + log_debug (LOG_NETLINK, " dumping link..."sv); addr = get_link_info (current_message); if (!addr || append_ifaddr (addr, ifaddrs_head, last_ifaddr) < 0) { ret = -1; goto cleanup; } - log_debug (LOG_NETLINK, " done\n"); + log_debug (LOG_NETLINK, " done"sv); break; case RTM_NEWADDR: - log_debug (LOG_NETLINK, " got an address\n"); + log_debug (LOG_NETLINK, " got an address"sv); addr = get_link_address (current_message, ifaddrs_head); if (!addr || append_ifaddr (addr, ifaddrs_head, last_ifaddr) < 0) { ret = -1; @@ -605,13 +605,13 @@ parse_netlink_reply (netlink_session *session, struct _monodroid_ifaddrs **ifadd break; case NLMSG_DONE: - log_debug (LOG_NETLINK, " message done\n"); + log_debug (LOG_NETLINK, " message done"sv); ret = 0; goto cleanup; break; default: - log_debug (LOG_NETLINK, " message type: %u", current_message->nlmsg_type); + log_debug (LOG_NETLINK, std::format (" message type: {}", current_message->nlmsg_type)); break; } } @@ -634,7 +634,7 @@ fill_sa_address (struct sockaddr **sa, struct ifaddrmsg *net_address, void *rta_ case AF_INET: { struct sockaddr_in *sa4; if (rta_payload_length != 4) /* IPv4 address length */ { - log_warn (LOG_NETLINK, "Unexpected IPv4 address payload length %u", rta_payload_length); + log_warn (LOG_NETLINK, std::format ("Unexpected IPv4 address payload length {}", rta_payload_length)); return -1; } sa4 = (struct sockaddr_in*)calloc (1, sizeof (*sa4)); @@ -650,7 +650,7 @@ fill_sa_address (struct sockaddr **sa, struct ifaddrmsg *net_address, void *rta_ case AF_INET6: { struct sockaddr_in6 *sa6; if (rta_payload_length != 16) /* IPv6 address length */ { - log_warn (LOG_NETLINK, "Unexpected IPv6 address payload length %u", rta_payload_length); + log_warn (LOG_NETLINK, std::format ("Unexpected IPv6 address payload length {}", rta_payload_length)); return -1; } sa6 = (struct sockaddr_in6*)calloc (1, sizeof (*sa6)); @@ -668,7 +668,7 @@ fill_sa_address (struct sockaddr **sa, struct ifaddrmsg *net_address, void *rta_ default: { struct sockaddr *sagen; if (rta_payload_length > sizeof (sagen->sa_data)) { - log_warn (LOG_NETLINK, "Unexpected RTA payload length %u (wanted at most %u)", rta_payload_length, sizeof (sagen->sa_data)); + log_warn (LOG_NETLINK, std::format ("Unexpected RTA payload length {} (wanted at most {})", rta_payload_length, sizeof (sagen->sa_data))); return -1; } @@ -701,16 +701,16 @@ fill_ll_address (struct sockaddr_ll_extended **sa, struct ifinfomsg *net_interfa /* The assert can only fail for Iniband links, which are quite unlikely to be found * in any mobile devices */ - log_debug (LOG_NETLINK, "rta_payload_length == %d; sizeof sll_addr == %d; hw type == 0x%X\n", rta_payload_length, sizeof ((*sa)->sll_addr), net_interface->ifi_type); + log_debug (LOG_NETLINK, std::format ("rta_payload_length == {}; sizeof sll_addr == {}; hw type == {:x}", rta_payload_length, sizeof ((*sa)->sll_addr), net_interface->ifi_type)); if (static_cast(rta_payload_length) > sizeof ((*sa)->sll_addr)) { - log_info (LOG_NETLINK, "Address is too long to place in sockaddr_ll (%d > %d)", rta_payload_length, sizeof ((*sa)->sll_addr)); + log_info (LOG_NETLINK, std::format ("Address is too long to place in sockaddr_ll ({} > {})", rta_payload_length, sizeof ((*sa)->sll_addr))); free (*sa); *sa = NULL; return -1; } if (rta_payload_length > std::numeric_limits::max ()) { - log_info (LOG_NETLINK, "Payload length too big to fit in the address structure"); + log_info (LOG_NETLINK, "Payload length too big to fit in the address structure"sv); free (*sa); *sa = NULL; return -1; @@ -817,16 +817,15 @@ calculate_address_netmask (struct _monodroid_ifaddrs *ifa, struct ifaddrmsg *net memset (netmask_data, 0xFF, prefix_bytes); if (postfix_bytes > 0) memset (netmask_data + prefix_bytes + 1, 0x00, postfix_bytes); - log_debug (LOG_NETLINK, " calculating netmask, prefix length is %u bits (%u bytes), data length is %u bytes\n", prefix_length, prefix_bytes, data_length); + log_debug (LOG_NETLINK, std::format (" calculating netmask, prefix length is {} bits ({} bytes), data length is {} bytes\n", prefix_length, prefix_bytes, data_length)); if (prefix_bytes + 2 < data_length) /* Set the rest of the mask bits in the byte following the last 0xFF value */ netmask_data [prefix_bytes + 1] = static_cast(0xff << (8 - (prefix_length % 8))); if (Util::should_log (LOG_NETLINK)) { - log_debug_nocheck (LOG_NETLINK, " netmask is: "); + log_debug_nocheck (LOG_NETLINK, " netmask is: "sv); for (uint32_t i = 0; i < data_length; i++) { - log_debug_nocheck (LOG_NETLINK, "%s%u", i == 0 ? " " : ".", (unsigned char)ifa->ifa_netmask->sa_data [i]); + log_debug_nocheck (LOG_NETLINK, std::format ("{}{}", i == 0 ? " "sv : "."sv, (unsigned char)ifa->ifa_netmask->sa_data [i])); } - log_debug_nocheck (LOG_NETLINK, "\n"); } } } @@ -848,7 +847,7 @@ get_link_address (const struct nlmsghdr *message, struct _monodroid_ifaddrs **if abort_if_invalid_pointer_argument (message, "message"); net_address = reinterpret_cast (NLMSG_DATA (message)); length = static_cast(IFA_PAYLOAD (message)); - log_debug (LOG_NETLINK, " address data length: %u", length); + log_debug (LOG_NETLINK, std::format (" address data length: {}", length)); if (length <= 0) { goto error; } @@ -862,17 +861,17 @@ get_link_address (const struct nlmsghdr *message, struct _monodroid_ifaddrs **if ifa->ifa_flags = static_cast(get_interface_flags_by_index (static_cast(net_address->ifa_index), ifaddrs_head)); attribute = IFA_RTA (net_address); - log_debug (LOG_NETLINK, " reading attributes"); + log_debug (LOG_NETLINK, " reading attributes"sv); while (RTA_OK (attribute, length)) { payload_size = RTA_PAYLOAD (attribute); - log_debug (LOG_NETLINK, " attribute payload_size == %u\n", payload_size); + log_debug (LOG_NETLINK, std::format (" attribute payload_size == {}", payload_size)); sa = NULL; switch (attribute->rta_type) { case IFA_LABEL: { size_t room_for_trailing_null = 0uz; - log_debug (LOG_NETLINK, " attribute type: LABEL"); + log_debug (LOG_NETLINK, " attribute type: LABEL"sv); if (payload_size > MAX_IFA_LABEL_SIZE) { payload_size = MAX_IFA_LABEL_SIZE; room_for_trailing_null = 1; @@ -893,7 +892,7 @@ get_link_address (const struct nlmsghdr *message, struct _monodroid_ifaddrs **if } case IFA_LOCAL: - log_debug (LOG_NETLINK, " attribute type: LOCAL"); + log_debug (LOG_NETLINK, " attribute type: LOCAL"sv); if (ifa->ifa_addr) { /* P2P protocol, set the dst/broadcast address union from the original address. * Since ifa_addr is set it means IFA_ADDRESS occured earlier and that address @@ -906,7 +905,7 @@ get_link_address (const struct nlmsghdr *message, struct _monodroid_ifaddrs **if break; case IFA_BROADCAST: - log_debug (LOG_NETLINK, " attribute type: BROADCAST"); + log_debug (LOG_NETLINK, " attribute type: BROADCAST"sv); if (ifa->_monodroid_ifa_dstaddr) { /* IFA_LOCAL happened earlier, undo its effect here */ free (ifa->_monodroid_ifa_dstaddr); @@ -916,7 +915,7 @@ get_link_address (const struct nlmsghdr *message, struct _monodroid_ifaddrs **if break; case IFA_ADDRESS: - log_debug (LOG_NETLINK, " attribute type: ADDRESS"); + log_debug (LOG_NETLINK, " attribute type: ADDRESS"sv); if (ifa->ifa_addr) { /* Apparently IFA_LOCAL occured earlier and we have a P2P connection * here. IFA_LOCAL carries the destination address, move it there @@ -928,23 +927,23 @@ get_link_address (const struct nlmsghdr *message, struct _monodroid_ifaddrs **if break; case IFA_UNSPEC: - log_debug (LOG_NETLINK, " attribute type: UNSPEC"); + log_debug (LOG_NETLINK, " attribute type: UNSPEC"sv); break; case IFA_ANYCAST: - log_debug (LOG_NETLINK, " attribute type: ANYCAST"); + log_debug (LOG_NETLINK, " attribute type: ANYCAST"sv); break; case IFA_CACHEINFO: - log_debug (LOG_NETLINK, " attribute type: CACHEINFO"); + log_debug (LOG_NETLINK, " attribute type: CACHEINFO"sv); break; case IFA_MULTICAST: - log_debug (LOG_NETLINK, " attribute type: MULTICAST"); + log_debug (LOG_NETLINK, " attribute type: MULTICAST"sv); break; default: - log_debug (LOG_NETLINK, " attribute type: %u", attribute->rta_type); + log_debug (LOG_NETLINK, std::format (" attribute type: {}", attribute->rta_type)); break; } @@ -960,10 +959,10 @@ get_link_address (const struct nlmsghdr *message, struct _monodroid_ifaddrs **if /* glibc stores the associated interface name in the address if IFA_LABEL never occured */ if (!ifa->ifa_name) { char *name = get_interface_name_by_index (static_cast(net_address->ifa_index), ifaddrs_head); - log_debug (LOG_NETLINK, " address has no name/label, getting one from interface\n"); + log_debug (LOG_NETLINK, " address has no name/label, getting one from interface"sv); ifa->ifa_name = name ? strdup (name) : NULL; } - log_debug (LOG_NETLINK, " address label: %s\n", ifa->ifa_name); + log_debug (LOG_NETLINK, std::format (" address label: {}", ifa->ifa_name)); if (calculate_address_netmask (ifa, net_address) < 0) { goto error; @@ -1017,13 +1016,13 @@ get_link_info (const struct nlmsghdr *message) goto error; } if (Util::should_log (LOG_NETLINK)) { - log_debug_nocheck (LOG_NETLINK, " interface name (payload length: %d; string length: %d)\n", RTA_PAYLOAD (attribute), strlen (ifa->ifa_name)); - log_debug_nocheck (LOG_NETLINK, " %s\n", ifa->ifa_name); + log_debug_nocheck (LOG_NETLINK, std::format (" interface name (payload length: {}; string length: {})", RTA_PAYLOAD (attribute), strlen (ifa->ifa_name))); + log_debug_nocheck (LOG_NETLINK, std::format (" {}", ifa->ifa_name)); } break; case IFLA_BROADCAST: - log_debug (LOG_NETLINK, " interface broadcast (%d bytes)\n", RTA_PAYLOAD (attribute)); + log_debug (LOG_NETLINK, std::format (" interface broadcast ({} bytes)", RTA_PAYLOAD (attribute))); if (fill_ll_address (&sa, net_interface, RTA_DATA (attribute), RTA_PAYLOAD (attribute)) < 0) { goto error; } @@ -1031,7 +1030,7 @@ get_link_info (const struct nlmsghdr *message) break; case IFLA_ADDRESS: - log_debug (LOG_NETLINK, " interface address (%d bytes)\n", RTA_PAYLOAD (attribute)); + log_debug (LOG_NETLINK, std::format (" interface address ({} bytes)", RTA_PAYLOAD (attribute))); if (fill_ll_address (&sa, net_interface, RTA_DATA (attribute), RTA_PAYLOAD (attribute)) < 0) { goto error; } @@ -1040,7 +1039,7 @@ get_link_info (const struct nlmsghdr *message) default: #if DEBUG - log_debug (LOG_NETLINK, " rta_type: "); + log_debug (LOG_NETLINK, " rta_type: "sv); print_ifla_name (attribute->rta_type); #endif // DEBUG break; @@ -1048,7 +1047,7 @@ get_link_info (const struct nlmsghdr *message) attribute = RTA_NEXT (attribute, length); } - log_debug (LOG_NETLINK, "link flags: 0x%X", ifa->ifa_flags); + log_debug (LOG_NETLINK, std::format ("link flags: {:X}", ifa->ifa_flags)); return ifa; error: @@ -1143,7 +1142,7 @@ print_ifla_name (int id) int i = 0; while (1) { if (iflas [i].value == -1 && iflas [i].name == 0) { - log_info_nocheck (LOG_NETLINK, "Unknown ifla->name: unknown id %d\n", id); + log_info_nocheck (LOG_NETLINK, std::format ("Unknown ifla->name: unknown id {}", id)); break; } @@ -1151,7 +1150,7 @@ print_ifla_name (int id) i++; continue; } - log_info_nocheck (LOG_NETLINK, "ifla->name: %s (%d)\n", iflas [i].name, iflas [i].value); + log_info_nocheck (LOG_NETLINK, std::format ("ifla->name: {} ({})", iflas [i].name, iflas [i].value)); break; } } @@ -1166,7 +1165,7 @@ print_address_list (const char title[], struct _monodroid_ifaddrs *list) char *msg, *tmp; if (!list) { - log_info_nocheck (LOG_NETLINK, "monodroid-net", "No list to print in %s", __FUNCTION__); + log_info_nocheck (LOG_NETLINK, std::format ("No list to print in {}", __FUNCTION__)); return; } @@ -1181,7 +1180,7 @@ print_address_list (const char title[], struct _monodroid_ifaddrs *list) cur = cur->ifa_next; } - log_info_nocheck (LOG_NETLINK, "%s: %s", title, msg ? msg : "[no addresses]"); + log_info_nocheck (LOG_NETLINK, std::format ("{}: {}", title, msg ? msg : "[no addresses]"sv)); free (msg); } #endif diff --git a/src/native/pinvoke-override/pinvoke-override-api-impl.hh b/src/native/pinvoke-override/pinvoke-override-api-impl.hh index 36523f092a9..240223b396c 100644 --- a/src/native/pinvoke-override/pinvoke-override-api-impl.hh +++ b/src/native/pinvoke-override/pinvoke-override-api-impl.hh @@ -23,21 +23,21 @@ namespace xamarin::android { constexpr bool PREFER_AOT_CACHE = false; lib_handle = internal::MonodroidDl::monodroid_dlopen (library_name, MONO_DL_LOCAL, nullptr, PREFER_AOT_CACHE); if (lib_handle == nullptr) { - log_warn (LOG_ASSEMBLY, "Shared library '%s' not loaded, p/invoke '%s' may fail", library_name, symbol_name); + log_warn (LOG_ASSEMBLY, std::format ("Shared library '{}' not loaded, p/invoke '{}' may fail", library_name, symbol_name)); return nullptr; } if (dso_handle != nullptr) { void *expected_null = nullptr; if (!__atomic_compare_exchange (dso_handle, &expected_null, &lib_handle, false /* weak */, __ATOMIC_ACQUIRE /* success_memorder */, __ATOMIC_RELAXED /* xxxfailure_memorder */)) { - log_debug (LOG_ASSEMBLY, "Library '%s' handle already cached by another thread", library_name); + log_debug (LOG_ASSEMBLY, std::format ("Library '{}' handle already cached by another thread", library_name)); } } } void *entry_handle = internal::MonodroidDl::monodroid_dlsym (lib_handle, symbol_name, nullptr, nullptr); if (entry_handle == nullptr) { - log_warn (LOG_ASSEMBLY, "Symbol '%s' not found in shared library '%s', p/invoke may fail", symbol_name, library_name); + log_warn (LOG_ASSEMBLY, std::format ("Symbol '{}' not found in shared library '{}', p/invoke may fail", symbol_name, library_name)); return nullptr; } @@ -60,7 +60,7 @@ namespace xamarin::android { return nullptr; } - log_debug (LOG_ASSEMBLY, "Caching p/invoke entry %s @ %s", library_name.c_str (), entrypoint_name.c_str ()); + log_debug (LOG_ASSEMBLY, std::format ("Caching p/invoke entry {} @ {}", library_name, entrypoint_name)); (*api_map)[entrypoint_name] = entry_handle; return entry_handle; } @@ -73,15 +73,15 @@ namespace xamarin::android { bool already_loaded = !__atomic_compare_exchange ( /* ptr */ &entry.func, - /* expected */ &expected_null, - /* desired */ &entry_handle, - /* weak */ false, - /* success_memorder */ __ATOMIC_ACQUIRE, - /* failure_memorder */ __ATOMIC_RELAXED + /* expected */ &expected_null, + /* desired */ &entry_handle, + /* weak */ false, + /* success_memorder */ __ATOMIC_ACQUIRE, + /* failure_memorder */ __ATOMIC_RELAXED ); if (already_loaded) { - log_debug (LOG_ASSEMBLY, "Entry '%s' from library '%s' already loaded by another thread", entrypoint_name, library_name); + log_debug (LOG_ASSEMBLY, std::format ("Entry '{}' from library '{}' already loaded by another thread", entrypoint_name, library_name)); } } @@ -147,7 +147,7 @@ namespace xamarin::android { handle = fetch_or_create_pinvoke_map_entry (lib_name, entry_name, entrypoint_name_hash, lib_map, /* need_lock */ false); } else { if (iter->second == nullptr) [[unlikely]] { - log_warn (LOG_ASSEMBLY, "Internal error: null entry in p/invoke map for key '%s'", library_name); + log_warn (LOG_ASSEMBLY, std::format ("Internal error: null entry in p/invoke map for key '{}'", library_name)); return nullptr; // fall back to `monodroid_dlopen` } diff --git a/src/native/pinvoke-override/precompiled.cc b/src/native/pinvoke-override/precompiled.cc index 1c84095080a..90ad9214ecd 100644 --- a/src/native/pinvoke-override/precompiled.cc +++ b/src/native/pinvoke-override/precompiled.cc @@ -22,16 +22,16 @@ PinvokeOverride::monodroid_pinvoke_override (const char *library_name, const cha PinvokeEntry *entry = find_pinvoke_address (entrypoint_hash, internal_pinvokes.data (), internal_pinvokes_count); if (entry == nullptr) [[unlikely]] { - log_fatal (LOG_ASSEMBLY, "Internal p/invoke symbol '%s @ %s' (hash: 0x%zx) not found in compile-time map.", library_name, entrypoint_name, entrypoint_hash); - log_fatal (LOG_ASSEMBLY, "compile-time map contents:"); + log_fatal (LOG_ASSEMBLY, std::format ("Internal p/invoke symbol '{} @ {}' (hash: {:x}) not found in compile-time map.", library_name, entrypoint_name, entrypoint_hash)); + log_fatal (LOG_ASSEMBLY, "compile-time map contents:"sv); for (size_t i = 0uz; i < internal_pinvokes_count; i++) { PinvokeEntry const& e = internal_pinvokes[i]; - log_fatal (LOG_ASSEMBLY, "\t'%s'=%p (hash: 0x%zx)", e.name, e.func, e.hash); + log_fatal (LOG_ASSEMBLY, std::format ("\t'{}'={:p} (hash: {:x})", e.name, e.func, e.hash)); } Helpers::abort_application ( LOG_ASSEMBLY, - Util::monodroid_strdup_printf ( - "Failure handling a p/invoke request for '%s'@'%s'", + std::format ( + "Failure handling a p/invoke request for '{}'@'{}'", entrypoint_name, library_name ) @@ -75,7 +75,7 @@ PinvokeOverride::monodroid_pinvoke_override (const char *library_name, const cha } // It's possible we don't have an entry for some `dotnet` p/invoke, fall back to the slow path below - log_debug (LOG_ASSEMBLY, "Symbol '%s' in library '%s' not found in the generated tables, falling back to slow path", entrypoint_name, library_name); + log_debug (LOG_ASSEMBLY, std::format ("Symbol '{}' in library '{}' not found in the generated tables, falling back to slow path", entrypoint_name, library_name)); } return handle_other_pinvoke_request (library_name, library_name_hash, entrypoint_name, entrypoint_hash); diff --git a/src/native/runtime-base/android-system.cc b/src/native/runtime-base/android-system.cc index 44745a7f34f..9119fe783a1 100644 --- a/src/native/runtime-base/android-system.cc +++ b/src/native/runtime-base/android-system.cc @@ -65,7 +65,7 @@ AndroidSystem::lookup_system_property (const char *name, size_t &value_len) noex return nullptr; if (application_config.system_property_count % 2 != 0) { - log_warn (LOG_DEFAULT, "Corrupted environment variable array: does not contain an even number of entries (%u)", application_config.system_property_count); + log_warn (LOG_DEFAULT, std::format ("Corrupted environment variable array: does not contain an even number of entries ({})", application_config.system_property_count)); return nullptr; } @@ -138,7 +138,7 @@ AndroidSystem::_monodroid__system_property_get (const char *name, char *sp_value char *buf = nullptr; if (sp_value_len < PROPERTY_VALUE_BUFFER_LEN) { size_t alloc_size = Helpers::add_with_overflow_check (PROPERTY_VALUE_BUFFER_LEN, 1uz); - log_warn (LOG_DEFAULT, "Buffer to store system property may be too small, will copy only %u bytes", sp_value_len); + log_warn (LOG_DEFAULT, std::format ("Buffer to store system property may be too small, will copy only {} bytes", sp_value_len)); buf = new char [alloc_size]; } @@ -250,12 +250,12 @@ AndroidSystem::monodroid_get_system_property_from_overrides ([[maybe_unused]] co } std::unique_ptr override_file {Util::path_combine (od, name)}; - log_info (LOG_DEFAULT, "Trying to get property from %s", override_file.get ()); + log_info (LOG_DEFAULT, std::format ("Trying to get property from {}", override_file.get ())); size_t result = _monodroid_get_system_property_from_file (override_file.get (), value); if (result == 0 || value == nullptr || (*value) == nullptr || **value == '\0') { continue; } - log_info (LOG_DEFAULT, "Property '%s' from %s has value '%s'.", name, od, *value); + log_info (LOG_DEFAULT, std::format ("Property '{}' from {} has value '{}'.", name, od, *value)); return result; } #endif // def DEBUG @@ -281,7 +281,7 @@ AndroidSystem::create_update_dir (char *override_dir) noexcept override_dirs [0] = override_dir; Util::create_public_directory (override_dir); - log_warn (LOG_DEFAULT, "Creating public update directory: `%s`", override_dir); + log_warn (LOG_DEFAULT, std::format ("Creating public update directory: `{}`", override_dir)); } bool @@ -306,16 +306,16 @@ AndroidSystem::load_dso (const char *path, unsigned int dl_flags, bool skip_exis if (path == nullptr || *path == '\0') return nullptr; - log_info (LOG_ASSEMBLY, "Trying to load shared library '%s'", path); + log_info (LOG_ASSEMBLY, std::format ("Trying to load shared library '{}'", path)); if (!skip_exists_check && !is_embedded_dso_mode_enabled () && !Util::file_exists (path)) { - log_info (LOG_ASSEMBLY, "Shared library '%s' not found", path); + log_info (LOG_ASSEMBLY, std::format ("Shared library '{}' not found", path)); return nullptr; } char *error = nullptr; void *handle = java_interop_lib_load (path, dl_flags, &error); if (handle == nullptr && Util::should_log (LOG_ASSEMBLY)) - log_info_nocheck (LOG_ASSEMBLY, "Failed to load shared library '%s'. %s", path, error); + log_info_nocheck (LOG_ASSEMBLY, std::format ("Failed to load shared library '{}'. {}", path, error)); java_interop_free (error); return handle; } @@ -450,9 +450,9 @@ AndroidSystem::get_max_gref_count_from_system (void) noexcept if (max < 0) max = std::numeric_limits::max (); if (*e) { - log_warn (LOG_GC, "Unsupported '%s' value '%s'.", SharedConstants::DEBUG_MONO_MAX_GREFC.data (), override.get ()); + log_warn (LOG_GC, std::format ("Unsupported '{}' value '{}'.", SharedConstants::DEBUG_MONO_MAX_GREFC.data (), override.get ())); } - log_warn (LOG_GC, "Overriding max JNI Global Reference count to %i", max); + log_warn (LOG_GC, std::format ("Overriding max JNI Global Reference count to {}", max)); } return max; } @@ -478,7 +478,7 @@ AndroidSystem::setup_environment (const char *name, const char *value) noexcept if (isupper (name [0]) || name [0] == '_') { if (setenv (name, v, 1) < 0) - log_warn (LOG_DEFAULT, "(Debug) Failed to set environment variable: %s", strerror (errno)); + log_warn (LOG_DEFAULT, std::format ("(Debug) Failed to set environment variable: {}", strerror (errno))); return; } @@ -492,13 +492,13 @@ AndroidSystem::setup_environment_from_override_file (const char *path) noexcept struct stat sbuf; if (::stat (path, &sbuf) < 0) { - log_warn (LOG_DEFAULT, "Failed to stat the environment override file %s: %s", path, strerror (errno)); + log_warn (LOG_DEFAULT, std::format ("Failed to stat the environment override file {}: {}", path, strerror (errno))); return; } int fd = open (path, O_RDONLY); if (fd < 0) { - log_warn (LOG_DEFAULT, "Failed to open the environment override file %s: %s", path, strerror (errno)); + log_warn (LOG_DEFAULT, std::format ("Failed to open the environment override file {}: {}", path, strerror (errno))); return; } @@ -515,7 +515,7 @@ AndroidSystem::setup_environment_from_override_file (const char *path) noexcept } while (r < 0 && errno == EINTR); if (nread == 0) { - log_warn (LOG_DEFAULT, "Failed to read the environment override file %s: %s", path, strerror (errno)); + log_warn (LOG_DEFAULT, std::format ("Failed to read the environment override file {}: {}", path, strerror (errno))); return; } @@ -536,26 +536,26 @@ AndroidSystem::setup_environment_from_override_file (const char *path) noexcept // # Variable value, terminated with NUL and padded to [value width] with NUL characters // value\0 if (nread < OVERRIDE_ENVIRONMENT_FILE_HEADER_SIZE) { - log_warn (LOG_DEFAULT, "Invalid format of the environment override file %s: malformatted header", path); + log_warn (LOG_DEFAULT, std::format ("Invalid format of the environment override file {}: malformatted header", path)); return; } char *endptr; unsigned long name_width = strtoul (buf.get (), &endptr, 16); if ((name_width == std::numeric_limits::max () && errno == ERANGE) || (buf[0] != '\0' && *endptr != '\0')) { - log_warn (LOG_DEFAULT, "Malformed header of the environment override file %s: name width has invalid format", path); + log_warn (LOG_DEFAULT, std::format ("Malformed header of the environment override file {}: name width has invalid format", path)); return; } unsigned long value_width = strtoul (buf.get () + 11, &endptr, 16); if ((value_width == std::numeric_limits::max () && errno == ERANGE) || (buf[0] != '\0' && *endptr != '\0')) { - log_warn (LOG_DEFAULT, "Malformed header of the environment override file %s: value width has invalid format", path); + log_warn (LOG_DEFAULT, std::format ("Malformed header of the environment override file {}: value width has invalid format", path)); return; } uint64_t data_width = name_width + value_width; if (data_width > file_size - OVERRIDE_ENVIRONMENT_FILE_HEADER_SIZE || (file_size - OVERRIDE_ENVIRONMENT_FILE_HEADER_SIZE) % data_width != 0) { - log_warn (LOG_DEFAULT, "Malformed environment override file %s: invalid data size", path); + log_warn (LOG_DEFAULT, std::format ("Malformed environment override file {}: invalid data size", path)); return; } @@ -563,11 +563,11 @@ AndroidSystem::setup_environment_from_override_file (const char *path) noexcept char *name = buf.get () + OVERRIDE_ENVIRONMENT_FILE_HEADER_SIZE; while (data_size > 0 && data_size >= data_width) { if (*name == '\0') { - log_warn (LOG_DEFAULT, "Malformed environment override file %s: name at offset %lu is empty", path, name - buf.get ()); + log_warn (LOG_DEFAULT, std::format ("Malformed environment override file {}: name at offset {} is empty", path, name - buf.get ())); return; } - log_debug (LOG_DEFAULT, "Setting environment variable from the override file %s: '%s' = '%s'", path, name, name + name_width); + log_debug (LOG_DEFAULT, std::format ("Setting environment variable from the override file {}: '{}' = '{}'", path, name, name + name_width)); setup_environment (name, name + name_width); name += data_width; data_size -= data_width; @@ -602,18 +602,18 @@ AndroidSystem::setup_environment () noexcept } if (aotMode != MonoAotMode::MONO_AOT_MODE_LAST) { - log_debug (LOG_DEFAULT, "Mono AOT mode: %s", mono_aot_mode_name); + log_debug (LOG_DEFAULT, std::format ("Mono AOT mode: {}", mono_aot_mode_name)); } else { if (!is_interpreter_enabled ()) { - log_warn (LOG_DEFAULT, "Unknown Mono AOT mode: %s", mono_aot_mode_name); + log_warn (LOG_DEFAULT, std::format ("Unknown Mono AOT mode: {}", mono_aot_mode_name)); } else { - log_warn (LOG_DEFAULT, "Mono AOT mode: interpreter"); + log_warn (LOG_DEFAULT, "Mono AOT mode: interpreter"sv); } } } if (application_config.environment_variable_count % 2 != 0) { - log_warn (LOG_DEFAULT, "Corrupted environment variable array: does not contain an even number of entries (%u)", application_config.environment_variable_count); + log_warn (LOG_DEFAULT, std::format ("Corrupted environment variable array: does not contain an even number of entries ({})", application_config.environment_variable_count)); return; } @@ -629,21 +629,21 @@ AndroidSystem::setup_environment () noexcept var_value = ""; #if defined (DEBUG) - log_info (LOG_DEFAULT, "Setting environment variable '%s' to '%s'", var_name, var_value); + log_info (LOG_DEFAULT, std::format ("Setting environment variable '{}' to '{}'", var_name, var_value)); #endif // def DEBUG if (setenv (var_name, var_value, 1) < 0) - log_warn (LOG_DEFAULT, "Failed to set environment variable: %s", strerror (errno)); + log_warn (LOG_DEFAULT, std::format ("Failed to set environment variable: {}", strerror (errno))); } #if defined (DEBUG) - log_debug (LOG_DEFAULT, "Loading environment from override directories."); + log_debug (LOG_DEFAULT, "Loading environment from override directories."sv); for (const char *od : override_dirs) { if (od == nullptr) { continue; } std::unique_ptr env_override_file {Util::path_combine (od, OVERRIDE_ENVIRONMENT_FILE_NAME.data ())}; - log_debug (LOG_DEFAULT, "%s", env_override_file.get ()); + log_debug (LOG_DEFAULT, std::format ("{}", env_override_file.get ())); if (Util::file_exists (env_override_file.get ())) { - log_debug (LOG_DEFAULT, "Loading %s", env_override_file.get ()); + log_debug (LOG_DEFAULT, std::format ("Loading {}", env_override_file.get ())); setup_environment_from_override_file (env_override_file.get ()); } } @@ -671,12 +671,12 @@ AndroidSystem::detect_embedded_dso_mode (jstring_array_wrapper& appDirs) noexcep { // appDirs[SharedConstants::APP_DIRS_DATA_DIR_INDEX] points to the native library directory std::unique_ptr libmonodroid_path {Util::path_combine (appDirs[SharedConstants::APP_DIRS_DATA_DIR_INDEX].get_cstr (), "libmonodroid.so")}; - log_debug (LOG_ASSEMBLY, "Checking if libmonodroid was unpacked to %s", libmonodroid_path.get ()); + log_debug (LOG_ASSEMBLY, std::format ("Checking if libmonodroid was unpacked to {}", libmonodroid_path.get ())); if (!Util::file_exists (libmonodroid_path.get ())) { - log_debug (LOG_ASSEMBLY, "%s not found, assuming application/android:extractNativeLibs == false", libmonodroid_path.get ()); + log_debug (LOG_ASSEMBLY, std::format ("{} not found, assuming application/android:extractNativeLibs == false", libmonodroid_path.get ())); set_embedded_dso_mode_enabled (true); } else { - log_debug (LOG_ASSEMBLY, "Native libs extracted to %s, assuming application/android:extractNativeLibs == true", appDirs[SharedConstants::APP_DIRS_DATA_DIR_INDEX].get_cstr ()); + log_debug (LOG_ASSEMBLY, std::format ("Native libs extracted to {}, assuming application/android:extractNativeLibs == true", appDirs[SharedConstants::APP_DIRS_DATA_DIR_INDEX].get_cstr ())); set_embedded_dso_mode_enabled (false); } } @@ -685,13 +685,13 @@ void AndroidSystem::setup_app_library_directories (jstring_array_wrapper& runtimeApks, jstring_array_wrapper& appDirs, bool have_split_apks) noexcept { if (!is_embedded_dso_mode_enabled ()) { - log_debug (LOG_DEFAULT, "Setting up for DSO lookup in app data directories"); + log_debug (LOG_DEFAULT, "Setting up for DSO lookup in app data directories"sv); AndroidSystem::app_lib_directories = std::span (single_app_lib_directory); AndroidSystem::app_lib_directories [0] = Util::strdup_new (appDirs[SharedConstants::APP_DIRS_DATA_DIR_INDEX].get_cstr ()); - log_debug (LOG_ASSEMBLY, "Added filesystem DSO lookup location: %s", appDirs[SharedConstants::APP_DIRS_DATA_DIR_INDEX].get_cstr ()); + log_debug (LOG_ASSEMBLY, std::format ("Added filesystem DSO lookup location: {}", appDirs[SharedConstants::APP_DIRS_DATA_DIR_INDEX].get_cstr ())); } else { - log_debug (LOG_DEFAULT, "Setting up for DSO lookup directly in the APK"); + log_debug (LOG_DEFAULT, "Setting up for DSO lookup directly in the APK"sv); if (have_split_apks) { // If split apks are used, then we will have just a single app library directory. Don't allocate any memory @@ -725,7 +725,7 @@ AndroidSystem::add_apk_libdir (const char *apk, size_t &index, const char *abi) { abort_unless (index < app_lib_directories.size (), "Index out of range"); app_lib_directories [index] = Util::string_concat (apk, "!/lib/", abi); - log_debug (LOG_ASSEMBLY, "Added APK DSO lookup location: %s", app_lib_directories[index]); + log_debug (LOG_ASSEMBLY, std::format ("Added APK DSO lookup location: {}", app_lib_directories[index])); index++; } diff --git a/src/native/runtime-base/monodroid-dl.hh b/src/native/runtime-base/monodroid-dl.hh index 14455578f0e..43e1b891a0e 100644 --- a/src/native/runtime-base/monodroid-dl.hh +++ b/src/native/runtime-base/monodroid-dl.hh @@ -48,11 +48,11 @@ namespace xamarin::android::internal size_t arr_size; if constexpr (WhichCache == CacheKind::AOT) { - log_debug (LOG_ASSEMBLY, "Looking for hash 0x%x in AOT cache", hash); + log_debug (LOG_ASSEMBLY, std::format ("Looking for hash {:x} in AOT cache", hash)); arr = aot_dso_cache; arr_size = application_config.number_of_aot_cache_entries; } else if constexpr (WhichCache == CacheKind::DSO) { - log_debug (LOG_ASSEMBLY, "Looking for hash 0x%x in DSO cache", hash); + log_debug (LOG_ASSEMBLY, std::format ("Looking for hash {:x} in DSO cache", hash)); arr = dso_cache; arr_size = application_config.number_of_dso_cache_entries; } @@ -102,7 +102,7 @@ namespace xamarin::android::internal if (MonodroidState::is_startup_in_progress ()) { auto ignore_component = [&](const char *label, MonoComponent component) -> bool { if ((application_config.mono_components_mask & component) != component) { - log_info (LOG_ASSEMBLY, "Mono '%s' component requested but not packaged, ignoring", label); + log_info (LOG_ASSEMBLY, std::format ("Mono '{}' component requested but not packaged, ignoring", label)); return true; } @@ -145,12 +145,12 @@ namespace xamarin::android::internal static void* monodroid_dlopen (const char *name, int flags, char **err, bool prefer_aot_cache) noexcept { if (name == nullptr) { - log_warn (LOG_ASSEMBLY, "monodroid_dlopen got a null name. This is not supported in NET+"); + log_warn (LOG_ASSEMBLY, "monodroid_dlopen got a null name. This is not supported in NET+"sv); return nullptr; } hash_t name_hash = xxhash::hash (name, strlen (name)); - log_debug (LOG_ASSEMBLY, "monodroid_dlopen: hash for name '%s' is 0x%zx", name, name_hash); + log_debug (LOG_ASSEMBLY, std::format ("monodroid_dlopen: hash for name '{}' is {:x}", name, name_hash)); DSOCacheEntry *dso = nullptr; if (prefer_aot_cache) { @@ -167,7 +167,7 @@ namespace xamarin::android::internal dso = find_only_dso_cache_entry (name_hash); } - log_debug (LOG_ASSEMBLY, "monodroid_dlopen: hash match %sfound, DSO name is '%s'", dso == nullptr ? "not " : "", dso == nullptr ? "" : dso->name); + log_debug (LOG_ASSEMBLY, std::format ("monodroid_dlopen: hash match {}found, DSO name is '{}'", dso == nullptr ? "not "sv : ""sv, dso == nullptr ? ""sv : dso->name)); if (dso == nullptr) { // DSO not known at build time, try to load it @@ -177,7 +177,7 @@ namespace xamarin::android::internal } if (dso->ignore) { - log_info (LOG_ASSEMBLY, "Request to load '%s' ignored, it is known not to exist", dso->name); + log_info (LOG_ASSEMBLY, std::format ("Request to load '{}' ignored, it is known not to exist", dso->name)); return nullptr; } diff --git a/src/native/shared/log_types.hh b/src/native/shared/log_types.hh index f6fb1142597..ff558a8185a 100644 --- a/src/native/shared/log_types.hh +++ b/src/native/shared/log_types.hh @@ -8,11 +8,7 @@ #include "java-interop-logger.h" -// We redeclare macros as real functions here -#if defined(DO_LOG) -#undef DO_LOG -#endif - +// We redeclare macros here #if defined(log_debug) #undef log_debug #endif @@ -21,15 +17,17 @@ #undef log_info #endif -namespace xamarin::android { - namespace detail { - [[gnu::always_inline]] - static inline bool _category_is_enabled (LogCategories category) noexcept - { - return (log_categories & category) == category; - } - } +#define DO_LOG_FMT(_level, _category_, _message_) \ + do { \ + if ((log_categories & ((_category_))) != 0) { \ + ::log_ ## _level ## _nocheck ((_category_), _message_); \ + } \ + } while (0) + +#define log_debug(_category_, _message_) DO_LOG_FMT (debug, (_category_), (_message_)) +#define log_info(_category_, _message_) DO_LOG_FMT (info, (_category_), (_message_)) +namespace xamarin::android { enum class LogTimingCategories : uint32_t { Default = 0, @@ -54,109 +52,79 @@ namespace xamarin::android { // A slightly faster alternative to other log functions as it doesn't parse the message // for format placeholders nor it uses variable arguments void log_write (LogCategories category, LogLevel level, const char *message) noexcept; +} - template [[gnu::always_inline]] - static inline constexpr void log_debug (LogCategories category, const char *format, Args&& ...args) noexcept - { - if (detail::_category_is_enabled (category)) { - ::log_debug_nocheck (category, format, std::forward(args)...); - } - } - - template [[gnu::always_inline]] - static inline constexpr void log_debug (LogCategories category, std::string_view const& format, Args&& ...args) noexcept - { - if (detail::_category_is_enabled (category)) { - ::log_debug_nocheck (category, format.data (), std::forward(args)...); - } - } - - static inline constexpr void log_debug (LogCategories category, std::string const& message) noexcept - { - if (detail::_category_is_enabled (category)) { - ::log_debug_nocheck (category, message.c_str ()); - } - } - - // - // This will be enabled once all log_* calls are converted to std::format format - // - // template [[gnu::always_inline]] - // static inline constexpr void log_debug (LogCategories category, std::format_string fmt, Args&& ...args) - // { - // if (detail::_category_is_enabled (category)) { - - // log_debug_nocheck (category, std::format (fmt, std::forward(args)...).c_str ()); - // } - // } - - template [[gnu::always_inline]] - static inline constexpr void log_info (LogCategories category, const char *format, Args&& ...args) noexcept - { - if (detail::_category_is_enabled (category)) { - ::log_info_nocheck (category, format, std::forward(args)...); - } - } +// +// This will be enabled once all log_* calls are converted to std::format format +// +// template [[gnu::always_inline]] +// static inline constexpr void log_debug (LogCategories category, std::format_string fmt, Args&& ...args) +// { +// if (detail::_category_is_enabled (category)) { + +// log_debug_nocheck (category, std::format (fmt, std::forward(args)...).c_str ()); +// } +// } + +[[gnu::always_inline]] +static inline constexpr void log_debug_nocheck (LogCategories category, std::string const& message) noexcept +{ + log_write (category, xamarin::android::LogLevel::Debug, message.c_str ()); +} - template [[gnu::always_inline]] - static inline constexpr void log_info (LogCategories category, std::string_view const& format, Args&& ...args) noexcept - { - if (detail::_category_is_enabled (category)) { - ::log_info_nocheck (category, format.data (), std::forward(args)...); - } - } +[[gnu::always_inline]] +static inline constexpr void log_debug_nocheck (LogCategories category, std::string_view const& message) noexcept +{ + log_write (category, xamarin::android::LogLevel::Debug, message.data ()); +} - [[gnu::always_inline]] - static inline constexpr void log_info (LogCategories category, std::string const& message) noexcept - { - if (detail::_category_is_enabled (category)) { - ::log_info_nocheck (category, message.c_str ()); - } - } +[[gnu::always_inline]] +static inline constexpr void log_info_nocheck (LogCategories category, std::string const& message) noexcept +{ + log_write (category, xamarin::android::LogLevel::Info, message.c_str ()); +} - [[gnu::always_inline]] - static inline constexpr void log_info_nocheck (LogCategories category, std::string const& message) noexcept - { - if (detail::_category_is_enabled (category)) { - ::log_info_nocheck (category, message.c_str ()); - } - } +[[gnu::always_inline]] +static inline constexpr void log_info_nocheck (LogCategories category, std::string_view const& message) noexcept +{ + log_write (category, xamarin::android::LogLevel::Info, message.data ()); +} - [[gnu::always_inline]] - static inline constexpr void log_warn (LogCategories category, std::string const& message) noexcept - { - ::log_warn (category, message.c_str ()); - } +[[gnu::always_inline]] +static inline constexpr void log_warn (LogCategories category, std::string const& message) noexcept +{ + log_write (category, xamarin::android::LogLevel::Warn, message.c_str ()); +} - [[gnu::always_inline]] - static inline constexpr void log_warn (LogCategories category, std::string_view const& message) noexcept - { - ::log_warn (category, message.data ()); - } +[[gnu::always_inline]] +static inline constexpr void log_warn (LogCategories category, std::string_view const& message) noexcept +{ + log_write (category, xamarin::android::LogLevel::Warn, message.data ()); +} - [[gnu::always_inline]] - static inline constexpr void log_error (LogCategories category, std::string const& message) noexcept - { - ::log_error (category, message.c_str ()); - } +[[gnu::always_inline]] +static inline constexpr void log_error (LogCategories category, std::string const& message) noexcept +{ + log_write (category, xamarin::android::LogLevel::Error, message.c_str ()); +} - [[gnu::always_inline]] - static inline constexpr void log_error (LogCategories category, std::string_view const& message) noexcept - { - ::log_error (category, message.data ()); - } +[[gnu::always_inline]] +static inline constexpr void log_error (LogCategories category, std::string_view const& message) noexcept +{ + log_write (category, xamarin::android::LogLevel::Error, message.data ()); +} - [[gnu::always_inline]] - static inline constexpr void log_fatal (LogCategories category, std::string const& message) noexcept - { - ::log_fatal (category, message.c_str ()); - } +[[gnu::always_inline]] +static inline constexpr void log_fatal (LogCategories category, std::string const& message) noexcept +{ + log_write (category, xamarin::android::LogLevel::Fatal, message.c_str ()); +} - [[gnu::always_inline]] - static inline constexpr void log_fatal (LogCategories category, std::string_view const& message) noexcept - { - ::log_fatal (category, message.data ()); - } +[[gnu::always_inline]] +static inline constexpr void log_fatal (LogCategories category, std::string_view const& message) noexcept +{ + log_write (category, xamarin::android::LogLevel::Fatal, message.data ()); } + extern unsigned int log_categories; #endif // ndef LOG_LEVEL_HH From 98a40548adcb9cc9ba69e2d2b1b3466fef76fd37 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Wed, 27 Nov 2024 20:51:12 +0100 Subject: [PATCH 18/54] More std::format --- .../monodroid/embedded-assemblies-zip.cc | 2 +- src/native/monodroid/internal-pinvokes.cc | 16 +-- src/native/monodroid/mono-image-loader.hh | 6 +- .../monodroid/monodroid-glue-internal.hh | 2 +- src/native/monodroid/monodroid-networkinfo.cc | 18 +-- src/native/monodroid/monodroid-tracing.cc | 2 +- .../monodroid/xamarin-android-app-context.cc | 46 +++++--- src/native/pinvoke-override/precompiled.cc | 2 +- src/native/runtime-base/internal-pinvokes.hh | 2 +- src/native/runtime-base/logger.cc | 17 ++- src/native/runtime-base/strings.hh | 8 +- src/native/runtime-base/timing-internal.cc | 6 +- src/native/runtime-base/timing-internal.hh | 4 +- src/native/runtime-base/timing.hh | 24 +--- src/native/runtime-base/util.cc | 12 +- src/native/runtime-base/util.hh | 4 +- src/native/shared/cpp-util.hh | 2 +- src/native/shared/helpers.cc | 15 +-- src/native/shared/log_functions.cc | 2 +- src/native/shared/log_types.hh | 4 +- .../debug-app-helper.cc | 103 ++++-------------- 21 files changed, 119 insertions(+), 178 deletions(-) diff --git a/src/native/monodroid/embedded-assemblies-zip.cc b/src/native/monodroid/embedded-assemblies-zip.cc index 16b2c817b64..35ef82d68f7 100644 --- a/src/native/monodroid/embedded-assemblies-zip.cc +++ b/src/native/monodroid/embedded-assemblies-zip.cc @@ -45,7 +45,7 @@ EmbeddedAssemblies::zip_load_entry_common (size_t entry_index, std::vector + #include "android-system.hh" #include "globals.hh" #include "internal-pinvokes.hh" @@ -31,30 +33,30 @@ monodroid_log (LogLevel level, LogCategories category, const char *message) switch (level) { case LogLevel::Verbose: case LogLevel::Debug: - log_debug_nocheck (category, message); + log_debug_nocheck (category, std::string_view { message }); break; case LogLevel::Info: - log_info_nocheck (category, message); + log_info_nocheck (category, std::string_view { message }); break; case LogLevel::Warn: case LogLevel::Silent: // warn is always printed - log_warn (category, message); + log_warn (category, std::string_view { message }); break; case LogLevel::Error: - log_error (category, message); + log_error (category, std::string_view { message }); break; case LogLevel::Fatal: - log_fatal (category, message); + log_fatal (category, std::string_view { message }); break; default: case LogLevel::Unknown: case LogLevel::Default: - log_info_nocheck (category, message); + log_info_nocheck (category, std::string_view { message }); break; } } @@ -156,7 +158,7 @@ _monodroid_timezone_get_default_id () const char *mutf8 = env->GetStringUTFChars (id, nullptr); if (mutf8 == nullptr) { - log_error (LOG_DEFAULT, "Failed to convert Java TimeZone ID to UTF8 (out of memory?)"); + log_error (LOG_DEFAULT, "Failed to convert Java TimeZone ID to UTF8 (out of memory?)"sv); env->DeleteLocalRef (id); env->DeleteLocalRef (d); return nullptr; diff --git a/src/native/monodroid/mono-image-loader.hh b/src/native/monodroid/mono-image-loader.hh index 783b6af679c..d843bf32188 100644 --- a/src/native/monodroid/mono-image-loader.hh +++ b/src/native/monodroid/mono-image-loader.hh @@ -110,7 +110,7 @@ namespace xamarin::android::internal { force_inline static MonoImage* stash_and_return (MonoImage *image, MonoImageOpenStatus status, [[maybe_unused]] hash_t hash) noexcept { if (image == nullptr || status != MonoImageOpenStatus::MONO_IMAGE_OK) { - log_warn (LOG_ASSEMBLY, "Failed to open assembly image. %s", mono_image_strerror (status)); + log_warn (LOG_ASSEMBLY, std::format ("Failed to open assembly image. {}", mono_image_strerror (status))); return nullptr; } @@ -119,8 +119,8 @@ namespace xamarin::android::internal { if (index < 0) { Helpers::abort_application ( LOG_ASSEMBLY, - Util::monodroid_strdup_printf ( - "Failed to look up image index for hash 0x%zx", + std::format ( + "Failed to look up image index for hash {:x}", hash ) ); diff --git a/src/native/monodroid/monodroid-glue-internal.hh b/src/native/monodroid/monodroid-glue-internal.hh index 59f00ceffd2..dbd78121458 100644 --- a/src/native/monodroid/monodroid-glue-internal.hh +++ b/src/native/monodroid/monodroid-glue-internal.hh @@ -166,7 +166,7 @@ namespace xamarin::android::internal void *symptr = MonodroidDl::monodroid_dlsym (handle, name, &err, nullptr); if (symptr == nullptr) { - log_warn (LOG_DEFAULT, "Failed to load symbol '%s' library with handle %p. %s", name, handle, err == nullptr ? "Unknown error" : err); + log_warn (LOG_DEFAULT, std::format ("Failed to load symbol '{}' library with handle {}. {}", name, handle, err == nullptr ? "Unknown error"sv : err)); fnptr = nullptr; return; } diff --git a/src/native/monodroid/monodroid-networkinfo.cc b/src/native/monodroid/monodroid-networkinfo.cc index 50267299def..f9dcba4c181 100644 --- a/src/native/monodroid/monodroid-networkinfo.cc +++ b/src/native/monodroid/monodroid-networkinfo.cc @@ -76,10 +76,10 @@ _monodroid_get_network_interface_state (const char *ifname, mono_bool *is_up, mo if (!NetworkInterface_class || !NetworkInterface_getByName) { if (!NetworkInterface_class) - log_warn (LOG_NET, "Failed to find the 'java.net.NetworkInterface' Java class"); + log_warn (LOG_NET, "Failed to find the 'java.net.NetworkInterface' Java class"sv); if (!NetworkInterface_getByName) - log_warn (LOG_NET, "Failed to find the 'java.net.NetworkInterface.getByName' function"); - log_warn (LOG_NET, "Unable to determine network interface state because of missing Java API"); + log_warn (LOG_NET, "Failed to find the 'java.net.NetworkInterface.getByName' function"sv); + log_warn (LOG_NET, "Unable to determine network interface state because of missing Java API"sv); goto leave; } @@ -88,21 +88,21 @@ _monodroid_get_network_interface_state (const char *ifname, mono_bool *is_up, mo networkInterface = env->CallStaticObjectMethod (NetworkInterface_class, NetworkInterface_getByName, NetworkInterface_nameArg); env->DeleteLocalRef (NetworkInterface_nameArg); if (env->ExceptionOccurred ()) { - log_warn (LOG_NET, "Java exception occurred while looking up the interface '%s'", ifname); + log_warn (LOG_NET, std::format ("Java exception occurred while looking up the interface '{}'", ifname)); env->ExceptionDescribe (); env->ExceptionClear (); goto leave; } if (!networkInterface) { - log_warn (LOG_NET, "Failed to look up interface '%s' using Java API", ifname); + log_warn (LOG_NET, std::format ("Failed to look up interface '{}' using Java API", ifname)); ret = FALSE; goto leave; } if (is_up) { if (!NetworkInterface_isUp) { - log_warn (LOG_NET, "Failed to find the 'java.net.NetworkInterface.isUp' function. Unable to determine interface operational state"); + log_warn (LOG_NET, "Failed to find the 'java.net.NetworkInterface.isUp' function. Unable to determine interface operational state"sv); ret = FALSE; } else *is_up = (mono_bool)env->CallBooleanMethod (networkInterface, NetworkInterface_isUp); @@ -110,7 +110,7 @@ _monodroid_get_network_interface_state (const char *ifname, mono_bool *is_up, mo if (supports_multicast) { if (!NetworkInterface_supportsMulticast) { - log_warn (LOG_NET, "Failed to find the 'java.net.NetworkInterface.supportsMulticast' function. Unable to determine whether interface supports multicast"); + log_warn (LOG_NET, "Failed to find the 'java.net.NetworkInterface.supportsMulticast' function. Unable to determine whether interface supports multicast"sv); ret = FALSE; } else *supports_multicast = (mono_bool)env->CallBooleanMethod (networkInterface, NetworkInterface_supportsMulticast); @@ -118,7 +118,7 @@ _monodroid_get_network_interface_state (const char *ifname, mono_bool *is_up, mo leave: if (!ret) - log_warn (LOG_NET, "Unable to determine interface '%s' state using Java API", ifname); + log_warn (LOG_NET, std::format ("Unable to determine interface '{}' state using Java API", ifname)); if (networkInterface != nullptr && env != nullptr) { env->DeleteLocalRef (networkInterface); @@ -143,7 +143,7 @@ int _monodroid_get_dns_servers (void **dns_servers_array) { if (!dns_servers_array) { - log_warn (LOG_NET, "Unable to get DNS servers, no location to store data in"); + log_warn (LOG_NET, "Unable to get DNS servers, no location to store data in"sv); return -1; } *dns_servers_array = nullptr; diff --git a/src/native/monodroid/monodroid-tracing.cc b/src/native/monodroid/monodroid-tracing.cc index 7b5c3d9e4f2..56db0e50dd1 100644 --- a/src/native/monodroid/monodroid-tracing.cc +++ b/src/native/monodroid/monodroid-tracing.cc @@ -27,7 +27,7 @@ MonodroidRuntime::log_traces (JNIEnv *env, TraceKind kind, const char *first_lin char *err = nullptr; void *handle = MonodroidDl::monodroid_dlopen (SharedConstants::xamarin_native_tracing_name.data (), MONO_DL_EAGER, &err, nullptr); if (handle == nullptr) { - log_warn (LOG_DEFAULT, "Failed to load native tracing library '%s'. %s", SharedConstants::xamarin_native_tracing_name, err == nullptr ? "Unknown error" : err); + log_warn (LOG_DEFAULT, std::format ("Failed to load native tracing library '{}'. {}", SharedConstants::xamarin_native_tracing_name, err == nullptr ? "Unknown error"sv : err)); } else { load_symbol (handle, "xa_get_native_backtrace", _xa_get_native_backtrace); load_symbol (handle, "xa_get_managed_backtrace", _xa_get_managed_backtrace); diff --git a/src/native/monodroid/xamarin-android-app-context.cc b/src/native/monodroid/xamarin-android-app-context.cc index 925975c336f..e55635f2443 100644 --- a/src/native/monodroid/xamarin-android-app-context.cc +++ b/src/native/monodroid/xamarin-android-app-context.cc @@ -15,7 +15,7 @@ MonodroidRuntime::get_method_name (uint32_t mono_image_index, uint32_t method_to { uint64_t id = (static_cast(mono_image_index) << 32) | method_token; - log_debug (LOG_ASSEMBLY, "MM: looking for name of method with id 0x%llx, in mono image at index %u", id, mono_image_index); + log_debug (LOG_ASSEMBLY, std::format ("MM: looking for name of method with id {:x}, in mono image at index {}", id, mono_image_index)); size_t i = 0uz; while (mm_method_names[i].id != 0) { if (mm_method_names[i].id == id) { @@ -43,15 +43,16 @@ MonodroidRuntime::get_function_pointer (uint32_t mono_image_index, uint32_t clas { log_debug ( LOG_ASSEMBLY, - "MM: Trying to look up pointer to method '%s' (token 0x%x) in class '%s' (index %u)", - get_method_name (mono_image_index, method_token), method_token, - get_class_name (class_index), class_index + std::format ("MM: Trying to look up pointer to method '{}' (token {:x}) in class '{}' (index {})", + get_method_name (mono_image_index, method_token), method_token, + get_class_name (class_index), class_index + ) ); if (class_index >= marshal_methods_number_of_classes) [[unlikely]] { Helpers::abort_application ( - Util::monodroid_strdup_printf ( - "Internal error: invalid index for class cache (expected at most %u, got %u)", + std::format ( + "Internal error: invalid index for class cache (expected at most {}, got {})", marshal_methods_number_of_classes - 1, class_index ) @@ -78,29 +79,40 @@ MonodroidRuntime::get_function_pointer (uint32_t mono_image_index, uint32_t clas target_ptr = ret; } - log_debug (LOG_ASSEMBLY, "Loaded pointer to method %s (%p) (mono_image_index == %u; class_index == %u; method_token == 0x%x)", mono_method_full_name (method, true), ret, mono_image_index, class_index, method_token); + log_debug ( + LOG_ASSEMBLY, + std::format ("Loaded pointer to method {} ({:p}) (mono_image_index == {}; class_index == {}; method_token == {:x})", + mono_method_full_name (method, true), + ret, + mono_image_index, + class_index, + method_token + ) + ); return; } log_fatal ( LOG_DEFAULT, - "Failed to obtain function pointer to method '%s' in class '%s'", - get_method_name (mono_image_index, method_token), - get_class_name (class_index) + std::format ("Failed to obtain function pointer to method '{}' in class '{}'", + get_method_name (mono_image_index, method_token), + get_class_name (class_index) + ) ); log_fatal ( LOG_DEFAULT, - "Looked for image index %u, class index %u, method token 0x%x", - mono_image_index, - class_index, - method_token + std::format ("Looked for image index {}, class index {}, method token {:x}", + mono_image_index, + class_index, + method_token + ) ); if (image == nullptr) { - log_fatal (LOG_DEFAULT, "Failed to load MonoImage for the assembly"); + log_fatal (LOG_DEFAULT, "Failed to load MonoImage for the assembly"sv); } else if (method == nullptr) { - log_fatal (LOG_DEFAULT, "Failed to load class from the assembly"); + log_fatal (LOG_DEFAULT, "Failed to load class from the assembly"sv); } const char *message = nullptr; @@ -109,7 +121,7 @@ MonodroidRuntime::get_function_pointer (uint32_t mono_image_index, uint32_t clas } Helpers::abort_application ( - message == nullptr ? "Failure to obtain marshal methods function pointer" : message + message == nullptr ? "Failure to obtain marshal methods function pointer"sv : message ); } diff --git a/src/native/pinvoke-override/precompiled.cc b/src/native/pinvoke-override/precompiled.cc index 90ad9214ecd..1ef4bbfaba0 100644 --- a/src/native/pinvoke-override/precompiled.cc +++ b/src/native/pinvoke-override/precompiled.cc @@ -67,7 +67,7 @@ PinvokeOverride::monodroid_pinvoke_override (const char *library_name, const cha load_library_entry (library_name, entrypoint_name, *entry, dotnet_dso_handle); if (entry->func == nullptr) { - log_fatal (LOG_ASSEMBLY, "Failed to load symbol '%s' from shared library '%s'", entrypoint_name, library_name); + log_fatal (LOG_ASSEMBLY, std::format ("Failed to load symbol '{}' from shared library '{}'", entrypoint_name, library_name)); return nullptr; // let Mono deal with the fallout } diff --git a/src/native/runtime-base/internal-pinvokes.hh b/src/native/runtime-base/internal-pinvokes.hh index b73e390cccf..84477577de8 100644 --- a/src/native/runtime-base/internal-pinvokes.hh +++ b/src/native/runtime-base/internal-pinvokes.hh @@ -3,7 +3,7 @@ #include #include -#include +//#include #include #include diff --git a/src/native/runtime-base/logger.cc b/src/native/runtime-base/logger.cc index 5c4be349fae..cc2f2133a97 100644 --- a/src/native/runtime-base/logger.cc +++ b/src/native/runtime-base/logger.cc @@ -27,8 +27,15 @@ namespace { FILE *f; if (path && access (path, W_OK) < 0) { - log_warn (category, "Could not open path '%s' for logging (\"%s\"). Using '%s/%s' instead.", - path, strerror (errno), override_dir, filename); + log_warn (category, + std::format ( + "Could not open path '{}' for logging (\"{}\"). Using '{}/{}' instead.", + path, + strerror (errno), + override_dir, + filename + ) + ); path = NULL; } @@ -45,7 +52,7 @@ namespace { if (f) { Util::set_world_accessable (path); } else { - log_warn (category, "Could not open path '%s' for logging: %s", path, strerror (errno)); + log_warn (category, std::format ("Could not open path '{}' for logging: {}", path, strerror (errno))); } free (p); @@ -71,12 +78,12 @@ Logger::set_debugger_log_level (const char *level) noexcept unsigned long v = strtoul (level, nullptr, 0); if (v == std::numeric_limits::max () && errno == ERANGE) { - log_error (LOG_DEFAULT, "Invalid debugger log level value '%s', expecting a positive integer or zero", level); + log_error (LOG_DEFAULT, std::format ("Invalid debugger log level value '{}', expecting a positive integer or zero", level)); return; } if (v > std::numeric_limits::max ()) { - log_warn (LOG_DEFAULT, "Debugger log level value is higher than the maximum of %u, resetting to the maximum value.", std::numeric_limits::max ()); + log_warn (LOG_DEFAULT, std::format ("Debugger log level value is higher than the maximum of {}, resetting to the maximum value.", std::numeric_limits::max ())); v = std::numeric_limits::max (); } diff --git a/src/native/runtime-base/strings.hh b/src/native/runtime-base/strings.hh index 74fe498de4c..393a3783525 100644 --- a/src/native/runtime-base/strings.hh +++ b/src/native/runtime-base/strings.hh @@ -156,7 +156,7 @@ namespace xamarin::android::internal } if (!can_access (start_index)) { - log_error (LOG_DEFAULT, "Cannot convert string to integer, index %u is out of range", start_index); + log_error (LOG_DEFAULT, std::format ("Cannot convert string to integer, index {} is out of range", start_index)); return false; } @@ -180,17 +180,17 @@ namespace xamarin::android::internal } if (out_of_range || errno == ERANGE) { - log_error (LOG_DEFAULT, "Value %s is out of range of this type (%lld..%llu)", s, static_cast(min), static_cast(max)); + log_error (LOG_DEFAULT, std::format ("Value {} is out of range of this type ({}..{})", reinterpret_cast(s), static_cast(min), static_cast(max))); return false; } if (endp == s) { - log_error (LOG_DEFAULT, "Value %s does not represent a base %d integer", s, base); + log_error (LOG_DEFAULT, std::format ("Value {} does not represent a base {} integer", reinterpret_cast(s), base)); return false; } if (*endp != '\0') { - log_error (LOG_DEFAULT, "Value %s has non-numeric characters at the end", s); + log_error (LOG_DEFAULT, std::format ("Value {} has non-numeric characters at the end", reinterpret_cast(s))); return false; } diff --git a/src/native/runtime-base/timing-internal.cc b/src/native/runtime-base/timing-internal.cc index eaaee8c17ef..7b23705d880 100644 --- a/src/native/runtime-base/timing-internal.cc +++ b/src/native/runtime-base/timing-internal.cc @@ -78,11 +78,11 @@ FastTiming::dump () noexcept log_write (LOG_TIMING, LogLevel::Info, "[2/4] Accumulated performance results"); ns_to_time (total_assembly_load_time, sec, ms, ns); - log_info_nocheck (LOG_TIMING, " [2/5] Assembly load: %u:%u::%u", sec, ms, ns); + log_info_nocheck (LOG_TIMING, std::format (" [2/5] Assembly load: {}:{}::{}", sec, ms, ns)); ns_to_time (total_java_to_managed_time, sec, ms, ns); - log_info_nocheck (LOG_TIMING, " [2/6] Java to Managed lookup: %u:%u::%u", sec, ms, ns); + log_info_nocheck (LOG_TIMING, std::format (" [2/6] Java to Managed lookup: {}:{}::{}", sec, ms, ns)); ns_to_time (total_managed_to_java_time, sec, ms, ns); - log_info_nocheck (LOG_TIMING, " [2/7] Managed to Java lookup: %u:%u::%u", sec, ms, ns); + log_info_nocheck (LOG_TIMING, std::format (" [2/7] Managed to Java lookup: {}:{}::{}", sec, ms, ns)); } diff --git a/src/native/runtime-base/timing-internal.hh b/src/native/runtime-base/timing-internal.hh index 4e896c8fc94..27cc6da274f 100644 --- a/src/native/runtime-base/timing-internal.hh +++ b/src/native/runtime-base/timing-internal.hh @@ -144,7 +144,7 @@ namespace xamarin::android::internal // likely we'll run out of memory way, way, way before that happens size_t old_size = events.capacity (); events.reserve (old_size << 1); - log_warn (LOG_TIMING, "Reallocated timing event buffer from %zu to %zu", old_size, events.size ()); + log_warn (LOG_TIMING, std::format ("Reallocated timing event buffer from {} to {}", old_size, events.size ())); } } @@ -246,7 +246,7 @@ namespace xamarin::android::internal force_inline bool is_valid_event_index (size_t index, const char *method_name) noexcept { if (index >= events.capacity ()) [[unlikely]] { - log_warn (LOG_TIMING, "Invalid event index passed to method '%s'", method_name); + log_warn (LOG_TIMING, std::format ("Invalid event index passed to method '{}'", method_name)); return false; } diff --git a/src/native/runtime-base/timing.hh b/src/native/runtime-base/timing.hh index 815e256252c..31f9892e918 100644 --- a/src/native/runtime-base/timing.hh +++ b/src/native/runtime-base/timing.hh @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -69,11 +70,9 @@ namespace xamarin::android // This class is intended to be used by the managed code. It can be used by the native code as // well, but the overhead it has (out of necessity) might not be desirable in native code. -#define TIMING_FORMAT "; elapsed: %lis:%lu::%lu" - class Timing { - static constexpr char MESSAGE_FORMAT[] = "%s" TIMING_FORMAT; + static inline constexpr std::string_view MESSAGE_FORMAT { "{}; elapsed: {}:{}::{}" }; public: static constexpr size_t DEFAULT_POOL_SIZE = 16uz; @@ -94,14 +93,14 @@ namespace xamarin::android { timing_diff diff (period); - log_info_nocheck (LOG_TIMING, MESSAGE_FORMAT, message == nullptr ? "" : message, diff.sec, diff.ms, diff.ns); + log_info_nocheck (LOG_TIMING, std::format (MESSAGE_FORMAT, message == nullptr ? ""sv : message, diff.sec, diff.ms, diff.ns)); } static void warn (timing_period const &period, const char *message) noexcept { timing_diff diff (period); - log_warn (LOG_TIMING, MESSAGE_FORMAT, message == nullptr ? "" : message, diff.sec, diff.ms, diff.ns); + log_warn (LOG_TIMING, std::format (MESSAGE_FORMAT, message == nullptr ? ""sv : message, diff.sec, diff.ms, diff.ns)); } managed_timing_sequence* get_available_sequence () noexcept @@ -147,20 +146,5 @@ namespace xamarin::android size_t sequence_pool_size; xamarin::android::mutex sequence_lock; }; - - // This is a hack to avoid having to allocate memory when rendering messages that use additional - // format placeholders on the caller side. Memory allocation would be necessary since we append - // the standard timing suffix to every message printed. Using a variadic macro allows us to - // compose a call with all the elements present and make the composition compile-time. - // - // It could be done with template packs but that would result in extra code generated whenever a - // call with a different set of parameters would be made, plus the code to implement that would - // be a bit verbose and unwieldy, so we will stick to this simple method. -#define TIMING_DO_LOG(_level, _category_, ...) ::log_ ## _level ## _nocheck ((_category_), __VA_ARGS__) - -#define TIMING_LOG_INFO(__period__, __format__, ...) { \ - timing_diff diff ((__period__)); \ - TIMING_DO_LOG (info, LOG_TIMING, __format__ TIMING_FORMAT, __VA_ARGS__, diff.sec, diff.ms, diff.ns); \ - } } #endif // __TIMING_HH diff --git a/src/native/runtime-base/util.cc b/src/native/runtime-base/util.cc index 7a58a2836c1..f7350c82ba4 100644 --- a/src/native/runtime-base/util.cc +++ b/src/native/runtime-base/util.cc @@ -149,7 +149,7 @@ Util::create_public_directory (const char *dir) mode_t m = umask (0); int ret = mkdir (dir, 0777); if (ret < 0) { - log_warn (LOG_DEFAULT, "Failed to create directory '%s'. %s", dir, std::strerror (errno)); + log_warn (LOG_DEFAULT, std::format ("Failed to create directory '{}'. {}", dir, std::strerror (errno))); } umask (m); } @@ -197,7 +197,7 @@ Util::set_world_accessable ([[maybe_unused]] const char *path) } while (r == -1 && errno == EINTR); if (r == -1) { - log_error (LOG_DEFAULT, "chmod(\"%s\", 0664) failed: %s", path, strerror (errno)); + log_error (LOG_DEFAULT, std::format ("chmod(\"{}\", 0664) failed: {}", path, strerror (errno))); } } @@ -210,7 +210,7 @@ Util::set_user_executable ([[maybe_unused]] const char *path) } while (r == -1 && errno == EINTR); if (r == -1) { - log_error (LOG_DEFAULT, "chmod(\"%s\") failed: %s", path, strerror (errno)); + log_error (LOG_DEFAULT, std::format ("chmod(\"{}\") failed: {}", path, strerror (errno))); } } @@ -240,12 +240,12 @@ bool Util::file_copy (const char *to, const char *from) { if (to == nullptr || *to == '\0') { - log_error (LOG_DEFAULT, "Util::file_copy: `to` parameter must not be null or empty"); + log_error (LOG_DEFAULT, "Util::file_copy: `to` parameter must not be null or empty"sv); return false; } if (from == nullptr || *from == '\0') { - log_error (LOG_DEFAULT, "Util::file_copy: `from` parameter must not be null or empty"); + log_error (LOG_DEFAULT, "Util::file_copy: `from` parameter must not be null or empty"sv); return false; } @@ -297,7 +297,7 @@ Util::monodroid_fopen (const char *filename, const char *mode) */ ret = fopen (filename, mode); if (ret == nullptr) { - log_error (LOG_DEFAULT, "fopen failed for file %s: %s", filename, strerror (errno)); + log_error (LOG_DEFAULT, std::format ("fopen failed for file {}: {}", filename, strerror (errno))); return nullptr; } diff --git a/src/native/runtime-base/util.hh b/src/native/runtime-base/util.hh index 97db495dbea..35eb8c3c590 100644 --- a/src/native/runtime-base/util.hh +++ b/src/native/runtime-base/util.hh @@ -79,7 +79,7 @@ namespace xamarin::android { struct stat sbuf; if (fstatat (dirfd, file_name, &sbuf, 0) == -1) { - log_warn (LOG_ASSEMBLY, "Failed to stat file '%s': %s", file_name, std::strerror (errno)); + log_warn (LOG_ASSEMBLY, std::format ("Failed to stat file '{}': {}", file_name, std::strerror (errno))); return std::nullopt; } @@ -90,7 +90,7 @@ namespace xamarin::android { int fd = openat (dirfd, file_name, O_RDONLY); if (fd < 0) { - log_error (LOG_ASSEMBLY, "Failed to open file '%s' for reading: %s", file_name, std::strerror (errno)); + log_error (LOG_ASSEMBLY, std::format ("Failed to open file '{}' for reading: {}", file_name, std::strerror (errno))); return std::nullopt; } diff --git a/src/native/shared/cpp-util.hh b/src/native/shared/cpp-util.hh index f893d6614e3..8c2397218f5 100644 --- a/src/native/shared/cpp-util.hh +++ b/src/native/shared/cpp-util.hh @@ -83,7 +83,7 @@ abort_if_negative_integer_argument (int arg, const char *arg_name, std::source_l // of the calls present. force_inline inline void pd_log_location (std::source_location sloc = std::source_location::current ()) noexcept { - log_info_nocheck (LOG_DEFAULT, "loc: %s:%u ('%s')", sloc.file_name (), sloc.line (), sloc.function_name ()); + log_info_nocheck (LOG_DEFAULT, std::format ("loc: {}:{} ('{}')", sloc.file_name (), sloc.line (), sloc.function_name ())); } namespace xamarin::android diff --git a/src/native/shared/helpers.cc b/src/native/shared/helpers.cc index bf8a8bd5339..645f30e0d84 100644 --- a/src/native/shared/helpers.cc +++ b/src/native/shared/helpers.cc @@ -3,7 +3,7 @@ #include #include "helpers.hh" -#include "java-interop-logger.h" +#include "log_types.hh" using namespace xamarin::android; @@ -11,7 +11,7 @@ using namespace xamarin::android; Helpers::abort_application (LogCategories category, const char *message, bool log_location, std::source_location sloc) noexcept { // Log it, but also... - log_fatal (category, message); + log_fatal (category, std::string_view { message }); // ...let android include it in the tombstone, debuggerd output, stack trace etc android_set_abort_message (message); @@ -35,11 +35,12 @@ Helpers::abort_application (LogCategories category, const char *message, bool lo log_fatal ( category, - "Abort at %s:%u:%u ('%s')", - file_name, - sloc.line (), - sloc.column (), - sloc.function_name () + std::format ("Abort at {}:{}:{} ('%s')", + file_name, + sloc.line (), + sloc.column (), + sloc.function_name () + ) ); } std::abort (); diff --git a/src/native/shared/log_functions.cc b/src/native/shared/log_functions.cc index 114bc0186e7..e82f2bd5856 100644 --- a/src/native/shared/log_functions.cc +++ b/src/native/shared/log_functions.cc @@ -3,7 +3,7 @@ #include -#include "java-interop-logger.h" +//#include "java-interop-logger.h" #include "log_types.hh" // Must match the same ordering as LogCategories diff --git a/src/native/shared/log_types.hh b/src/native/shared/log_types.hh index ff558a8185a..31a1b22dac0 100644 --- a/src/native/shared/log_types.hh +++ b/src/native/shared/log_types.hh @@ -1,5 +1,4 @@ -#if !defined(LOG_LEVEL_HH) -#define LOG_LEVEL_HH +#pragma once #include #include @@ -127,4 +126,3 @@ static inline constexpr void log_fatal (LogCategories category, std::string_view } extern unsigned int log_categories; -#endif // ndef LOG_LEVEL_HH diff --git a/src/native/xamarin-debug-app-helper/debug-app-helper.cc b/src/native/xamarin-debug-app-helper/debug-app-helper.cc index e083f905ab4..ae8c2cd4bc6 100644 --- a/src/native/xamarin-debug-app-helper/debug-app-helper.cc +++ b/src/native/xamarin-debug-app-helper/debug-app-helper.cc @@ -14,33 +14,17 @@ #include "debug-app-helper.hh" #include "shared-constants.hh" #include "jni-wrappers.hh" +#include "log_types.hh" using namespace xamarin::android; using namespace xamarin::android::internal; -#undef DO_LOG -#undef log_info - -void log_info (LogCategories category, const char *format, ...); -void log_warn (LogCategories category, const char *format, ...); -void log_error (LogCategories category, const char *format, ...); -void log_fatal (LogCategories category, const char *format, ...); - static void copy_file_to_internal_location (char *to_dir, char *from_dir, char *file); static void copy_native_libraries_to_internal_location (); static const char* get_libmonosgen_path (); bool maybe_load_library (const char *path); -#define DO_LOG(_level_,_tag_,_format_,_args_) \ - va_start ((_args_), (_format_)); \ - __android_log_vprint ((_level_), (_tag_), (_format_), (_args_)); \ - va_end ((_args_)); - -static constexpr char TAG[] = "debug-app-helper"; - -unsigned int log_categories = LOG_DEFAULT | LOG_ASSEMBLY; - JNIEXPORT jint JNICALL JNI_OnLoad ([[maybe_unused]] JavaVM *vm, [[maybe_unused]] void *reserved) { @@ -64,7 +48,7 @@ Java_mono_android_DebugRuntime_init (JNIEnv *env, [[maybe_unused]] jclass klass, if (runtimeNativeLibDir != nullptr) { jstr = runtimeNativeLibDir; AndroidSystem::set_runtime_libdir (Util::strdup_new (jstr.get_cstr ())); - log_warn (LOG_DEFAULT, "Using runtime path: %s", AndroidSystem::get_runtime_libdir ()); + log_warn (LOG_DEFAULT, std::format ("Using runtime path: {}", AndroidSystem::get_runtime_libdir ())); } const char *monosgen_path = get_libmonosgen_path (); @@ -89,8 +73,12 @@ copy_file_to_internal_location (char *to_dir, char *from_dir, char *file) if (!from_file || !Util::file_exists (from_file)) break; - log_warn (LOG_DEFAULT, "Copying file `%s` from external location `%s` to internal location `%s`", - file, from_dir, to_dir); + log_warn (LOG_DEFAULT, + std::format ( + "Copying file `{}` from external location `{}` to internal location `{}`", + file, from_dir, to_dir + ) + ); to_file = Util::path_combine (to_dir, file); if (!to_file) @@ -98,12 +86,12 @@ copy_file_to_internal_location (char *to_dir, char *from_dir, char *file) int r = unlink (to_file); if (r < 0 && errno != ENOENT) { - log_warn (LOG_DEFAULT, "Unable to delete file `%s`: %s", to_file, strerror (errno)); + log_warn (LOG_DEFAULT, std::format ("Unable to delete file `{}`: {}", to_file, strerror (errno))); break; } if (!Util::file_copy (to_file, from_file)) { - log_warn (LOG_DEFAULT, "Copy failed from `%s` to `%s`: %s", from_file, to_file, strerror (errno)); + log_warn (LOG_DEFAULT, std::format ("Copy failed from `{}` to `{}`: {}", from_file, to_file, strerror (errno))); break; } @@ -122,22 +110,22 @@ copy_native_libraries_to_internal_location () dirent *e; char *dir_path = Util::path_combine (od, "lib"); - log_warn (LOG_DEFAULT, "checking directory: `%s`", dir_path); + log_warn (LOG_DEFAULT, std::format ("checking directory: `{}`", dir_path)); if (dir_path == nullptr || !Util::directory_exists (dir_path)) { - log_warn (LOG_DEFAULT, "directory does not exist: `%s`", dir_path); + log_warn (LOG_DEFAULT, std::format ("directory does not exist: `{}`", dir_path)); delete[] dir_path; continue; } if ((dir = ::opendir (dir_path)) == nullptr) { - log_warn (LOG_DEFAULT, "could not open directory: `%s`", dir_path); + log_warn (LOG_DEFAULT, std::format ("could not open directory: `{}`", dir_path)); delete[] dir_path; continue; } while ((e = readdir (dir)) != nullptr) { - log_warn (LOG_DEFAULT, "checking file: `%s`", e->d_name); + log_warn (LOG_DEFAULT, std::format ("checking file: `{}`", e->d_name)); if (Util::monodroid_dirent_hasextension (e, ".so")) { copy_file_to_internal_location (AndroidSystem::get_primary_override_dir (), dir_path, e->d_name); } @@ -154,9 +142,9 @@ runtime_exists (const char *dir, char*& libmonoso) return false; libmonoso = Util::path_combine (dir, SharedConstants::MONO_SGEN_SO); - log_warn (LOG_DEFAULT, "Checking whether Mono runtime exists at: %s", libmonoso); + log_warn (LOG_DEFAULT, std::format ("Checking whether Mono runtime exists at: {}", libmonoso)); if (Util::file_exists (libmonoso)) { - log_info (LOG_DEFAULT, "Mono runtime found at: %s", libmonoso); + log_info (LOG_DEFAULT, std::format ("Mono runtime found at: {}", libmonoso)); return true; } delete[] libmonoso; @@ -208,25 +196,25 @@ get_libmonosgen_path () if (!Util::file_exists (link)) { int result = symlink (libmonoso, link); if (result != 0 && errno == EEXIST) { - log_warn (LOG_DEFAULT, "symlink exists, recreating: %s -> %s", link, libmonoso); + log_warn (LOG_DEFAULT, std::format ("symlink exists, recreating: {} -> {}", link, libmonoso)); unlink (link); result = symlink (libmonoso, link); } if (result != 0) - log_warn (LOG_DEFAULT, "symlink failed with errno=%i %s", errno, strerror (errno)); + log_warn (LOG_DEFAULT, std::format ("symlink failed with errno={} {}", errno, strerror (errno))); } delete[] libmonoso; libmonoso = link; } - log_warn (LOG_DEFAULT, "Trying to load sgen from: %s", libmonoso != nullptr ? libmonoso : ""); + log_warn (LOG_DEFAULT, std::format ("Trying to load sgen from: {}", libmonoso != nullptr ? libmonoso : ""sv)); if (libmonoso != nullptr && Util::file_exists (libmonoso)) return libmonoso; delete[] libmonoso; if (runtime_exists (AndroidSystem::SYSTEM_LIB_PATH.data (), libmonoso)) return libmonoso; - log_fatal (LOG_DEFAULT, "Cannot find '%s'. Looked in the following locations:", SharedConstants::MONO_SGEN_SO); + log_fatal (LOG_DEFAULT, std::format ("Cannot find '{}'. Looked in the following locations:", SharedConstants::MONO_SGEN_SO)); for (const char *od : AndroidSystem::override_dirs) { if (od == nullptr) @@ -245,54 +233,3 @@ get_libmonosgen_path () return libmonoso; } - -void -log_debug_nocheck ([[maybe_unused]] LogCategories category, const char *format, ...) -{ - va_list args; - - if ((log_categories & category) == 0) - return; - - DO_LOG (ANDROID_LOG_DEBUG, TAG, format, args); -} - -void -log_info ([[maybe_unused]] LogCategories category, const char *format, ...) -{ - va_list args; - - DO_LOG (ANDROID_LOG_INFO, TAG, format, args); -} - -void -log_info_nocheck ([[maybe_unused]] LogCategories category, const char *format, ...) -{ - va_list args; - - if ((log_categories & category) == 0) - return; - - DO_LOG (ANDROID_LOG_INFO, TAG, format, args); -} - -void log_error ([[maybe_unused]] LogCategories category, const char* format, ...) -{ - va_list args; - - DO_LOG (ANDROID_LOG_ERROR, TAG, format, args); -} - -void log_fatal ([[maybe_unused]] LogCategories category, const char* format, ...) -{ - va_list args; - - DO_LOG (ANDROID_LOG_FATAL, TAG, format, args); -} - -void log_warn ([[maybe_unused]] LogCategories category, const char* format, ...) -{ - va_list args; - - DO_LOG (ANDROID_LOG_WARN, TAG, format, args); -} From ac5c3edc044123492390a42e835a7ed0485c267d Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Thu, 28 Nov 2024 17:17:26 +0100 Subject: [PATCH 19/54] Friendlier, no need to use `std::format` directly in log_* anymore --- src/native/monodroid/debug.cc | 61 +++---- .../monodroid/embedded-assemblies-zip.cc | 69 ++++--- src/native/monodroid/embedded-assemblies.cc | 171 +++++++++--------- src/native/monodroid/embedded-assemblies.hh | 6 +- .../monodroid/monodroid-glue-internal.hh | 2 +- src/native/monodroid/monodroid-glue.cc | 73 ++++---- src/native/monodroid/monodroid-networkinfo.cc | 6 +- src/native/monodroid/monodroid-tracing.cc | 2 +- src/native/monodroid/osbridge.cc | 160 ++++++++-------- .../monodroid/xamarin-android-app-context.cc | 38 ++-- src/native/monodroid/xamarin_getifaddrs.cc | 56 +++--- .../pinvoke-override-api-impl.hh | 12 +- src/native/pinvoke-override/precompiled.cc | 8 +- src/native/runtime-base/android-system.cc | 64 +++---- src/native/runtime-base/logger.cc | 1 + src/native/runtime-base/monodroid-dl.hh | 12 +- src/native/runtime-base/strings.hh | 8 +- src/native/runtime-base/timing-internal.cc | 6 +- src/native/runtime-base/timing-internal.hh | 4 +- src/native/runtime-base/timing.hh | 4 +- src/native/runtime-base/util.cc | 8 +- src/native/runtime-base/util.hh | 4 +- src/native/shared/cpp-util.hh | 2 +- src/native/shared/helpers.cc | 13 +- src/native/shared/log_functions.cc | 4 +- src/native/shared/log_level.hh | 26 +++ src/native/shared/log_types.hh | 94 ++++------ .../debug-app-helper.cc | 32 ++-- 28 files changed, 459 insertions(+), 487 deletions(-) create mode 100644 src/native/shared/log_level.hh diff --git a/src/native/monodroid/debug.cc b/src/native/monodroid/debug.cc index 7aa2ec6abb2..cbcdeec2e87 100644 --- a/src/native/monodroid/debug.cc +++ b/src/native/monodroid/debug.cc @@ -95,10 +95,9 @@ Debug::monodroid_profiler_load (const char *libmono_path, const char *desc, cons if (!found) log_warn (LOG_DEFAULT, - std::format ("The '{}' profiler wasn't found in the main executable nor could it be loaded from '{}'.", - mname.get (), - libname.get () - ) + "The '{}' profiler wasn't found in the main executable nor could it be loaded from '{}'.", + mname.get (), + libname.get () ); } @@ -110,7 +109,7 @@ bool Debug::load_profiler (void *handle, const char *desc, const char *symbol) { ProfilerInitializer func = reinterpret_cast (java_interop_lib_symbol (handle, symbol, nullptr)); - log_warn (LOG_DEFAULT, std::format ("Looking for profiler init symbol '{}'? {:p}", symbol, reinterpret_cast(func))); + log_warn (LOG_DEFAULT, "Looking for profiler init symbol '{}'? {:p}", symbol, reinterpret_cast(func)); if (func != nullptr) { func (desc); @@ -140,7 +139,7 @@ Debug::parse_options (char *options, ConnOptions *opts) { char **args, **ptr; - log_info (LOG_DEFAULT, std::format ("Connection options: '{}'", options)); + log_info (LOG_DEFAULT, "Connection options: '{}'", options); args = Util::monodroid_strsplit (options, ",", 0); @@ -150,12 +149,12 @@ Debug::parse_options (char *options, ConnOptions *opts) if (strstr (arg, "port=") == arg) { int port = atoi (arg + strlen ("port=")); if (port < 0 || port > std::numeric_limits::max ()) { - log_error (LOG_DEFAULT, std::format ("Invalid debug port value {}", port)); + log_error (LOG_DEFAULT, "Invalid debug port value {}", port); continue; } conn_port = static_cast(port); - log_info (LOG_DEFAULT, std::format ("XS port = {}", conn_port)); + log_info (LOG_DEFAULT, "XS port = {}", conn_port); } else if (strstr (arg, "timeout=") == arg) { char *endp; @@ -164,7 +163,7 @@ Debug::parse_options (char *options, ConnOptions *opts) if ((endp == arg) || (*endp != '\0')) log_error (LOG_DEFAULT, "Invalid --timeout argument."sv); } else { - log_info (LOG_DEFAULT, std::format ("Unknown connection option: '{}'", arg)); + log_info (LOG_DEFAULT, "Unknown connection option: '{}'", arg); } } } @@ -188,7 +187,7 @@ Debug::start_connection (char *options) cur_time = time (nullptr); if (opts.timeout_time && cur_time > opts.timeout_time) { - log_warn (LOG_DEBUGGER, std::format ("Not connecting to IDE as the timeout value has been reached; current-time: {} timeout: {}", cur_time, opts.timeout_time)); + log_warn (LOG_DEBUGGER, "Not connecting to IDE as the timeout value has been reached; current-time: {} timeout: {}", cur_time, opts.timeout_time); return DebuggerConnectionStatus::Unconnected; } @@ -199,7 +198,7 @@ Debug::start_connection (char *options) res = pthread_create (&conn_thread_id, nullptr, xamarin::android::conn_thread, this); if (res) { - log_error (LOG_DEFAULT, std::format ("Failed to create connection thread: {}", strerror (errno))); + log_error (LOG_DEFAULT, "Failed to create connection thread: {}", strerror (errno)); return DebuggerConnectionStatus::Error; } @@ -263,20 +262,20 @@ Debug::process_connection (int fd) return false; } if (rv <= 0) { - log_info (LOG_DEFAULT, std::format ("Error while receiving command from XS ({})", strerror (errno))); + log_info (LOG_DEFAULT, "Error while receiving command from XS ({})", strerror (errno)); return false; } rv = Util::recv_uninterrupted (fd, command, cmd_len); if (rv <= 0) { - log_info (LOG_DEFAULT, std::format ("Error while receiving command from XS ({})", strerror (errno))); + log_info (LOG_DEFAULT, "Error while receiving command from XS ({})", strerror (errno)); return false; } // null-terminate command [cmd_len] = 0; - log_info (LOG_DEFAULT, std::format ("Received cmd: '{}'.", command)); + log_info (LOG_DEFAULT, "Received cmd: '{}'.", command); if (process_cmd (fd, command)) return true; @@ -288,14 +287,14 @@ Debug::handle_server_connection (void) { int listen_socket = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP); if (listen_socket == -1) { - log_info (LOG_DEFAULT, std::format ("Could not create socket for XS to connect to: {}", strerror (errno))); + log_info (LOG_DEFAULT, "Could not create socket for XS to connect to: {}", strerror (errno)); return 1; } int flags = 1; int rv = setsockopt (listen_socket, SOL_SOCKET, SO_REUSEADDR, &flags, sizeof (flags)); if (rv == -1 && Util::should_log (LOG_DEFAULT)) { - log_info_nocheck (LOG_DEFAULT, std::format ("Could not set SO_REUSEADDR on the listening socket ({})", strerror (errno))); + log_info_nocheck_fmt (LOG_DEFAULT, "Could not set SO_REUSEADDR on the listening socket ({})", strerror (errno)); // not a fatal failure } @@ -309,7 +308,7 @@ Debug::handle_server_connection (void) listen_addr.sin_addr.s_addr = INADDR_ANY; rv = bind (listen_socket, (struct sockaddr *) &listen_addr, sizeof (listen_addr)); if (rv == -1) { - log_info (LOG_DEFAULT, std::format ("Could not bind to address: {}", strerror (errno))); + log_info (LOG_DEFAULT, "Could not bind to address: {}", strerror (errno)); rv = 2; goto cleanup; } @@ -321,7 +320,7 @@ Debug::handle_server_connection (void) rv = listen (listen_socket, 1); if (rv == -1) { - log_info (LOG_DEFAULT, std::format ("Could not listen for XS: {}", strerror (errno))); + log_info (LOG_DEFAULT, "Could not listen for XS: {}", strerror (errno)); rv = 2; goto cleanup; } @@ -371,7 +370,7 @@ Debug::handle_server_connection (void) } while (rv == -1 && errno == EINTR); if (rv == -1) { - log_info (LOG_DEFAULT, std::format ("Failed while waiting for XS to connect: {}", strerror (errno))); + log_info (LOG_DEFAULT, "Failed while waiting for XS to connect: {}", strerror (errno)); rv = 2; goto cleanup; } @@ -379,18 +378,18 @@ Debug::handle_server_connection (void) socklen_t len = sizeof (struct sockaddr_in); int fd = accept (listen_socket, (struct sockaddr *) &listen_addr, &len); if (fd == -1) { - log_info (LOG_DEFAULT, std::format ("Failed to accept connection from XS: {}", strerror (errno))); + log_info (LOG_DEFAULT, "Failed to accept connection from XS: {}", strerror (errno)); rv = 3; goto cleanup; } flags = 1; if (setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, (char *) &flags, sizeof (flags)) < 0) { - log_info (LOG_DEFAULT, std::format ("Could not set TCP_NODELAY on socket ({})", strerror (errno))); + log_info (LOG_DEFAULT, "Could not set TCP_NODELAY on socket ({})", strerror (errno)); // not a fatal failure } - log_info (LOG_DEFAULT, std::format ("Successfully received connection from XS on port {}, fd: {}", listen_port, fd)); + log_info (LOG_DEFAULT, "Successfully received connection from XS on port {}, fd: {}", listen_port, fd); need_new_conn = process_connection (fd); } @@ -442,7 +441,7 @@ Debug::process_cmd (int fd, char *cmd) constexpr std::string_view PONG_REPLY { "pong" }; if (strcmp (cmd, PING_CMD.data ()) == 0) { if (!Util::send_uninterrupted (fd, const_cast (reinterpret_cast (PONG_REPLY.data ())), 5)) - log_error (LOG_DEFAULT, std::format ("Got keepalive request from XS, but could not send response back ({})", strerror (errno))); + log_error (LOG_DEFAULT, "Got keepalive request from XS, but could not send response back ({})", strerror (errno)); return false; } @@ -488,7 +487,7 @@ Debug::process_cmd (int fd, char *cmd) profiler_fd = fd; profiler_description = Util::monodroid_strdup_printf ("%s,output=#%i", prof, profiler_fd); } else { - log_error (LOG_DEFAULT, std::format ("Unknown profiler: '{}'", prof)); + log_error (LOG_DEFAULT, "Unknown profiler: '{}'", prof); } /* Notify the main thread (start_profiling ()) */ profiler_configured = true; @@ -497,7 +496,7 @@ Debug::process_cmd (int fd, char *cmd) pthread_mutex_unlock (&process_cmd_mutex); return use_fd; } else { - log_error (LOG_DEFAULT, std::format ("Unsupported command: '{}'", cmd)); + log_error (LOG_DEFAULT, "Unsupported command: '{}'", cmd); } return false; @@ -527,7 +526,7 @@ Debug::start_debugging (void) // this text is used in unit tests to check the debugger started // do not change it without updating the test. - log_warn (LOG_DEBUGGER, std::format ("Trying to initialize the debugger with options: {}", debug_arg)); + log_warn (LOG_DEBUGGER, "Trying to initialize the debugger with options: {}", debug_arg); if (enable_soft_breakpoints ()) { constexpr std::string_view soft_breakpoints { "--soft-breakpoints" }; @@ -554,7 +553,7 @@ Debug::start_profiling () if (!profiler_description) return; - log_info (LOG_DEFAULT, std::format ("Loading profiler: '{}'", profiler_description)); + log_info (LOG_DEFAULT, "Loading profiler: '{}'", profiler_description); monodroid_profiler_load (AndroidSystem::get_runtime_libdir (), profiler_description, nullptr); } @@ -574,7 +573,7 @@ Debug::enable_soft_breakpoints (void) uname (&name); for (const char** ptr = soft_breakpoint_kernel_list; *ptr; ptr++) { if (strcmp (name.release, *ptr) == 0) { - log_info (LOG_DEBUGGER, std::format ("soft breakpoints enabled due to kernel version match ({})", name.release)); + log_info (LOG_DEBUGGER, "soft breakpoints enabled due to kernel version match ({})", name.release); return 1; } } @@ -582,17 +581,17 @@ Debug::enable_soft_breakpoints (void) char *value; /* Soft breakpoints are enabled by default */ if (AndroidSystem::monodroid_get_system_property (SharedConstants::DEBUG_MONO_SOFT_BREAKPOINTS, &value) <= 0) { - log_info (LOG_DEBUGGER, std::format ("soft breakpoints enabled by default ({} property not defined)", SharedConstants::DEBUG_MONO_SOFT_BREAKPOINTS.data ())); + log_info (LOG_DEBUGGER, "soft breakpoints enabled by default ({} property not defined)", SharedConstants::DEBUG_MONO_SOFT_BREAKPOINTS.data ()); return 1; } bool ret; if (strcmp ("0", value) == 0) { ret = false; - log_info (LOG_DEBUGGER, std::format ("soft breakpoints disabled ({} property set to {})", SharedConstants::DEBUG_MONO_SOFT_BREAKPOINTS.data (), value)); + log_info (LOG_DEBUGGER, "soft breakpoints disabled ({} property set to {})", SharedConstants::DEBUG_MONO_SOFT_BREAKPOINTS.data (), value); } else { ret = true; - log_info (LOG_DEBUGGER, std::format ("soft breakpoints enabled ({} property set to {})", SharedConstants::DEBUG_MONO_SOFT_BREAKPOINTS.data (), value)); + log_info (LOG_DEBUGGER, "soft breakpoints enabled ({} property set to {})", SharedConstants::DEBUG_MONO_SOFT_BREAKPOINTS.data (), value); } delete[] value; return ret; diff --git a/src/native/monodroid/embedded-assemblies-zip.cc b/src/native/monodroid/embedded-assemblies-zip.cc index 35ef82d68f7..2497cab1c83 100644 --- a/src/native/monodroid/embedded-assemblies-zip.cc +++ b/src/native/monodroid/embedded-assemblies-zip.cc @@ -22,7 +22,7 @@ EmbeddedAssemblies::zip_load_entry_common (size_t entry_index, std::vector } auto [payload_start, payload_size] = get_wrapper_dso_payload_pointer_and_size (assembly_store_map, entry_name.get ()); - log_debug (LOG_ASSEMBLY, std::format ("Adjusted assembly store pointer: {:p}; size: {}", payload_start, payload_size)); + log_debug (LOG_ASSEMBLY, "Adjusted assembly store pointer: {:p}; size: {}", payload_start, payload_size); auto header = static_cast(payload_start); if (header->magic != ASSEMBLY_STORE_MAGIC) { @@ -264,7 +262,7 @@ EmbeddedAssemblies::zip_load_assembly_store_entries (std::vector const& dynamic_local_string entry_name; bool assembly_store_found = false; - log_debug (LOG_ASSEMBLY, std::format ("Looking for assembly stores in APK ('{}')", assembly_store_file_path.data ())); + log_debug (LOG_ASSEMBLY, "Looking for assembly stores in APK ('{}')", assembly_store_file_path.data ()); for (size_t i = 0uz; i < num_entries; i++) { if (all_required_zip_entries_found ()) { need_to_scan_more_apks = false; @@ -300,14 +298,12 @@ EmbeddedAssemblies::zip_load_assembly_store_entries (std::vector const& log_debug ( LOG_ASSEMBLY, - std::format ( - "Found a shared library entry {} (index: {}; name: {}; hash: {:x}; apk offset: {})", - entry_name.get (), - number_of_zip_dso_entries, - name, - apk_entry->name_hash, - apk_entry->offset - ) + "Found a shared library entry {} (index: {}; name: {}; hash: {:x}; apk offset: {})", + entry_name.get (), + number_of_zip_dso_entries, + name, + apk_entry->name_hash, + apk_entry->offset ); number_of_zip_dso_entries++; } @@ -331,9 +327,9 @@ EmbeddedAssemblies::zip_load_entries (int fd, const char *apk_name, [[maybe_unus ); } #ifdef DEBUG - log_info (LOG_ASSEMBLY, std::format ("Central directory offset: {}", cd_offset)); - log_info (LOG_ASSEMBLY, std::format ("Central directory size: {}", cd_size)); - log_info (LOG_ASSEMBLY, std::format ("Central directory entries: {}", cd_entries)); + log_info (LOG_ASSEMBLY, "Central directory offset: {}", cd_offset); + log_info (LOG_ASSEMBLY, "Central directory size: {}", cd_size); + log_info (LOG_ASSEMBLY, "Central directory entries: {}", cd_entries); #endif off_t retval = ::lseek (fd, static_cast(cd_offset), SEEK_SET); if (retval < 0) { @@ -411,9 +407,8 @@ EmbeddedAssemblies::set_entry_data (XamarinAndroidBundledAssembly &entry, ZipEnt log_debug ( LOG_ASSEMBLY, - std::format ("Set bundled assembly entry data. file name: '{}'; entry name: '{}'; data size: {}", - entry.file_name, entry.name, entry.data_size - ) + "Set bundled assembly entry data. file name: '{}'; entry name: '{}'; data size: {}", + entry.file_name, entry.name, entry.data_size ); } @@ -435,14 +430,14 @@ EmbeddedAssemblies::zip_read_cd_info (int fd, uint32_t& cd_offset, uint32_t& cd_ // The simplest case - no file comment off_t ret = ::lseek (fd, -ZIP_EOCD_LEN, SEEK_END); if (ret < 0) { - log_error (LOG_ASSEMBLY, std::format ("Unable to seek into the APK to find ECOD: {} (ret: {}; errno: {})", std::strerror (errno), ret, errno)); + log_error (LOG_ASSEMBLY, "Unable to seek into the APK to find ECOD: {} (ret: {}; errno: {})", std::strerror (errno), ret, errno); return false; } std::array eocd; ssize_t nread = ::read (fd, eocd.data (), eocd.size ()); if (nread < 0 || nread != eocd.size ()) { - log_error (LOG_ASSEMBLY, std::format ("Failed to read EOCD from the APK: {} (nread: {}; errno: {})", std::strerror (errno), nread, errno)); + log_error (LOG_ASSEMBLY, "Failed to read EOCD from the APK: {} (nread: {}; errno: {})", std::strerror (errno), nread, errno); return false; } @@ -462,7 +457,7 @@ EmbeddedAssemblies::zip_read_cd_info (int fd, uint32_t& cd_offset, uint32_t& cd_ constexpr size_t alloc_size = 65535uz + ZIP_EOCD_LEN; // 64k is the biggest comment size allowed ret = ::lseek (fd, static_cast(-alloc_size), SEEK_END); if (ret < 0) { - log_error (LOG_ASSEMBLY, std::format ("Unable to seek into the file to find ECOD before APK comment: {} (ret: {}; errno: {})", std::strerror (errno), ret, errno)); + log_error (LOG_ASSEMBLY, "Unable to seek into the file to find ECOD before APK comment: {} (ret: {}; errno: {})", std::strerror (errno), ret, errno); return false; } @@ -471,7 +466,7 @@ EmbeddedAssemblies::zip_read_cd_info (int fd, uint32_t& cd_offset, uint32_t& cd_ nread = ::read (fd, buf.data (), buf.size ()); if (nread < 0 || static_cast(nread) != alloc_size) { - log_error (LOG_ASSEMBLY, std::format ("Failed to read EOCD and comment from the APK: {} (nread: {}; errno: {})", std::strerror (errno), nread, errno)); + log_error (LOG_ASSEMBLY, "Failed to read EOCD and comment from the APK: {} (nread: {}; errno: {})", std::strerror (errno), nread, errno); return false; } @@ -505,10 +500,8 @@ EmbeddedAssemblies::zip_adjust_data_offset (int fd, ZipEntryLoadState &state) no if (result < 0) { log_error ( LOG_ASSEMBLY, - std::format ( - "Failed to seek to archive entry local header at offset {}. {} (result: {}; errno: {})", - state.local_header_offset, std::strerror (errno), result, errno - ) + "Failed to seek to archive entry local header at offset {}. {} (result: {}; errno: {})", + state.local_header_offset, std::strerror (errno), result, errno ); return false; } @@ -518,32 +511,32 @@ EmbeddedAssemblies::zip_adjust_data_offset (int fd, ZipEntryLoadState &state) no ssize_t nread = ::read (fd, local_header.data (), local_header.size ()); if (nread < 0 || nread != ZIP_LOCAL_LEN) { - log_error (LOG_ASSEMBLY, std::format ("Failed to read local header at offset {}: {} (nread: {}; errno: {})", state.local_header_offset, std::strerror (errno), nread, errno)); + log_error (LOG_ASSEMBLY, "Failed to read local header at offset {}: {} (nread: {}; errno: {})", state.local_header_offset, std::strerror (errno), nread, errno); return false; } size_t index = 0; if (!zip_read_field (local_header, index, signature)) { - log_error (LOG_ASSEMBLY, std::format ("Failed to read Local Header entry signature at offset {}", state.local_header_offset)); + log_error (LOG_ASSEMBLY, "Failed to read Local Header entry signature at offset {}", state.local_header_offset); return false; } if (memcmp (signature.data (), ZIP_LOCAL_MAGIC.data (), signature.size ()) != 0) { - log_error (LOG_ASSEMBLY, std::format ("Invalid Local Header entry signature at offset {}", state.local_header_offset)); + log_error (LOG_ASSEMBLY, "Invalid Local Header entry signature at offset {}", state.local_header_offset); return false; } uint16_t file_name_length; index = LH_FILE_NAME_LENGTH_OFFSET; if (!zip_read_field (local_header, index, file_name_length)) { - log_error (LOG_ASSEMBLY, std::format ("Failed to read Local Header 'file name length' field at offset {}", (state.local_header_offset + index))); + log_error (LOG_ASSEMBLY, "Failed to read Local Header 'file name length' field at offset {}", (state.local_header_offset + index)); return false; } uint16_t extra_field_length; index = LH_EXTRA_LENGTH_OFFSET; if (!zip_read_field (local_header, index, extra_field_length)) { - log_error (LOG_ASSEMBLY, std::format ("Failed to read Local Header 'extra field length' field at offset {}", (state.local_header_offset + index))); + log_error (LOG_ASSEMBLY, "Failed to read Local Header 'extra field length' field at offset {}", (state.local_header_offset + index)); return false; } @@ -585,7 +578,7 @@ force_inline bool EmbeddedAssemblies::zip_ensure_valid_params (T const& buf, size_t index, size_t to_read) noexcept { if (index + to_read > buf.size ()) { - log_error (LOG_ASSEMBLY, std::format ("Buffer too short to read {} bytes of data", to_read)); + log_error (LOG_ASSEMBLY, "Buffer too short to read {} bytes of data", to_read); return false; } diff --git a/src/native/monodroid/embedded-assemblies.cc b/src/native/monodroid/embedded-assemblies.cc index d03e99cc44e..c868da14469 100644 --- a/src/native/monodroid/embedded-assemblies.cc +++ b/src/native/monodroid/embedded-assemblies.cc @@ -130,7 +130,7 @@ EmbeddedAssemblies::get_assembly_data (uint8_t *data, uint32_t data_size, [[mayb ) ); } else { - log_debug (LOG_ASSEMBLY, std::format ("Compressed assembly '{}' is smaller than when the application was built. Adjusting accordingly.", name)); + log_debug (LOG_ASSEMBLY, "Compressed assembly '{}' is smaller than when the application was built. Adjusting accordingly.", name); } cad.uncompressed_file_size = header->uncompressed_length; } @@ -228,7 +228,7 @@ EmbeddedAssemblies::map_runtime_file (XamarinAndroidBundledAssembly& file) noexc ); if (already_mapped) { - log_debug (LOG_ASSEMBLY, std::format ("Assembly {} already mmapped by another thread, unmapping our copy", file.name)); + log_debug (LOG_ASSEMBLY, "Assembly {} already mmapped by another thread, unmapping our copy", file.name); munmap (map_info.area, file.data_size); map_info.area = nullptr; } @@ -243,18 +243,16 @@ EmbeddedAssemblies::map_runtime_file (XamarinAndroidBundledAssembly& file) noexc header[j] = isprint (p [j]) ? p [j] : '.'; header [header.size () - 1] = '\0'; - log_info_nocheck ( + log_info_nocheck_fmt ( LOG_ASSEMBLY, - std::format ( - "file-offset: {:<8x} start: {:<8p} end: {:<8p} len: {:<12} zip-entry: {} name: {} [{}]", - file.data_offset, - static_cast(file.data), - pointer_add (file.data, file.data_size), - file.data_size, - file.name, - file.name, - header.data () - ) + "file-offset: {:<8x} start: {:<8p} end: {:<8p} len: {:<12} zip-entry: {} name: {} [{}]", + file.data_offset, + static_cast(file.data), + pointer_add (file.data, file.data_size), + file.data_size, + file.name, + file.name, + header.data () ); } } @@ -289,7 +287,7 @@ EmbeddedAssemblies::load_bundled_assembly ( if (strcmp (assembly.name, abi_name.get ()) != 0) { return nullptr; } else { - log_debug (LOG_ASSEMBLY, std::format ("open_from_bundles: found architecture-specific: '{}'", abi_name.get ())); + log_debug (LOG_ASSEMBLY, "open_from_bundles: found architecture-specific: '{}'", abi_name.get ()); } } @@ -350,7 +348,7 @@ EmbeddedAssemblies::individual_assemblies_open_from_bundles (dynamic_local_strin name.append (SharedConstants::DLL_EXTENSION); } - log_debug (LOG_ASSEMBLY, std::format ("individual_assemblies_open_from_bundles: looking for bundled name: '{}'", name.get ())); + log_debug (LOG_ASSEMBLY, "individual_assemblies_open_from_bundles: looking for bundled name: '{}'", name.get ()); dynamic_local_string abi_name; abi_name @@ -397,7 +395,7 @@ force_inline MonoAssembly* EmbeddedAssemblies::assembly_store_open_from_bundles (dynamic_local_string& name, TLoaderData loader_data, bool ref_only) noexcept { hash_t name_hash = xxhash::hash (name.get (), name.length ()); - log_debug (LOG_ASSEMBLY, std::format ("assembly_store_open_from_bundles: looking for bundled name: '{}' (hash {:x})", name.get (), name_hash)); + log_debug (LOG_ASSEMBLY, "assembly_store_open_from_bundles: looking for bundled name: '{}' (hash {:x})", name.get (), name_hash); const AssemblyStoreIndexEntry *hash_entry = find_assembly_store_entry (name_hash, assembly_store_hashes, assembly_store.index_entry_count); if (hash_entry == nullptr) { @@ -430,16 +428,15 @@ EmbeddedAssemblies::assembly_store_open_from_bundles (dynamic_local_string(assembly_runtime_info.image_data), - static_cast(assembly_runtime_info.debug_info_data), - static_cast(assembly_runtime_info.config_data), - static_cast(assembly_runtime_info.descriptor), - assembly_runtime_info.descriptor->data_size, - assembly_runtime_info.descriptor->debug_data_size, - assembly_runtime_info.descriptor->config_data_size, - name.get () - ) + "Mapped: image_data == {:p}; debug_info_data == {:p}; config_data == {:p}; descriptor == {:p}; data size == {}; debug data size == {}; config data size == {}; name == '{}'", + static_cast(assembly_runtime_info.image_data), + static_cast(assembly_runtime_info.debug_info_data), + static_cast(assembly_runtime_info.config_data), + static_cast(assembly_runtime_info.descriptor), + assembly_runtime_info.descriptor->data_size, + assembly_runtime_info.descriptor->debug_data_size, + assembly_runtime_info.descriptor->config_data_size, + name.get () ); } @@ -554,7 +551,7 @@ EmbeddedAssemblies::binary_search (const Key *key, const Entry *base, size_t nme if constexpr (use_precalculated_size) { size = precalculated_size; - log_info (LOG_ASSEMBLY, std::format ("Pre-calculated entry size = {}", size)); + log_info (LOG_ASSEMBLY, "Pre-calculated entry size = {}", size); } while (nmemb > 0) { @@ -623,26 +620,26 @@ EmbeddedAssemblies::typemap_java_to_managed ([[maybe_unused]] hash_t hash, const entry = binary_search (java_type_name.get (), type_map.java_to_managed, type_map.entry_count); if (entry == nullptr) [[unlikely]] { - log_info (LOG_ASSEMBLY, std::format ("typemap: unable to find mapping to a managed type from Java type '{}'", java_type_name.get ())); + log_info (LOG_ASSEMBLY, "typemap: unable to find mapping to a managed type from Java type '{}'", java_type_name.get ()); return nullptr; } const char *managed_type_name = entry->to; if (managed_type_name == nullptr) { - log_debug (LOG_ASSEMBLY, std::format ("typemap: Java type '{}' maps either to an open generic type or an interface type.", java_type_name.get ())); + log_debug (LOG_ASSEMBLY, "typemap: Java type '{}' maps either to an open generic type or an interface type.", java_type_name.get ()); return nullptr; } - log_debug (LOG_DEFAULT, std::format ("typemap: Java type '{}' corresponds to managed type '{}'", java_type_name.get (), managed_type_name)); + log_debug (LOG_DEFAULT, "typemap: Java type '{}' corresponds to managed type '{}'", java_type_name.get (), managed_type_name); MonoType *type = mono_reflection_type_from_name (const_cast(managed_type_name), nullptr); if (type == nullptr) [[unlikely]] { - log_info (LOG_ASSEMBLY, std::format ("typemap: managed type '{}' (mapped from Java type '{}') could not be loaded", managed_type_name, java_type_name.get ())); + log_info (LOG_ASSEMBLY, "typemap: managed type '{}' (mapped from Java type '{}') could not be loaded", managed_type_name, java_type_name.get ()); return nullptr; } MonoReflectionType *ret = mono_type_get_object (Util::get_current_domain (), type); if (ret == nullptr) [[unlikely]] { - log_warn (LOG_ASSEMBLY, std::format ("typemap: unable to instantiate managed type '{}'", managed_type_name)); + log_warn (LOG_ASSEMBLY, "typemap: unable to instantiate managed type '{}'", managed_type_name); return nullptr; } @@ -662,16 +659,16 @@ EmbeddedAssemblies::typemap_java_to_managed (hash_t hash, const MonoString *java TypeMapModule *module = java_entry != nullptr && java_entry->module_index < map_module_count ? &map_modules[java_entry->module_index] : nullptr; if (module == nullptr) { if (java_entry == nullptr) { - log_info (LOG_ASSEMBLY, std::format ("typemap: unable to find mapping to a managed type from Java type '{}' (hash {:x})", to_utf8 (java_type_name).get (), hash)); + log_info (LOG_ASSEMBLY, "typemap: unable to find mapping to a managed type from Java type '{}' (hash {:x})", to_utf8 (java_type_name).get (), hash); } else { - log_warn (LOG_ASSEMBLY, std::format ("typemap: mapping from Java type '{}' to managed type has invalid module index {}", to_utf8 (java_type_name).get (), java_entry->module_index)); + log_warn (LOG_ASSEMBLY, "typemap: mapping from Java type '{}' to managed type has invalid module index {}", to_utf8 (java_type_name).get (), java_entry->module_index); } return nullptr; } const TypeMapModuleEntry *entry = binary_search (java_entry->type_token_id, module->map, module->entry_count); if (entry == nullptr) { - log_info (LOG_ASSEMBLY, std::format ("typemap: unable to find mapping from Java type '{}' to managed type with token ID {} in module [{}]", to_utf8 (java_type_name).get (), java_entry->type_token_id, MonoGuidString (module->module_uuid).get ())); + log_info (LOG_ASSEMBLY, "typemap: unable to find mapping from Java type '{}' to managed type with token ID {} in module [{}]", to_utf8 (java_type_name).get (), java_entry->type_token_id, MonoGuidString (module->module_uuid).get ()); return nullptr; } @@ -679,7 +676,7 @@ EmbeddedAssemblies::typemap_java_to_managed (hash_t hash, const MonoString *java module->image = mono_image_loaded (module->assembly_name); if (module->image == nullptr) { - log_debug (LOG_ASSEMBLY, std::format ("typemap: assembly '{}' hasn't been loaded yet, attempting a full load", module->assembly_name)); + log_debug (LOG_ASSEMBLY, "typemap: assembly '{}' hasn't been loaded yet, attempting a full load", module->assembly_name); // Fake a request from MonoVM to load the assembly. MonoAssemblyName *assembly_name = mono_assembly_name_new (module->assembly_name); @@ -702,15 +699,15 @@ EmbeddedAssemblies::typemap_java_to_managed (hash_t hash, const MonoString *java } if (module->image == nullptr) { - log_error (LOG_ASSEMBLY, std::format ("typemap: unable to load assembly '{}' when looking up managed type corresponding to Java type '{}'", module->assembly_name, to_utf8 (java_type_name).get ())); + log_error (LOG_ASSEMBLY, "typemap: unable to load assembly '{}' when looking up managed type corresponding to Java type '{}'", module->assembly_name, to_utf8 (java_type_name).get ()); return nullptr; } } - log_debug (LOG_ASSEMBLY, std::format ("typemap: java type '{}' corresponds to managed token id {} ({:x})", to_utf8 (java_type_name).get (), java_entry->type_token_id, java_entry->type_token_id)); + log_debug (LOG_ASSEMBLY, "typemap: java type '{}' corresponds to managed token id {} ({:x})", to_utf8 (java_type_name).get (), java_entry->type_token_id, java_entry->type_token_id); MonoClass *klass = mono_class_get (module->image, java_entry->type_token_id); if (klass == nullptr) [[unlikely]] { - log_error (LOG_ASSEMBLY, std::format ("typemap: unable to find managed type with token ID {} in assembly '{}', corresponding to Java type '{}'", java_entry->type_token_id, module->assembly_name, to_utf8 (java_type_name).get ())); + log_error (LOG_ASSEMBLY, "typemap: unable to find managed type with token ID {} in assembly '{}', corresponding to Java type '{}'", java_entry->type_token_id, module->assembly_name, to_utf8 (java_type_name).get ()); return nullptr; } @@ -721,7 +718,7 @@ EmbeddedAssemblies::typemap_java_to_managed (hash_t hash, const MonoString *java MonoReflectionType *ret = mono_type_get_object (domain, mono_class_get_type (klass)); if (ret == nullptr) { - log_warn (LOG_ASSEMBLY, std::format ("typemap: unable to instantiate managed type with token ID {} in assembly '{}', corresponding to Java type '{}'", java_entry->type_token_id, module->assembly_name, to_utf8 (java_type_name).get ())); + log_warn (LOG_ASSEMBLY, "typemap: unable to instantiate managed type with token ID {} in assembly '{}', corresponding to Java type '{}'", java_entry->type_token_id, module->assembly_name, to_utf8 (java_type_name).get ()); return nullptr; } @@ -786,7 +783,7 @@ EmbeddedAssemblies::typemap_managed_to_java ([[maybe_unused]] MonoType *type, Mo const TypeMapEntry *entry = typemap_managed_to_java (full_name.get ()); if (entry == nullptr) [[unlikely]] { - log_info (LOG_ASSEMBLY, std::format ("typemap: unable to find mapping to a Java type from managed type '{}'", full_name.get ())); + log_info (LOG_ASSEMBLY, "typemap: unable to find mapping to a Java type from managed type '{}'", full_name.get ()); return nullptr; } @@ -807,13 +804,13 @@ EmbeddedAssemblies::typemap_managed_to_java ([[maybe_unused]] MonoType *type, Mo if (mvid == nullptr) { log_warn (LOG_ASSEMBLY, "typemap: no mvid specified in call to typemap_managed_to_java"sv); } else { - log_info (LOG_ASSEMBLY, std::format ("typemap: module matching MVID [{}] not found.", MonoGuidString (mvid).get ())); + log_info (LOG_ASSEMBLY, "typemap: module matching MVID [{}] not found.", MonoGuidString (mvid).get ()); } return nullptr; } uint32_t token = mono_class_get_type_token (klass); - log_debug (LOG_ASSEMBLY, std::format ("typemap: MVID [{}] maps to assembly {}, looking for token {} ({:x}), table index {}", MonoGuidString (mvid).get (), match->assembly_name, token, token, token & 0x00FFFFFF)); + log_debug (LOG_ASSEMBLY, "typemap: MVID [{}] maps to assembly {}, looking for token {} ({:x}), table index {}", MonoGuidString (mvid).get (), match->assembly_name, token, token, token & 0x00FFFFFF); // Each map entry is a pair of 32-bit integers: [TypeTokenID][JavaMapArrayIndex] const TypeMapModuleEntry *entry = match->map != nullptr ? binary_search (token, match->map, match->entry_count) : nullptr; if (entry == nullptr) { @@ -823,41 +820,40 @@ EmbeddedAssemblies::typemap_managed_to_java ([[maybe_unused]] MonoType *type, Mo } if (match->duplicate_count > 0 && match->duplicate_map != nullptr) { - log_debug (LOG_ASSEMBLY, std::format ("typemap: searching module [{}] duplicate map for token {} ({:x})", MonoGuidString (mvid).get (), token, token)); + log_debug (LOG_ASSEMBLY, "typemap: searching module [{}] duplicate map for token {} ({:x})", MonoGuidString (mvid).get (), token, token); entry = binary_search (token, match->duplicate_map, match->duplicate_count); } if (entry == nullptr) { - log_info (LOG_ASSEMBLY, std::format ("typemap: type with token {} ({:x}) in module [{}] ({}) not found.", token, token, MonoGuidString (mvid).get (), match->assembly_name)); + log_info (LOG_ASSEMBLY, "typemap: type with token {} ({:x}) in module [{}] ({}) not found.", token, token, MonoGuidString (mvid).get (), match->assembly_name); return nullptr; } } if (entry->java_map_index >= java_type_count) [[unlikely]] { - log_warn (LOG_ASSEMBLY, std::format ("typemap: type with token {} ({:x}) in module [{}] ({}) has invalid Java type index {}", token, token, MonoGuidString (mvid).get (), match->assembly_name, entry->java_map_index)); + log_warn (LOG_ASSEMBLY, "typemap: type with token {} ({:x}) in module [{}] ({}) has invalid Java type index {}", token, token, MonoGuidString (mvid).get (), match->assembly_name, entry->java_map_index); return nullptr; } TypeMapJava const& java_entry = map_java[entry->java_map_index]; if (java_entry.java_name_index >= java_type_count) [[unlikely]] { - log_warn (LOG_ASSEMBLY, std::format ("typemap: type with token {} ({:x}) in module [{}] ({}) points to invalid Java type at index {} (invalid type name index {})", token, token, MonoGuidString (mvid).get (), match->assembly_name, entry->java_map_index, java_entry.java_name_index)); + log_warn (LOG_ASSEMBLY, "typemap: type with token {} ({:x}) in module [{}] ({}) points to invalid Java type at index {} (invalid type name index {})", token, token, MonoGuidString (mvid).get (), match->assembly_name, entry->java_map_index, java_entry.java_name_index); return nullptr; } const char *ret = java_type_names[java_entry.java_name_index]; if (ret == nullptr) [[unlikely]] { - log_warn (LOG_ASSEMBLY, std::format ("typemap: empty Java type name returned for entry at index {}", entry->java_map_index)); + log_warn (LOG_ASSEMBLY, "typemap: empty Java type name returned for entry at index {}", entry->java_map_index); } log_debug ( LOG_ASSEMBLY, - std::format ("typemap: type with token {} ({:x}) in module [{}] ({}) corresponds to Java type '{}'", - token, - token, - MonoGuidString (mvid).get (), - match->assembly_name, - ret - ) + "typemap: type with token {} ({:x}) in module [{}] ({}) corresponds to Java type '{}'", + token, + token, + MonoGuidString (mvid).get (), + match->assembly_name, + ret ); return ret; @@ -919,7 +915,7 @@ EmbeddedAssemblies::md_mmap_apk_file (int fd, uint32_t offset, size_t size, cons log_info ( LOG_ASSEMBLY, - std::format (" mmap_start: {:<8p}; mmap_end: {:<8p} mmap_len: {:<12} file_start: {:<8p} file_end: {:<8p} file_len: {:<12} apk descriptor: {} file: {}", + " mmap_start: {:<8p}; mmap_end: {:<8p} mmap_len: {:<12} file_start: {:<8p} file_end: {:<8p} file_len: {:<12} apk descriptor: {} file: {}", mmap_info.area, pointer_add (mmap_info.area, mmap_info.size), mmap_info.size, @@ -928,7 +924,6 @@ EmbeddedAssemblies::md_mmap_apk_file (int fd, uint32_t offset, size_t size, cons file_info.size, fd, filename - ) ); return file_info; @@ -948,7 +943,7 @@ EmbeddedAssemblies::gather_bundled_assemblies_from_apk (const char* apk, monodro ) ); } - log_debug (LOG_ASSEMBLY, std::format ("APK {} FD: {}", apk, fd)); + log_debug (LOG_ASSEMBLY, "APK {} FD: {}", apk, fd); zip_load_entries (fd, apk, should_register); } @@ -975,40 +970,40 @@ EmbeddedAssemblies::typemap_read_header ([[maybe_unused]] int dir_fd, const char struct stat sbuf; int res = fstatat (dir_fd, file_path, &sbuf, 0); if (res < 0) { - log_error (LOG_ASSEMBLY, std::format ("typemap: failed to stat {} file '{}/{}': {}", file_type, dir_path, file_path, strerror (errno))); + log_error (LOG_ASSEMBLY, "typemap: failed to stat {} file '{}/{}': {}", file_type, dir_path, file_path, strerror (errno)); return false; } file_size = static_cast(sbuf.st_size); if (file_size < sizeof (header)) { - log_error (LOG_ASSEMBLY, std::format ("typemap: {} file '{}/{}' is too small (must be at least {} bytes)", file_type, dir_path, file_path, sizeof (header))); + log_error (LOG_ASSEMBLY, "typemap: {} file '{}/{}' is too small (must be at least {} bytes)", file_type, dir_path, file_path, sizeof (header)); return false; } fd = openat (dir_fd, file_path, O_RDONLY); if (fd < 0) { - log_error (LOG_ASSEMBLY, std::format ("typemap: failed to open {} file {}/{} for reading: {}", file_type, dir_path, file_path, strerror (errno))); + log_error (LOG_ASSEMBLY, "typemap: failed to open {} file {}/{} for reading: {}", file_type, dir_path, file_path, strerror (errno)); return false; } ssize_t nread = do_read (fd, &header, sizeof (header)); if (nread <= 0) { if (nread < 0) { - log_error (LOG_ASSEMBLY, std::format ("typemap: failed to read {} file header from '{}/{}': {}", file_type, dir_path, file_path, strerror (errno))); + log_error (LOG_ASSEMBLY, "typemap: failed to read {} file header from '{}/{}': {}", file_type, dir_path, file_path, strerror (errno)); } else { - log_error (LOG_ASSEMBLY, std::format ("typemap: end of file while reading {} file header from '{}/{}'", file_type, dir_path, file_path)); + log_error (LOG_ASSEMBLY, "typemap: end of file while reading {} file header from '{}/{}'", file_type, dir_path, file_path); } return false; } if (header.magic != expected_magic) { - log_error (LOG_ASSEMBLY, std::format ("typemap: invalid magic value in the {} file header from '{}/{}': expected {:x}, got {:x}", file_type, dir_path, file_path, expected_magic, header.magic)); + log_error (LOG_ASSEMBLY, "typemap: invalid magic value in the {} file header from '{}/{}': expected {:x}, got {:x}", file_type, dir_path, file_path, expected_magic, header.magic); return false; } if (header.version != MODULE_FORMAT_VERSION) { - log_error (LOG_ASSEMBLY, std::format ("typemap: incompatible {} format version. This build supports only version {}, file '{}/{}' uses version {}", file_type, MODULE_FORMAT_VERSION, dir_path, file_path, header.version)); + log_error (LOG_ASSEMBLY, "typemap: incompatible {} format version. This build supports only version {}, file '{}/{}' uses version {}", file_type, MODULE_FORMAT_VERSION, dir_path, file_path, header.version); return false; } @@ -1021,14 +1016,14 @@ EmbeddedAssemblies::typemap_load_index (TypeMapIndexHeader &header, size_t file_ size_t entry_size = header.module_file_name_width; size_t data_size = entry_size * type_map_count; if (sizeof(header) + data_size > file_size) { - log_error (LOG_ASSEMBLY, std::format ("typemap: index file is too small, expected {}, found {} bytes", data_size + sizeof(header), file_size)); + log_error (LOG_ASSEMBLY, "typemap: index file is too small, expected {}, found {} bytes", data_size + sizeof(header), file_size); return nullptr; } auto data = std::make_unique (data_size); ssize_t nread = do_read (index_fd, data.get (), data_size); if (nread != static_cast(data_size)) { - log_error (LOG_ASSEMBLY, std::format ("typemap: failed to read {} bytes from index file. {}", data_size, strerror (errno))); + log_error (LOG_ASSEMBLY, "typemap: failed to read {} bytes from index file. {}", data_size, strerror (errno)); return nullptr; } @@ -1044,7 +1039,7 @@ EmbeddedAssemblies::typemap_load_index (TypeMapIndexHeader &header, size_t file_ std::unique_ptr EmbeddedAssemblies::typemap_load_index (int dir_fd, const char *dir_path, const char *index_path) { - log_debug (LOG_ASSEMBLY, std::format ("typemap: loading TypeMap index file '{}/{}'", dir_path, index_path)); + log_debug (LOG_ASSEMBLY, "typemap: loading TypeMap index file '{}/{}'", dir_path, index_path); TypeMapIndexHeader header; size_t file_size; @@ -1071,7 +1066,7 @@ EmbeddedAssemblies::typemap_load_file (BinaryTypeMapHeader &header, const char * ssize_t nread = do_read (file_fd, module.assembly_name, header.assembly_name_length); if (nread != static_cast(header.assembly_name_length)) { - log_error (LOG_ASSEMBLY, std::format ("typemap: failed to read map assembly name from '{}/{}': {}", dir_path, file_path, strerror (errno))); + log_error (LOG_ASSEMBLY, "typemap: failed to read map assembly name from '{}/{}': {}", dir_path, file_path, strerror (errno)); return false; } @@ -1080,16 +1075,14 @@ EmbeddedAssemblies::typemap_load_file (BinaryTypeMapHeader &header, const char * log_debug ( LOG_ASSEMBLY, - std::format ( - "typemap: '{}/{}':: entry count == {}; Java name field width == {}; Managed name width == {}; assembly name length == {}; assembly name == {}", - dir_path, - file_path, - header.entry_count, - header.java_name_width, - header.managed_name_width, - header.assembly_name_length, - module.assembly_name - ) + "typemap: '{}/{}':: entry count == {}; Java name field width == {}; Managed name width == {}; assembly name length == {}; assembly name == {}", + dir_path, + file_path, + header.entry_count, + header.java_name_width, + header.managed_name_width, + header.assembly_name_length, + module.assembly_name ); // [name][index] @@ -1103,7 +1096,7 @@ EmbeddedAssemblies::typemap_load_file (BinaryTypeMapHeader &header, const char * module.data = new uint8_t [data_size]; nread = do_read (file_fd, module.data, data_size); if (nread != static_cast(data_size)) { - log_error (LOG_ASSEMBLY, std::format ("typemap: failed to read map data from '{}/{}': {}", dir_path, file_path, strerror (errno))); + log_error (LOG_ASSEMBLY, "typemap: failed to read map data from '{}/{}': {}", dir_path, file_path, strerror (errno)); return false; } @@ -1147,7 +1140,7 @@ EmbeddedAssemblies::typemap_load_file (BinaryTypeMapHeader &header, const char * bool EmbeddedAssemblies::typemap_load_file (int dir_fd, const char *dir_path, const char *file_path, TypeMap &module) { - log_debug (LOG_ASSEMBLY, std::format ("typemap: loading TypeMap file '{}/{}'", dir_path, file_path)); + log_debug (LOG_ASSEMBLY, "typemap: loading TypeMap file '{}/{}'", dir_path, file_path); bool ret = true; BinaryTypeMapHeader header; @@ -1186,7 +1179,7 @@ EmbeddedAssemblies::register_from_apk (const char *apk_file, monodroid_should_re gather_bundled_assemblies_from_apk (apk_file, should_register); - log_info (LOG_ASSEMBLY, std::format ("Package '{}' contains {} assemblies", apk_file, number_of_found_assemblies - prev)); + log_info (LOG_ASSEMBLY, "Package '{}' contains {} assemblies", apk_file, number_of_found_assemblies - prev); return number_of_found_assemblies; } @@ -1290,10 +1283,10 @@ EmbeddedAssemblies::maybe_register_blob_from_filesystem ( force_inline size_t EmbeddedAssemblies::register_from_filesystem (const char *lib_dir_path,bool look_for_mangled_names, monodroid_should_register should_register) noexcept { - log_debug (LOG_ASSEMBLY, std::format ("Looking for assemblies in '{}'", lib_dir_path)); + log_debug (LOG_ASSEMBLY, "Looking for assemblies in '{}'", lib_dir_path); DIR *lib_dir = opendir (lib_dir_path); // TODO: put it in a scope guard at some point if (lib_dir == nullptr) { - log_warn (LOG_ASSEMBLY, std::format ("Unable to open app library directory '{}': {}", lib_dir_path, std::strerror (errno))); + log_warn (LOG_ASSEMBLY, "Unable to open app library directory '{}': {}", lib_dir_path, std::strerror (errno)); return 0; } @@ -1302,14 +1295,14 @@ EmbeddedAssemblies::register_from_filesystem (const char *lib_dir_path,bool look int dir_fd = dirfd (lib_dir); if (dir_fd < 0) [[unlikely]] { - log_warn (LOG_ASSEMBLY, std::format ("Unable to obtain file descriptor for directory '{}': {}", lib_dir_path, std::strerror (errno))); + log_warn (LOG_ASSEMBLY, "Unable to obtain file descriptor for directory '{}': {}", lib_dir_path, std::strerror (errno)); closedir (lib_dir); return 0; } state.file_fd = dup (dir_fd); if (state.file_fd < 0) [[unlikely]] { - log_warn (LOG_ASSEMBLY, std::format ("Unable to duplicate file descriptor {} for directory '{}': {}", dir_fd, lib_dir_path, std::strerror (errno))); + log_warn (LOG_ASSEMBLY, "Unable to duplicate file descriptor {} for directory '{}': {}", dir_fd, lib_dir_path, std::strerror (errno)); closedir (lib_dir); return 0; } @@ -1326,7 +1319,7 @@ EmbeddedAssemblies::register_from_filesystem (const char *lib_dir_path,bool look dirent *cur = readdir (lib_dir); if (cur == nullptr) { if (errno != 0) { - log_warn (LOG_ASSEMBLY, std::format ("Failed to open a directory entry from '{}': {}", lib_dir_path, std::strerror (errno))); + log_warn (LOG_ASSEMBLY, "Failed to open a directory entry from '{}': {}", lib_dir_path, std::strerror (errno)); continue; // keep going, no harm } break; // No more entries, we're done @@ -1346,7 +1339,7 @@ EmbeddedAssemblies::register_from_filesystem (const char *lib_dir_path,bool look // ...and we can handle the runtime config entry if (!runtime_config_blob_found && std::strncmp (cur->d_name, SharedConstants::RUNTIME_CONFIG_BLOB_NAME.data (), SharedConstants::RUNTIME_CONFIG_BLOB_NAME.size ()) == 0) { - log_debug (LOG_ASSEMBLY, std::format ("Mapping runtime config blob from '{}'", cur->d_name)); + log_debug (LOG_ASSEMBLY, "Mapping runtime config blob from '{}'", cur->d_name); auto file_size = Util::get_file_size_at (state.file_fd, cur->d_name); if (!file_size) { continue; @@ -1393,6 +1386,6 @@ EmbeddedAssemblies::register_from_filesystem (monodroid_should_register should_r ); #endif - log_debug (LOG_ASSEMBLY, std::format ("Found {} assemblies on the filesystem", assembly_count)); + log_debug (LOG_ASSEMBLY, "Found {} assemblies on the filesystem", assembly_count); return assembly_count; } diff --git a/src/native/monodroid/embedded-assemblies.hh b/src/native/monodroid/embedded-assemblies.hh index 21fc0de80b8..c17d957b4c2 100644 --- a/src/native/monodroid/embedded-assemblies.hh +++ b/src/native/monodroid/embedded-assemblies.hh @@ -310,7 +310,7 @@ namespace xamarin::android::internal { elf_header->e_ident[EI_MAG1] != ELFMAG1 || elf_header->e_ident[EI_MAG2] != ELFMAG2 || elf_header->e_ident[EI_MAG3] != ELFMAG3) { - log_debug (LOG_ASSEMBLY, std::format ("Not an ELF image: {}", file_name)); + log_debug (LOG_ASSEMBLY, "Not an ELF image: {}", file_name); // Not an ELF image, just return what we mmapped before return { map_info.area, map_info.size }; } @@ -329,7 +329,7 @@ namespace xamarin::android::internal { static void store_mapped_runtime_config_data (md_mmap_info const& map_info, const char *file_name) noexcept { auto [payload_start, payload_size] = get_wrapper_dso_payload_pointer_and_size (map_info, file_name); - log_debug (LOG_ASSEMBLY, std::format ("Runtime config: payload pointer {:p} ; size {}", payload_start, payload_size)); + log_debug (LOG_ASSEMBLY, "Runtime config: payload pointer {:p} ; size {}", payload_start, payload_size); runtime_config_data = payload_start; runtime_config_data_size = payload_size; runtime_config_blob_found = true; @@ -431,7 +431,7 @@ namespace xamarin::android::internal { } } } - log_debug (LOG_ASSEMBLY, std::format ("Unmangled name to '{}'", name.get ())); + log_debug (LOG_ASSEMBLY, "Unmangled name to '{}'", name.get ()); }; private: diff --git a/src/native/monodroid/monodroid-glue-internal.hh b/src/native/monodroid/monodroid-glue-internal.hh index dbd78121458..da7f9f6be2c 100644 --- a/src/native/monodroid/monodroid-glue-internal.hh +++ b/src/native/monodroid/monodroid-glue-internal.hh @@ -166,7 +166,7 @@ namespace xamarin::android::internal void *symptr = MonodroidDl::monodroid_dlsym (handle, name, &err, nullptr); if (symptr == nullptr) { - log_warn (LOG_DEFAULT, std::format ("Failed to load symbol '{}' library with handle {}. {}", name, handle, err == nullptr ? "Unknown error"sv : err)); + log_warn (LOG_DEFAULT, "Failed to load symbol '{}' library with handle {}. {}", name, handle, err == nullptr ? "Unknown error"sv : err); fnptr = nullptr; return; } diff --git a/src/native/monodroid/monodroid-glue.cc b/src/native/monodroid/monodroid-glue.cc index 25c10b07660..49e614a4455 100644 --- a/src/native/monodroid/monodroid-glue.cc +++ b/src/native/monodroid/monodroid-glue.cc @@ -174,12 +174,12 @@ MonodroidRuntime::open_from_update_dir (MonoAssemblyName *aname, [[maybe_unused] fullpath.append (SharedConstants::DLL_EXTENSION); } - log_debug (LOG_ASSEMBLY, std::format ("open_from_update_dir: trying to open assembly: {}", fullpath.get ())); + log_debug (LOG_ASSEMBLY, "open_from_update_dir: trying to open assembly: {}", fullpath.get ()); if (Util::file_exists (fullpath.get ())) { MonoImageOpenStatus status{}; result = mono_assembly_open_full (fullpath.get (), &status, 0); if (result == nullptr || status != MonoImageOpenStatus::MONO_IMAGE_OK) { - log_warn (LOG_ASSEMBLY, std::format ("Failed to load managed assembly '{}'. {}", fullpath.get (), mono_image_strerror (status))); + log_warn (LOG_ASSEMBLY, "Failed to load managed assembly '{}'. {}", fullpath.get (), mono_image_strerror (status)); } } else { log_warn (LOG_ASSEMBLY, "open_from_update_dir: assembly file DOES NOT EXIST"sv); @@ -191,7 +191,7 @@ MonodroidRuntime::open_from_update_dir (MonoAssemblyName *aname, [[maybe_unused] } if (result != nullptr && Util::should_log (LOG_ASSEMBLY)) { - log_info_nocheck (LOG_ASSEMBLY, std::format ("open_from_update_dir: loaded assembly: {:p}", reinterpret_cast(result))); + log_info_nocheck_fmt (LOG_ASSEMBLY, "open_from_update_dir: loaded assembly: {:p}", reinterpret_cast(result)); } return result; } @@ -378,7 +378,7 @@ MonodroidRuntime::parse_gdb_options () noexcept time_t secs = time (nullptr); if (v + 10 < secs) { - log_warn (LOG_DEFAULT, std::format ("Found stale {} property with value '{}', not waiting.", SharedConstants::DEBUG_MONO_GDB_PROPERTY.data (), val.get ())); + log_warn (LOG_DEFAULT, "Found stale {} property with value '{}', not waiting.", SharedConstants::DEBUG_MONO_GDB_PROPERTY.data (), val.get ()); do_wait = false; } } @@ -449,13 +449,13 @@ MonodroidRuntime::parse_runtime_args (dynamic_local_string std::numeric_limits::max ()) { - log_error (LOG_DEFAULT, std::format ("Invalid SDB port value {}", sdb_port)); + log_error (LOG_DEFAULT, "Invalid SDB port value {}", sdb_port); ret = false; continue; } if (out_port > std::numeric_limits::max ()) { - log_error (LOG_DEFAULT, std::format ("Invalid output port value {}", out_port)); + log_error (LOG_DEFAULT, "Invalid output port value {}", out_port); ret = false; continue; } @@ -480,7 +480,7 @@ MonodroidRuntime::parse_runtime_args (dynamic_local_string arg (token); - log_error (LOG_DEFAULT, std::format ("Unknown runtime argument: '{}'", arg.get ())); + log_error (LOG_DEFAULT, "Unknown runtime argument: '{}'", arg.get ()); ret = false; } } @@ -509,9 +509,9 @@ MonodroidRuntime::mono_runtime_init ([[maybe_unused]] JNIEnv *env, [[maybe_unuse cur_time = time (nullptr); if (!parse_runtime_args (runtime_args, &options)) { - log_error (LOG_DEFAULT, std::format ("Failed to parse runtime args: '{}'", runtime_args.get ())); + log_error (LOG_DEFAULT, "Failed to parse runtime args: '{}'", runtime_args.get ()); } else if (options.debug && cur_time > options.timeout_time) { - log_warn (LOG_DEBUGGER, std::format ("Not starting the debugger as the timeout value has been reached; current-time: {}; timeout: {}", cur_time, options.timeout_time)); + log_warn (LOG_DEBUGGER, "Not starting the debugger as the timeout value has been reached; current-time: {}; timeout: {}", cur_time, options.timeout_time); } else if (options.debug && cur_time <= options.timeout_time) { EmbeddedAssemblies::set_register_debug_symbols (true); @@ -537,7 +537,7 @@ MonodroidRuntime::mono_runtime_init ([[maybe_unused]] JNIEnv *env, [[maybe_unuse // this text is used in unit tests to check the debugger started // do not change it without updating the test. - log_warn (LOG_DEBUGGER, std::format ("Trying to initialize the debugger with options: {}", debug_arg)); + log_warn (LOG_DEBUGGER, "Trying to initialize the debugger with options: {}", debug_arg); if (options.out_port > 0) { int sock = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP); @@ -570,7 +570,7 @@ MonodroidRuntime::mono_runtime_init ([[maybe_unused]] JNIEnv *env, [[maybe_unuse if (options.server) { int accepted = monodroid_debug_accept (sock, addr); - log_warn (LOG_DEBUGGER, std::format ("Accepted stdout connection: {}", accepted)); + log_warn (LOG_DEBUGGER, "Accepted stdout connection: {}", accepted); if (accepted < 0) { Helpers::abort_application ( LOG_DEBUGGER, @@ -662,7 +662,7 @@ MonodroidRuntime::mono_runtime_init ([[maybe_unused]] JNIEnv *env, [[maybe_unuse if (AndroidSystem::monodroid_get_system_property (SharedConstants::DEBUG_MONO_RUNTIME_ARGS_PROPERTY, prop_val) > 0) { char **ptr; - log_warn (LOG_DEBUGGER, std::format ("passing '{}' as extra arguments to the runtime.", prop_val.get ())); + log_warn (LOG_DEBUGGER, "passing '{}' as extra arguments to the runtime.", prop_val.get ()); char **args = Util::monodroid_strsplit (prop_val.get (), " ", 0); int argc = 0; @@ -730,11 +730,9 @@ MonodroidRuntime::create_domain (JNIEnv *env, jstring_array_wrapper &runtimeApks if (user_assemblies_count == 0 && AndroidSystem::count_override_assemblies () == 0 && !is_running_on_desktop) { #if defined (DEBUG) log_fatal (LOG_DEFAULT, - std::format ( - "No assemblies found in '{}' or '{}'. Assuming this is part of Fast Deployment. Exiting...", - AndroidSystem::override_dirs [0], - (AndroidSystem::override_dirs.size () > 1 && AndroidSystem::override_dirs [1] != nullptr) ? AndroidSystem::override_dirs [1] : ""sv - ) + "No assemblies found in '{}' or '{}'. Assuming this is part of Fast Deployment. Exiting...", + AndroidSystem::override_dirs [0], + (AndroidSystem::override_dirs.size () > 1 && AndroidSystem::override_dirs [1] != nullptr) ? AndroidSystem::override_dirs [1] : ""sv ); #else log_fatal (LOG_DEFAULT, "No assemblies (or assembly blobs) were found in the application APK file(s) or on the filesystem"sv); @@ -858,7 +856,7 @@ MonodroidRuntime::init_android_runtime (JNIEnv *env, jclass runtimeClass, jobjec // GC threshold is 90% of the max GREF count init.grefGcThreshold = static_cast(AndroidSystem::get_gref_gc_threshold ()); - log_info (LOG_GC, std::format ("GREF GC Threshold: {}", init.grefGcThreshold)); + log_info (LOG_GC, "GREF GC Threshold: {}", init.grefGcThreshold); init.grefClass = RuntimeUtil::get_class_from_runtime_field (env, runtimeClass, "java_lang_Class", true); Class_getName = env->GetMethodID (init.grefClass, "getName", "()Ljava/lang/String;"); @@ -944,7 +942,7 @@ MonodroidRuntime::init_android_runtime (JNIEnv *env, jclass runtimeClass, jobjec auto initialize = reinterpret_cast (mono_method_get_unmanaged_callers_only_ftnptr (method, &error)); if (initialize == nullptr) { - log_fatal (LOG_DEFAULT, std::format ("Failed to get pointer to Initialize. Mono error: {}", mono_error_get_message (&error))); + log_fatal (LOG_DEFAULT, "Failed to get pointer to Initialize. Mono error: {}", mono_error_get_message (&error)); } abort_unless ( @@ -1000,7 +998,7 @@ MonodroidRuntime::set_environment_variable_for_directory (const char *name, jstr if (createDirectory) { int rv = Util::create_directory (value.get_cstr (), mode); if (rv < 0 && errno != EEXIST) - log_warn (LOG_DEFAULT, std::format ("Failed to create directory for environment variable {}. {}", name, strerror (errno))); + log_warn (LOG_DEFAULT, "Failed to create directory for environment variable {}. {}", name, strerror (errno)); } setenv (name, value.get_cstr (), 1); } @@ -1010,10 +1008,10 @@ MonodroidRuntime::create_xdg_directory (jstring_wrapper& home, size_t home_len, { static_local_string dir (home_len + relative_path.length ()); Util::path_combine (dir, home.get_cstr (), home_len, relative_path.data (), relative_path.length ()); - log_debug (LOG_DEFAULT, std::format ("Creating XDG directory: {}", dir.get ())); + log_debug (LOG_DEFAULT, "Creating XDG directory: {}", dir.get ()); int rv = Util::create_directory (dir.get (), DEFAULT_DIRECTORY_MODE); if (rv < 0 && errno != EEXIST) - log_warn (LOG_DEFAULT, std::format ("Failed to create XDG directory {}. {}", dir.get (), strerror (errno))); + log_warn (LOG_DEFAULT, "Failed to create XDG directory {}. {}", dir.get (), strerror (errno)); if (!environment_variable_name.empty ()) { setenv (environment_variable_name.data (), dir.get (), 1); } @@ -1042,7 +1040,7 @@ MonodroidRuntime::set_debug_env_vars (void) noexcept return; auto log_envvar = [](const char *name, const char *v) { - log_debug (LOG_DEFAULT, std::format ("Env variable '{}' set to '{}'.", name, v)); + log_debug (LOG_DEFAULT, "Env variable '{}' set to '{}'.", name, v); }; string_segment arg_token; @@ -1062,7 +1060,7 @@ MonodroidRuntime::set_debug_env_vars (void) noexcept log_envvar (arg.get (), one.data ()); } else if (index == 0) { // ’=value’ - log_warn (LOG_DEFAULT, std::format ("Attempt to set environment variable without specifying name: '{}'", arg.get ())); + log_warn (LOG_DEFAULT, "Attempt to set environment variable without specifying name: '{}'", arg.get ()); } else { // ’name=value’ arg[index] = '\0'; @@ -1142,10 +1140,10 @@ MonodroidRuntime::set_profile_options () noexcept .append (output_path.get (), output_path.length ()); } if (Util::create_directory (AndroidSystem::override_dirs[0], 0) < 0) { - log_warn (LOG_DEFAULT, std::format ("Failed to create directory '{}'. {}", AndroidSystem::override_dirs[0], std::strerror (errno))); + log_warn (LOG_DEFAULT, "Failed to create directory '{}'. {}", AndroidSystem::override_dirs[0], std::strerror (errno)); } - log_warn (LOG_DEFAULT, std::format ("Initializing profiler with options: {}", value.get ())); + log_warn (LOG_DEFAULT, "Initializing profiler with options: {}", value.get ()); debug.monodroid_profiler_load (AndroidSystem::get_runtime_libdir (), value.get (), output_path.get ()); } @@ -1470,7 +1468,7 @@ MonodroidRuntime::Java_mono_android_Runtime_initInternal (JNIEnv *env, jclass kl if (runtimeNativeLibDir != nullptr) { jstr = runtimeNativeLibDir; AndroidSystem::set_runtime_libdir (strdup (jstr.get_cstr ())); - log_debug (LOG_DEFAULT, std::format ("Using runtime path: {}", AndroidSystem::get_runtime_libdir ())); + log_debug (LOG_DEFAULT, "Using runtime path: {}", AndroidSystem::get_runtime_libdir ()); } AndroidSystem::setup_process_args (runtimeApks); @@ -1533,17 +1531,16 @@ MonodroidRuntime::Java_mono_android_Runtime_initInternal (JNIEnv *env, jclass kl } if (Util::should_log (LOG_DEFAULT)) [[unlikely]] { - log_info_nocheck ( + log_info_nocheck_fmt ( LOG_DEFAULT, - std::format (".NET for Android version: {} ({}; {}); built on {}; NDK version: {}; API level: {}; MonoVM version: {}", - BuildInfo::xa_version.data (), - BuildInfo::architecture.data (), - BuildInfo::kind.data (), - BuildInfo::date.data (), - BuildInfo::ndk_version.data (), - BuildInfo::ndk_api_level.data (), - mono_get_runtime_build_info () - ) + ".NET for Android version: {} ({}; {}); built on {}; NDK version: {}; API level: {}; MonoVM version: {}", + BuildInfo::xa_version.data (), + BuildInfo::architecture.data (), + BuildInfo::kind.data (), + BuildInfo::date.data (), + BuildInfo::ndk_version.data (), + BuildInfo::ndk_api_level.data (), + mono_get_runtime_build_info () ); } @@ -1666,7 +1663,7 @@ MonodroidRuntime::get_java_class_name_for_TypeManager (jclass klass) noexcept JNIEnv *env = osBridge.ensure_jnienv (); jstring name = reinterpret_cast (env->CallObjectMethod (klass, Class_getName)); if (name == nullptr) { - log_error (LOG_DEFAULT, std::format ("Failed to obtain Java class name for object at {:p}", reinterpret_cast(klass))); + log_error (LOG_DEFAULT, "Failed to obtain Java class name for object at {:p}", reinterpret_cast(klass)); return nullptr; } diff --git a/src/native/monodroid/monodroid-networkinfo.cc b/src/native/monodroid/monodroid-networkinfo.cc index f9dcba4c181..4e87c0079d3 100644 --- a/src/native/monodroid/monodroid-networkinfo.cc +++ b/src/native/monodroid/monodroid-networkinfo.cc @@ -88,14 +88,14 @@ _monodroid_get_network_interface_state (const char *ifname, mono_bool *is_up, mo networkInterface = env->CallStaticObjectMethod (NetworkInterface_class, NetworkInterface_getByName, NetworkInterface_nameArg); env->DeleteLocalRef (NetworkInterface_nameArg); if (env->ExceptionOccurred ()) { - log_warn (LOG_NET, std::format ("Java exception occurred while looking up the interface '{}'", ifname)); + log_warn (LOG_NET, "Java exception occurred while looking up the interface '{}'", ifname); env->ExceptionDescribe (); env->ExceptionClear (); goto leave; } if (!networkInterface) { - log_warn (LOG_NET, std::format ("Failed to look up interface '{}' using Java API", ifname)); + log_warn (LOG_NET, "Failed to look up interface '{}' using Java API", ifname); ret = FALSE; goto leave; } @@ -118,7 +118,7 @@ _monodroid_get_network_interface_state (const char *ifname, mono_bool *is_up, mo leave: if (!ret) - log_warn (LOG_NET, std::format ("Unable to determine interface '{}' state using Java API", ifname)); + log_warn (LOG_NET, "Unable to determine interface '{}' state using Java API", ifname); if (networkInterface != nullptr && env != nullptr) { env->DeleteLocalRef (networkInterface); diff --git a/src/native/monodroid/monodroid-tracing.cc b/src/native/monodroid/monodroid-tracing.cc index 56db0e50dd1..96c9778dd37 100644 --- a/src/native/monodroid/monodroid-tracing.cc +++ b/src/native/monodroid/monodroid-tracing.cc @@ -27,7 +27,7 @@ MonodroidRuntime::log_traces (JNIEnv *env, TraceKind kind, const char *first_lin char *err = nullptr; void *handle = MonodroidDl::monodroid_dlopen (SharedConstants::xamarin_native_tracing_name.data (), MONO_DL_EAGER, &err, nullptr); if (handle == nullptr) { - log_warn (LOG_DEFAULT, std::format ("Failed to load native tracing library '{}'. {}", SharedConstants::xamarin_native_tracing_name, err == nullptr ? "Unknown error"sv : err)); + log_warn (LOG_DEFAULT, "Failed to load native tracing library '{}'. {}", SharedConstants::xamarin_native_tracing_name, err == nullptr ? "Unknown error"sv : err); } else { load_symbol (handle, "xa_get_native_backtrace", _xa_get_native_backtrace); load_symbol (handle, "xa_get_managed_backtrace", _xa_get_managed_backtrace); diff --git a/src/native/monodroid/osbridge.cc b/src/native/monodroid/osbridge.cc index 94e0317d3e9..e909ab51ec2 100644 --- a/src/native/monodroid/osbridge.cc +++ b/src/native/monodroid/osbridge.cc @@ -188,7 +188,7 @@ OSBridge::_write_stack_trace (FILE *to, char *from, LogCategories category) *end = '\0'; if ((category == LOG_GREF && gref_to_logcat) || (category == LOG_LREF && lref_to_logcat)) { - log_debug (category, std::format ("{}", m)); + log_debug (category, "{}", m); } if (to != nullptr) { fprintf (to, "%s\n", m); @@ -202,7 +202,7 @@ void OSBridge::_monodroid_gref_log (const char *message) { if (gref_to_logcat) { - log_debug (LOG_GREF, std::format ("{}", message)); + log_debug (LOG_GREF, "{}", message); } if (!gref_log) return; @@ -217,22 +217,21 @@ OSBridge::_monodroid_gref_log_new (jobject curHandle, char curType, jobject newH if ((log_categories & LOG_GREF) == 0) return c; log_info (LOG_GREF, - std::format ("+g+ grefc {} gwrefc {} obj-handle {:p}/{} -> new-handle {:p}/{} from thread '{}'({})", - c, - gc_weak_gref_count, - reinterpret_cast(curHandle), - curType, - reinterpret_cast(newHandle), - newType, - threadName, - threadId - ) + "+g+ grefc {} gwrefc {} obj-handle {:p}/{} -> new-handle {:p}/{} from thread '{}'({})", + c, + gc_weak_gref_count, + reinterpret_cast(curHandle), + curType, + reinterpret_cast(newHandle), + newType, + threadName, + threadId ); if (gref_to_logcat) { if (from_writable) { _write_stack_trace (nullptr, const_cast(from), LOG_GREF); } else { - log_info (LOG_GREF, std::format ("{}", from)); + log_info (LOG_GREF, "{}", from); } } if (!gref_log) @@ -263,20 +262,19 @@ OSBridge::_monodroid_gref_log_delete (jobject handle, char type, const char *thr if ((log_categories & LOG_GREF) == 0) return; log_info (LOG_GREF, - std::format ("-g- grefc {} gwrefc {} handle {:p}/{} from thread '{}'({})", - c, - gc_weak_gref_count, - reinterpret_cast(handle), - type, - threadName, - threadId - ) + "-g- grefc {} gwrefc {} handle {:p}/{} from thread '{}'({})", + c, + gc_weak_gref_count, + reinterpret_cast(handle), + type, + threadName, + threadId ); if (gref_to_logcat) { if (from_writable) { _write_stack_trace (nullptr, const_cast(from), LOG_GREF); } else { - log_info (LOG_GREF, std::format ("{}", from)); + log_info (LOG_GREF, "{}", from); } } if (!gref_log) @@ -303,22 +301,21 @@ OSBridge::_monodroid_weak_gref_new (jobject curHandle, char curType, jobject new if ((log_categories & LOG_GREF) == 0) return; log_info (LOG_GREF, - std::format ("+w+ grefc {} gwrefc {} obj-handle {:p}/{} -> new-handle {:p}/{} from thread '{}'({})", - gc_gref_count, - gc_weak_gref_count, - reinterpret_cast(curHandle), - curType, - reinterpret_cast(newHandle), - newType, - threadName, - threadId - ) + "+w+ grefc {} gwrefc {} obj-handle {:p}/{} -> new-handle {:p}/{} from thread '{}'({})", + gc_gref_count, + gc_weak_gref_count, + reinterpret_cast(curHandle), + curType, + reinterpret_cast(newHandle), + newType, + threadName, + threadId ); if (gref_to_logcat) { if (from_writable) { _write_stack_trace (nullptr, const_cast(from), LOG_GREF); } else { - log_info (LOG_GREF, std::format ("{}", from)); + log_info (LOG_GREF, "{}", from); } } if (!gref_log) @@ -347,20 +344,19 @@ OSBridge::_monodroid_weak_gref_delete (jobject handle, char type, const char *th if ((log_categories & LOG_GREF) == 0) return; log_info (LOG_GREF, - std::format ("-w- grefc {} gwrefc {} handle {:p}/{} from thread '{}'({})", - gc_gref_count, - gc_weak_gref_count, - reinterpret_cast(handle), - type, - threadName, - threadId - ) + "-w- grefc {} gwrefc {} handle {:p}/{} from thread '{}'({})", + gc_gref_count, + gc_weak_gref_count, + reinterpret_cast(handle), + type, + threadName, + threadId ); if (gref_to_logcat) { if (from_writable) { _write_stack_trace (nullptr, const_cast(from), LOG_GREF); } else { - log_info (LOG_GREF, std::format ("{}", from)); + log_info (LOG_GREF, "{}", from); } } if (!gref_log) @@ -386,19 +382,18 @@ OSBridge::_monodroid_lref_log_new (int lrefc, jobject handle, char type, const c if ((log_categories & LOG_LREF) == 0) return; log_info (LOG_LREF, - std::format ("+l+ lrefc {} handle {:p}/{} from thread '{}'({})", - lrefc, - reinterpret_cast(handle), - type, - threadName, - threadId - ) + "+l+ lrefc {} handle {:p}/{} from thread '{}'({})", + lrefc, + reinterpret_cast(handle), + type, + threadName, + threadId ); if (lref_to_logcat) { if (from_writable) { _write_stack_trace (nullptr, const_cast(from), LOG_GREF); } else { - log_info (LOG_GREF, std::format ("{}", from)); + log_info (LOG_GREF, "{}", from); } } if (!lref_log) @@ -423,19 +418,18 @@ OSBridge::_monodroid_lref_log_delete (int lrefc, jobject handle, char type, cons if ((log_categories & LOG_LREF) == 0) return; log_info (LOG_LREF, - std::format ("-l- lrefc {} handle {:p}/{} from thread '{}'({})", - lrefc, - reinterpret_cast(handle), - type, - threadName, - threadId - ) + "-l- lrefc {} handle {:p}/{} from thread '{}'({})", + lrefc, + reinterpret_cast(handle), + type, + threadName, + threadId ); if (lref_to_logcat) { if (from_writable) { _write_stack_trace (nullptr, const_cast(from), LOG_GREF); } else { - log_info (LOG_GREF, std::format ("{}", from)); + log_info (LOG_GREF, "{}", from); } } if (!lref_log) @@ -548,11 +542,9 @@ OSBridge::gc_bridge_class_kind (MonoClass *klass) i = get_gc_bridge_index (klass); if (i == static_cast (-NUM_GC_BRIDGE_TYPES)) { log_info (LOG_GC, - std::format ( - "asked if a class {}.{} is a bridge before we inited java.lang.Object", - mono_class_get_namespace (klass), - mono_class_get_name (klass) - ) + "asked if a class {}.{} is a bridge before we inited java.lang.Object", + mono_class_get_namespace (klass), + mono_class_get_name (klass) ); return MonoGCBridgeObjectKind::GC_BRIDGE_TRANSPARENT_CLASS; } @@ -578,11 +570,9 @@ OSBridge::gc_is_bridge_object (MonoObject *object) #if DEBUG MonoClass *mclass = mono_object_get_class (object); log_info (LOG_GC, - std::format ( - "object of class {}.{} with null handle", - mono_class_get_namespace (mclass), - mono_class_get_name (mclass) - ) + "object of class {}.{} with null handle", + mono_class_get_namespace (mclass), + mono_class_get_name (mclass) ); #endif return 0; @@ -669,9 +659,9 @@ OSBridge::add_reference (JNIEnv *env, OSBridge::AddReferenceTarget target, OSBri *reffed_description = describe_target (reffed_target); if (success) - log_warn (LOG_GC, std::format ("Added reference for {} to {}", description, reffed_description)); + log_warn (LOG_GC, "Added reference for {} to {}", description, reffed_description); else - log_error (LOG_GC, std::format ("Missing monodroidAddReference method for {}", description)); + log_error (LOG_GC, "Missing monodroidAddReference method for {}", description); free (description); free (reffed_description); @@ -908,11 +898,9 @@ OSBridge::gc_cleanup_after_java_collection (JNIEnv *env, int num_sccs, MonoGCBri if (Logger::gc_spew_enabled ()) { klass = mono_object_get_class (obj); log_error (LOG_GC, - std::format ( - "Missing monodroidClearReferences method for object of class {}.{}", - mono_class_get_namespace (klass), - mono_class_get_name (klass) - ) + "Missing monodroidClearReferences method for object of class {}.{}", + mono_class_get_namespace (klass), + mono_class_get_name (klass) ); } #endif @@ -927,7 +915,7 @@ OSBridge::gc_cleanup_after_java_collection (JNIEnv *env, int num_sccs, MonoGCBri } } #if DEBUG - log_info (LOG_GC, std::format ("GC cleanup summary: {} objects tested - resurrecting {}.", total, alive)); + log_info (LOG_GC, "GC cleanup summary: {} objects tested - resurrecting {}.", total, alive); #endif } @@ -957,10 +945,10 @@ OSBridge::gc_cross_references (int num_sccs, MonoGCBridgeSCC **sccs, int num_xre if (Logger::gc_spew_enabled ()) { int i, j; - log_info (LOG_GC, std::format ("cross references callback invoked with {} sccs and {} xrefs.", num_sccs, num_xrefs)); + log_info (LOG_GC, "cross references callback invoked with {} sccs and {} xrefs.", num_sccs, num_xrefs); for (i = 0; i < num_sccs; ++i) { - log_info (LOG_GC, std::format ("group {} with {} objects", i, sccs [i]->num_objs)); + log_info (LOG_GC, "group {} with {} objects", i, sccs [i]->num_objs); for (j = 0; j < sccs [i]->num_objs; ++j) { MonoObject *obj = sccs [i]->objs [j]; @@ -975,21 +963,19 @@ OSBridge::gc_cross_references (int num_sccs, MonoGCBridgeSCC **sccs, int num_xre } MonoClass *klass = mono_object_get_class (obj); log_info (LOG_GC, - std::format ( - "\tobj {:p} [{}::{}] handle {:p} key_handle {:p}", - reinterpret_cast(obj), - mono_class_get_namespace (klass), - mono_class_get_name (klass), - reinterpret_cast(handle), - key_handle - ) + "\tobj {:p} [{}::{}] handle {:p} key_handle {:p}", + reinterpret_cast(obj), + mono_class_get_namespace (klass), + mono_class_get_name (klass), + reinterpret_cast(handle), + key_handle ); } } if (Util::should_log (LOG_GC)) { for (i = 0; i < num_xrefs; ++i) - log_info_nocheck (LOG_GC, std::format ("xref [{}] {} -> {}", i, xrefs [i].src_scc_index, xrefs [i].dst_scc_index)); + log_info_nocheck_fmt (LOG_GC, "xref [{}] {} -> {}", i, xrefs [i].src_scc_index, xrefs [i].dst_scc_index); } } diff --git a/src/native/monodroid/xamarin-android-app-context.cc b/src/native/monodroid/xamarin-android-app-context.cc index e55635f2443..75973eb020e 100644 --- a/src/native/monodroid/xamarin-android-app-context.cc +++ b/src/native/monodroid/xamarin-android-app-context.cc @@ -15,7 +15,7 @@ MonodroidRuntime::get_method_name (uint32_t mono_image_index, uint32_t method_to { uint64_t id = (static_cast(mono_image_index) << 32) | method_token; - log_debug (LOG_ASSEMBLY, std::format ("MM: looking for name of method with id {:x}, in mono image at index {}", id, mono_image_index)); + log_debug (LOG_ASSEMBLY, "MM: looking for name of method with id {:x}, in mono image at index {}", id, mono_image_index); size_t i = 0uz; while (mm_method_names[i].id != 0) { if (mm_method_names[i].id == id) { @@ -43,10 +43,9 @@ MonodroidRuntime::get_function_pointer (uint32_t mono_image_index, uint32_t clas { log_debug ( LOG_ASSEMBLY, - std::format ("MM: Trying to look up pointer to method '{}' (token {:x}) in class '{}' (index {})", - get_method_name (mono_image_index, method_token), method_token, - get_class_name (class_index), class_index - ) + "MM: Trying to look up pointer to method '{}' (token {:x}) in class '{}' (index {})", + get_method_name (mono_image_index, method_token), method_token, + get_class_name (class_index), class_index ); if (class_index >= marshal_methods_number_of_classes) [[unlikely]] { @@ -81,32 +80,29 @@ MonodroidRuntime::get_function_pointer (uint32_t mono_image_index, uint32_t clas log_debug ( LOG_ASSEMBLY, - std::format ("Loaded pointer to method {} ({:p}) (mono_image_index == {}; class_index == {}; method_token == {:x})", - mono_method_full_name (method, true), - ret, - mono_image_index, - class_index, - method_token - ) + "Loaded pointer to method {} ({:p}) (mono_image_index == {}; class_index == {}; method_token == {:x})", + mono_method_full_name (method, true), + ret, + mono_image_index, + class_index, + method_token ); return; } log_fatal ( LOG_DEFAULT, - std::format ("Failed to obtain function pointer to method '{}' in class '{}'", - get_method_name (mono_image_index, method_token), - get_class_name (class_index) - ) + "Failed to obtain function pointer to method '{}' in class '{}'", + get_method_name (mono_image_index, method_token), + get_class_name (class_index) ); log_fatal ( LOG_DEFAULT, - std::format ("Looked for image index {}, class index {}, method token {:x}", - mono_image_index, - class_index, - method_token - ) + "Looked for image index {}, class index {}, method token {:x}", + mono_image_index, + class_index, + method_token ); if (image == nullptr) { diff --git a/src/native/monodroid/xamarin_getifaddrs.cc b/src/native/monodroid/xamarin_getifaddrs.cc index 99ba01039e6..57c4935a7bf 100644 --- a/src/native/monodroid/xamarin_getifaddrs.cc +++ b/src/native/monodroid/xamarin_getifaddrs.cc @@ -421,7 +421,7 @@ open_netlink_session (netlink_session *session) memset (session, 0, sizeof (*session)); session->sock_fd = socket (AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); if (session->sock_fd == -1) { - log_warn (LOG_NETLINK, std::format ("Failed to create a netlink socket. {}", strerror (errno))); + log_warn (LOG_NETLINK, "Failed to create a netlink socket. {}", strerror (errno)); return -1; } @@ -440,7 +440,7 @@ open_netlink_session (netlink_session *session) session->them.nl_family = AF_NETLINK; if (bind (session->sock_fd, (struct sockaddr *)&session->us, sizeof (session->us)) < 0) { - log_warn (LOG_NETLINK, std::format ("Failed to bind to the netlink socket. {}", strerror (errno))); + log_warn (LOG_NETLINK, "Failed to bind to the netlink socket. {}", strerror (errno)); return -1; } @@ -478,7 +478,7 @@ send_netlink_dump_request (netlink_session *session, int type) session->message_header.msg_iov = &session->payload_vector; if (sendmsg (session->sock_fd, (const struct msghdr*)&session->message_header, 0) < 0) { - log_warn (LOG_NETLINK, std::format ("Failed to send netlink message. {}", strerror (errno))); + log_warn (LOG_NETLINK, "Failed to send netlink message. {}", strerror (errno)); return -1; } @@ -529,7 +529,7 @@ parse_netlink_reply (netlink_session *session, struct _monodroid_ifaddrs **ifadd abort_if_invalid_pointer_argument (last_ifaddr, "last_ifaddr"); size_t buf_size = static_cast(getpagesize ()); - log_debug (LOG_NETLINK, std::format ("receive buffer size == {}", buf_size)); + log_debug (LOG_NETLINK, "receive buffer size == {}", buf_size); size_t alloc_size = Helpers::multiply_with_overflow_check (sizeof(*response), buf_size); response = (unsigned char*)malloc (alloc_size); @@ -551,10 +551,10 @@ parse_netlink_reply (netlink_session *session, struct _monodroid_ifaddrs **ifadd netlink_reply.msg_iov = &reply_vector; length = recvmsg (session->sock_fd, &netlink_reply, 0); - log_debug (LOG_NETLINK, std::format (" length == {}", (int)length)); + log_debug (LOG_NETLINK, " length == {}", (int)length); if (length < 0) { - log_debug (LOG_NETLINK, std::format ("Failed to receive reply from netlink. {}", strerror (errno))); + log_debug (LOG_NETLINK, "Failed to receive reply from netlink. {}", strerror (errno)); goto cleanup; } @@ -582,7 +582,7 @@ parse_netlink_reply (netlink_session *session, struct _monodroid_ifaddrs **ifadd break; for (current_message = (struct nlmsghdr*)response; current_message && NLMSG_OK (current_message, static_cast(length)); current_message = NLMSG_NEXT (current_message, length)) { - log_debug (LOG_NETLINK, std::format ("next message... (type: {})", current_message->nlmsg_type)); + log_debug (LOG_NETLINK, "next message... (type: {})", current_message->nlmsg_type); switch (current_message->nlmsg_type) { /* See rtnetlink.h */ case RTM_NEWLINK: @@ -611,7 +611,7 @@ parse_netlink_reply (netlink_session *session, struct _monodroid_ifaddrs **ifadd break; default: - log_debug (LOG_NETLINK, std::format (" message type: {}", current_message->nlmsg_type)); + log_debug (LOG_NETLINK, " message type: {}", current_message->nlmsg_type); break; } } @@ -634,7 +634,7 @@ fill_sa_address (struct sockaddr **sa, struct ifaddrmsg *net_address, void *rta_ case AF_INET: { struct sockaddr_in *sa4; if (rta_payload_length != 4) /* IPv4 address length */ { - log_warn (LOG_NETLINK, std::format ("Unexpected IPv4 address payload length {}", rta_payload_length)); + log_warn (LOG_NETLINK, "Unexpected IPv4 address payload length {}", rta_payload_length); return -1; } sa4 = (struct sockaddr_in*)calloc (1, sizeof (*sa4)); @@ -650,7 +650,7 @@ fill_sa_address (struct sockaddr **sa, struct ifaddrmsg *net_address, void *rta_ case AF_INET6: { struct sockaddr_in6 *sa6; if (rta_payload_length != 16) /* IPv6 address length */ { - log_warn (LOG_NETLINK, std::format ("Unexpected IPv6 address payload length {}", rta_payload_length)); + log_warn (LOG_NETLINK, "Unexpected IPv6 address payload length {}", rta_payload_length); return -1; } sa6 = (struct sockaddr_in6*)calloc (1, sizeof (*sa6)); @@ -668,7 +668,7 @@ fill_sa_address (struct sockaddr **sa, struct ifaddrmsg *net_address, void *rta_ default: { struct sockaddr *sagen; if (rta_payload_length > sizeof (sagen->sa_data)) { - log_warn (LOG_NETLINK, std::format ("Unexpected RTA payload length {} (wanted at most {})", rta_payload_length, sizeof (sagen->sa_data))); + log_warn (LOG_NETLINK, "Unexpected RTA payload length {} (wanted at most {})", rta_payload_length, sizeof (sagen->sa_data)); return -1; } @@ -701,9 +701,9 @@ fill_ll_address (struct sockaddr_ll_extended **sa, struct ifinfomsg *net_interfa /* The assert can only fail for Iniband links, which are quite unlikely to be found * in any mobile devices */ - log_debug (LOG_NETLINK, std::format ("rta_payload_length == {}; sizeof sll_addr == {}; hw type == {:x}", rta_payload_length, sizeof ((*sa)->sll_addr), net_interface->ifi_type)); + log_debug (LOG_NETLINK, "rta_payload_length == {}; sizeof sll_addr == {}; hw type == {:x}", rta_payload_length, sizeof ((*sa)->sll_addr), net_interface->ifi_type); if (static_cast(rta_payload_length) > sizeof ((*sa)->sll_addr)) { - log_info (LOG_NETLINK, std::format ("Address is too long to place in sockaddr_ll ({} > {})", rta_payload_length, sizeof ((*sa)->sll_addr))); + log_info (LOG_NETLINK, "Address is too long to place in sockaddr_ll ({} > {})", rta_payload_length, sizeof ((*sa)->sll_addr)); free (*sa); *sa = NULL; return -1; @@ -817,14 +817,14 @@ calculate_address_netmask (struct _monodroid_ifaddrs *ifa, struct ifaddrmsg *net memset (netmask_data, 0xFF, prefix_bytes); if (postfix_bytes > 0) memset (netmask_data + prefix_bytes + 1, 0x00, postfix_bytes); - log_debug (LOG_NETLINK, std::format (" calculating netmask, prefix length is {} bits ({} bytes), data length is {} bytes\n", prefix_length, prefix_bytes, data_length)); + log_debug (LOG_NETLINK, " calculating netmask, prefix length is {} bits ({} bytes), data length is {} bytes\n", prefix_length, prefix_bytes, data_length); if (prefix_bytes + 2 < data_length) /* Set the rest of the mask bits in the byte following the last 0xFF value */ netmask_data [prefix_bytes + 1] = static_cast(0xff << (8 - (prefix_length % 8))); if (Util::should_log (LOG_NETLINK)) { log_debug_nocheck (LOG_NETLINK, " netmask is: "sv); for (uint32_t i = 0; i < data_length; i++) { - log_debug_nocheck (LOG_NETLINK, std::format ("{}{}", i == 0 ? " "sv : "."sv, (unsigned char)ifa->ifa_netmask->sa_data [i])); + log_debug_nocheck_fmt (LOG_NETLINK, "{}{}", i == 0 ? " "sv : "."sv, (unsigned char)ifa->ifa_netmask->sa_data [i]); } } } @@ -847,7 +847,7 @@ get_link_address (const struct nlmsghdr *message, struct _monodroid_ifaddrs **if abort_if_invalid_pointer_argument (message, "message"); net_address = reinterpret_cast (NLMSG_DATA (message)); length = static_cast(IFA_PAYLOAD (message)); - log_debug (LOG_NETLINK, std::format (" address data length: {}", length)); + log_debug (LOG_NETLINK, " address data length: {}", length); if (length <= 0) { goto error; } @@ -864,7 +864,7 @@ get_link_address (const struct nlmsghdr *message, struct _monodroid_ifaddrs **if log_debug (LOG_NETLINK, " reading attributes"sv); while (RTA_OK (attribute, length)) { payload_size = RTA_PAYLOAD (attribute); - log_debug (LOG_NETLINK, std::format (" attribute payload_size == {}", payload_size)); + log_debug (LOG_NETLINK, " attribute payload_size == {}", payload_size); sa = NULL; switch (attribute->rta_type) { @@ -943,7 +943,7 @@ get_link_address (const struct nlmsghdr *message, struct _monodroid_ifaddrs **if break; default: - log_debug (LOG_NETLINK, std::format (" attribute type: {}", attribute->rta_type)); + log_debug (LOG_NETLINK, " attribute type: {}", attribute->rta_type); break; } @@ -962,7 +962,7 @@ get_link_address (const struct nlmsghdr *message, struct _monodroid_ifaddrs **if log_debug (LOG_NETLINK, " address has no name/label, getting one from interface"sv); ifa->ifa_name = name ? strdup (name) : NULL; } - log_debug (LOG_NETLINK, std::format (" address label: {}", ifa->ifa_name)); + log_debug (LOG_NETLINK, " address label: {}", ifa->ifa_name); if (calculate_address_netmask (ifa, net_address) < 0) { goto error; @@ -1016,13 +1016,13 @@ get_link_info (const struct nlmsghdr *message) goto error; } if (Util::should_log (LOG_NETLINK)) { - log_debug_nocheck (LOG_NETLINK, std::format (" interface name (payload length: {}; string length: {})", RTA_PAYLOAD (attribute), strlen (ifa->ifa_name))); - log_debug_nocheck (LOG_NETLINK, std::format (" {}", ifa->ifa_name)); + log_debug_nocheck_fmt (LOG_NETLINK, " interface name (payload length: {}; string length: {})", RTA_PAYLOAD (attribute), strlen (ifa->ifa_name)); + log_debug_nocheck_fmt (LOG_NETLINK, " {}", ifa->ifa_name); } break; case IFLA_BROADCAST: - log_debug (LOG_NETLINK, std::format (" interface broadcast ({} bytes)", RTA_PAYLOAD (attribute))); + log_debug (LOG_NETLINK, " interface broadcast ({} bytes)", RTA_PAYLOAD (attribute)); if (fill_ll_address (&sa, net_interface, RTA_DATA (attribute), RTA_PAYLOAD (attribute)) < 0) { goto error; } @@ -1030,7 +1030,7 @@ get_link_info (const struct nlmsghdr *message) break; case IFLA_ADDRESS: - log_debug (LOG_NETLINK, std::format (" interface address ({} bytes)", RTA_PAYLOAD (attribute))); + log_debug (LOG_NETLINK, " interface address ({} bytes)", RTA_PAYLOAD (attribute)); if (fill_ll_address (&sa, net_interface, RTA_DATA (attribute), RTA_PAYLOAD (attribute)) < 0) { goto error; } @@ -1047,7 +1047,7 @@ get_link_info (const struct nlmsghdr *message) attribute = RTA_NEXT (attribute, length); } - log_debug (LOG_NETLINK, std::format ("link flags: {:X}", ifa->ifa_flags)); + log_debug (LOG_NETLINK, "link flags: {:X}", ifa->ifa_flags); return ifa; error: @@ -1142,7 +1142,7 @@ print_ifla_name (int id) int i = 0; while (1) { if (iflas [i].value == -1 && iflas [i].name == 0) { - log_info_nocheck (LOG_NETLINK, std::format ("Unknown ifla->name: unknown id {}", id)); + log_info_nocheck_fmt (LOG_NETLINK, "Unknown ifla->name: unknown id {}", id); break; } @@ -1150,7 +1150,7 @@ print_ifla_name (int id) i++; continue; } - log_info_nocheck (LOG_NETLINK, std::format ("ifla->name: {} ({})", iflas [i].name, iflas [i].value)); + log_info_nocheck_fmt (LOG_NETLINK, "ifla->name: {} ({})", iflas [i].name, iflas [i].value); break; } } @@ -1165,7 +1165,7 @@ print_address_list (const char title[], struct _monodroid_ifaddrs *list) char *msg, *tmp; if (!list) { - log_info_nocheck (LOG_NETLINK, std::format ("No list to print in {}", __FUNCTION__)); + log_info_nocheck_fmt (LOG_NETLINK, "No list to print in {}", __FUNCTION__); return; } @@ -1180,7 +1180,7 @@ print_address_list (const char title[], struct _monodroid_ifaddrs *list) cur = cur->ifa_next; } - log_info_nocheck (LOG_NETLINK, std::format ("{}: {}", title, msg ? msg : "[no addresses]"sv)); + log_info_nocheck_fmt (LOG_NETLINK, "{}: {}", title, msg ? msg : "[no addresses]"sv); free (msg); } #endif diff --git a/src/native/pinvoke-override/pinvoke-override-api-impl.hh b/src/native/pinvoke-override/pinvoke-override-api-impl.hh index 240223b396c..f6c402c46e7 100644 --- a/src/native/pinvoke-override/pinvoke-override-api-impl.hh +++ b/src/native/pinvoke-override/pinvoke-override-api-impl.hh @@ -23,21 +23,21 @@ namespace xamarin::android { constexpr bool PREFER_AOT_CACHE = false; lib_handle = internal::MonodroidDl::monodroid_dlopen (library_name, MONO_DL_LOCAL, nullptr, PREFER_AOT_CACHE); if (lib_handle == nullptr) { - log_warn (LOG_ASSEMBLY, std::format ("Shared library '{}' not loaded, p/invoke '{}' may fail", library_name, symbol_name)); + log_warn (LOG_ASSEMBLY, "Shared library '{}' not loaded, p/invoke '{}' may fail", library_name, symbol_name); return nullptr; } if (dso_handle != nullptr) { void *expected_null = nullptr; if (!__atomic_compare_exchange (dso_handle, &expected_null, &lib_handle, false /* weak */, __ATOMIC_ACQUIRE /* success_memorder */, __ATOMIC_RELAXED /* xxxfailure_memorder */)) { - log_debug (LOG_ASSEMBLY, std::format ("Library '{}' handle already cached by another thread", library_name)); + log_debug (LOG_ASSEMBLY, "Library '{}' handle already cached by another thread", library_name); } } } void *entry_handle = internal::MonodroidDl::monodroid_dlsym (lib_handle, symbol_name, nullptr, nullptr); if (entry_handle == nullptr) { - log_warn (LOG_ASSEMBLY, std::format ("Symbol '{}' not found in shared library '{}', p/invoke may fail", symbol_name, library_name)); + log_warn (LOG_ASSEMBLY, "Symbol '{}' not found in shared library '{}', p/invoke may fail", symbol_name, library_name); return nullptr; } @@ -60,7 +60,7 @@ namespace xamarin::android { return nullptr; } - log_debug (LOG_ASSEMBLY, std::format ("Caching p/invoke entry {} @ {}", library_name, entrypoint_name)); + log_debug (LOG_ASSEMBLY, "Caching p/invoke entry {} @ {}", library_name, entrypoint_name); (*api_map)[entrypoint_name] = entry_handle; return entry_handle; } @@ -81,7 +81,7 @@ namespace xamarin::android { ); if (already_loaded) { - log_debug (LOG_ASSEMBLY, std::format ("Entry '{}' from library '{}' already loaded by another thread", entrypoint_name, library_name)); + log_debug (LOG_ASSEMBLY, "Entry '{}' from library '{}' already loaded by another thread", entrypoint_name, library_name); } } @@ -147,7 +147,7 @@ namespace xamarin::android { handle = fetch_or_create_pinvoke_map_entry (lib_name, entry_name, entrypoint_name_hash, lib_map, /* need_lock */ false); } else { if (iter->second == nullptr) [[unlikely]] { - log_warn (LOG_ASSEMBLY, std::format ("Internal error: null entry in p/invoke map for key '{}'", library_name)); + log_warn (LOG_ASSEMBLY, "Internal error: null entry in p/invoke map for key '{}'", library_name); return nullptr; // fall back to `monodroid_dlopen` } diff --git a/src/native/pinvoke-override/precompiled.cc b/src/native/pinvoke-override/precompiled.cc index 1ef4bbfaba0..e5c54608ff3 100644 --- a/src/native/pinvoke-override/precompiled.cc +++ b/src/native/pinvoke-override/precompiled.cc @@ -22,11 +22,11 @@ PinvokeOverride::monodroid_pinvoke_override (const char *library_name, const cha PinvokeEntry *entry = find_pinvoke_address (entrypoint_hash, internal_pinvokes.data (), internal_pinvokes_count); if (entry == nullptr) [[unlikely]] { - log_fatal (LOG_ASSEMBLY, std::format ("Internal p/invoke symbol '{} @ {}' (hash: {:x}) not found in compile-time map.", library_name, entrypoint_name, entrypoint_hash)); + log_fatal (LOG_ASSEMBLY, "Internal p/invoke symbol '{} @ {}' (hash: {:x}) not found in compile-time map.", library_name, entrypoint_name, entrypoint_hash); log_fatal (LOG_ASSEMBLY, "compile-time map contents:"sv); for (size_t i = 0uz; i < internal_pinvokes_count; i++) { PinvokeEntry const& e = internal_pinvokes[i]; - log_fatal (LOG_ASSEMBLY, std::format ("\t'{}'={:p} (hash: {:x})", e.name, e.func, e.hash)); + log_fatal (LOG_ASSEMBLY, "\t'{}'={:p} (hash: {:x})", e.name, e.func, e.hash); } Helpers::abort_application ( LOG_ASSEMBLY, @@ -67,7 +67,7 @@ PinvokeOverride::monodroid_pinvoke_override (const char *library_name, const cha load_library_entry (library_name, entrypoint_name, *entry, dotnet_dso_handle); if (entry->func == nullptr) { - log_fatal (LOG_ASSEMBLY, std::format ("Failed to load symbol '{}' from shared library '{}'", entrypoint_name, library_name)); + log_fatal (LOG_ASSEMBLY, "Failed to load symbol '{}' from shared library '{}'", entrypoint_name, library_name); return nullptr; // let Mono deal with the fallout } @@ -75,7 +75,7 @@ PinvokeOverride::monodroid_pinvoke_override (const char *library_name, const cha } // It's possible we don't have an entry for some `dotnet` p/invoke, fall back to the slow path below - log_debug (LOG_ASSEMBLY, std::format ("Symbol '{}' in library '{}' not found in the generated tables, falling back to slow path", entrypoint_name, library_name)); + log_debug (LOG_ASSEMBLY, "Symbol '{}' in library '{}' not found in the generated tables, falling back to slow path", entrypoint_name, library_name); } return handle_other_pinvoke_request (library_name, library_name_hash, entrypoint_name, entrypoint_hash); diff --git a/src/native/runtime-base/android-system.cc b/src/native/runtime-base/android-system.cc index 9119fe783a1..d3c8b2c56e4 100644 --- a/src/native/runtime-base/android-system.cc +++ b/src/native/runtime-base/android-system.cc @@ -65,7 +65,7 @@ AndroidSystem::lookup_system_property (const char *name, size_t &value_len) noex return nullptr; if (application_config.system_property_count % 2 != 0) { - log_warn (LOG_DEFAULT, std::format ("Corrupted environment variable array: does not contain an even number of entries ({})", application_config.system_property_count)); + log_warn (LOG_DEFAULT, "Corrupted environment variable array: does not contain an even number of entries ({})", application_config.system_property_count); return nullptr; } @@ -138,7 +138,7 @@ AndroidSystem::_monodroid__system_property_get (const char *name, char *sp_value char *buf = nullptr; if (sp_value_len < PROPERTY_VALUE_BUFFER_LEN) { size_t alloc_size = Helpers::add_with_overflow_check (PROPERTY_VALUE_BUFFER_LEN, 1uz); - log_warn (LOG_DEFAULT, std::format ("Buffer to store system property may be too small, will copy only {} bytes", sp_value_len)); + log_warn (LOG_DEFAULT, "Buffer to store system property may be too small, will copy only {} bytes", sp_value_len); buf = new char [alloc_size]; } @@ -250,12 +250,12 @@ AndroidSystem::monodroid_get_system_property_from_overrides ([[maybe_unused]] co } std::unique_ptr override_file {Util::path_combine (od, name)}; - log_info (LOG_DEFAULT, std::format ("Trying to get property from {}", override_file.get ())); + log_info (LOG_DEFAULT, "Trying to get property from {}", override_file.get ()); size_t result = _monodroid_get_system_property_from_file (override_file.get (), value); if (result == 0 || value == nullptr || (*value) == nullptr || **value == '\0') { continue; } - log_info (LOG_DEFAULT, std::format ("Property '{}' from {} has value '{}'.", name, od, *value)); + log_info (LOG_DEFAULT, "Property '{}' from {} has value '{}'.", name, od, *value); return result; } #endif // def DEBUG @@ -281,7 +281,7 @@ AndroidSystem::create_update_dir (char *override_dir) noexcept override_dirs [0] = override_dir; Util::create_public_directory (override_dir); - log_warn (LOG_DEFAULT, std::format ("Creating public update directory: `{}`", override_dir)); + log_warn (LOG_DEFAULT, "Creating public update directory: `{}`", override_dir); } bool @@ -306,16 +306,16 @@ AndroidSystem::load_dso (const char *path, unsigned int dl_flags, bool skip_exis if (path == nullptr || *path == '\0') return nullptr; - log_info (LOG_ASSEMBLY, std::format ("Trying to load shared library '{}'", path)); + log_info (LOG_ASSEMBLY, "Trying to load shared library '{}'", path); if (!skip_exists_check && !is_embedded_dso_mode_enabled () && !Util::file_exists (path)) { - log_info (LOG_ASSEMBLY, std::format ("Shared library '{}' not found", path)); + log_info (LOG_ASSEMBLY, "Shared library '{}' not found", path); return nullptr; } char *error = nullptr; void *handle = java_interop_lib_load (path, dl_flags, &error); if (handle == nullptr && Util::should_log (LOG_ASSEMBLY)) - log_info_nocheck (LOG_ASSEMBLY, std::format ("Failed to load shared library '{}'. {}", path, error)); + log_info_nocheck (LOG_ASSEMBLY, "Failed to load shared library '{}'. {}", path, error); java_interop_free (error); return handle; } @@ -450,9 +450,9 @@ AndroidSystem::get_max_gref_count_from_system (void) noexcept if (max < 0) max = std::numeric_limits::max (); if (*e) { - log_warn (LOG_GC, std::format ("Unsupported '{}' value '{}'.", SharedConstants::DEBUG_MONO_MAX_GREFC.data (), override.get ())); + log_warn (LOG_GC, "Unsupported '{}' value '{}'.", SharedConstants::DEBUG_MONO_MAX_GREFC.data (), override.get ()); } - log_warn (LOG_GC, std::format ("Overriding max JNI Global Reference count to {}", max)); + log_warn (LOG_GC, "Overriding max JNI Global Reference count to {}", max); } return max; } @@ -478,7 +478,7 @@ AndroidSystem::setup_environment (const char *name, const char *value) noexcept if (isupper (name [0]) || name [0] == '_') { if (setenv (name, v, 1) < 0) - log_warn (LOG_DEFAULT, std::format ("(Debug) Failed to set environment variable: {}", strerror (errno))); + log_warn (LOG_DEFAULT, "(Debug) Failed to set environment variable: {}", strerror (errno)); return; } @@ -492,13 +492,13 @@ AndroidSystem::setup_environment_from_override_file (const char *path) noexcept struct stat sbuf; if (::stat (path, &sbuf) < 0) { - log_warn (LOG_DEFAULT, std::format ("Failed to stat the environment override file {}: {}", path, strerror (errno))); + log_warn (LOG_DEFAULT, "Failed to stat the environment override file {}: {}", path, strerror (errno)); return; } int fd = open (path, O_RDONLY); if (fd < 0) { - log_warn (LOG_DEFAULT, std::format ("Failed to open the environment override file {}: {}", path, strerror (errno))); + log_warn (LOG_DEFAULT, "Failed to open the environment override file {}: {}", path, strerror (errno)); return; } @@ -515,7 +515,7 @@ AndroidSystem::setup_environment_from_override_file (const char *path) noexcept } while (r < 0 && errno == EINTR); if (nread == 0) { - log_warn (LOG_DEFAULT, std::format ("Failed to read the environment override file {}: {}", path, strerror (errno))); + log_warn (LOG_DEFAULT, "Failed to read the environment override file {}: {}", path, strerror (errno)); return; } @@ -536,26 +536,26 @@ AndroidSystem::setup_environment_from_override_file (const char *path) noexcept // # Variable value, terminated with NUL and padded to [value width] with NUL characters // value\0 if (nread < OVERRIDE_ENVIRONMENT_FILE_HEADER_SIZE) { - log_warn (LOG_DEFAULT, std::format ("Invalid format of the environment override file {}: malformatted header", path)); + log_warn (LOG_DEFAULT, "Invalid format of the environment override file {}: malformatted header", path); return; } char *endptr; unsigned long name_width = strtoul (buf.get (), &endptr, 16); if ((name_width == std::numeric_limits::max () && errno == ERANGE) || (buf[0] != '\0' && *endptr != '\0')) { - log_warn (LOG_DEFAULT, std::format ("Malformed header of the environment override file {}: name width has invalid format", path)); + log_warn (LOG_DEFAULT, "Malformed header of the environment override file {}: name width has invalid format", path); return; } unsigned long value_width = strtoul (buf.get () + 11, &endptr, 16); if ((value_width == std::numeric_limits::max () && errno == ERANGE) || (buf[0] != '\0' && *endptr != '\0')) { - log_warn (LOG_DEFAULT, std::format ("Malformed header of the environment override file {}: value width has invalid format", path)); + log_warn (LOG_DEFAULT, "Malformed header of the environment override file {}: value width has invalid format", path); return; } uint64_t data_width = name_width + value_width; if (data_width > file_size - OVERRIDE_ENVIRONMENT_FILE_HEADER_SIZE || (file_size - OVERRIDE_ENVIRONMENT_FILE_HEADER_SIZE) % data_width != 0) { - log_warn (LOG_DEFAULT, std::format ("Malformed environment override file {}: invalid data size", path)); + log_warn (LOG_DEFAULT, "Malformed environment override file {}: invalid data size", path); return; } @@ -563,11 +563,11 @@ AndroidSystem::setup_environment_from_override_file (const char *path) noexcept char *name = buf.get () + OVERRIDE_ENVIRONMENT_FILE_HEADER_SIZE; while (data_size > 0 && data_size >= data_width) { if (*name == '\0') { - log_warn (LOG_DEFAULT, std::format ("Malformed environment override file {}: name at offset {} is empty", path, name - buf.get ())); + log_warn (LOG_DEFAULT, "Malformed environment override file {}: name at offset {} is empty", path, name - buf.get ()); return; } - log_debug (LOG_DEFAULT, std::format ("Setting environment variable from the override file {}: '{}' = '{}'", path, name, name + name_width)); + log_debug (LOG_DEFAULT, "Setting environment variable from the override file {}: '{}' = '{}'", path, name, name + name_width); setup_environment (name, name + name_width); name += data_width; data_size -= data_width; @@ -602,10 +602,10 @@ AndroidSystem::setup_environment () noexcept } if (aotMode != MonoAotMode::MONO_AOT_MODE_LAST) { - log_debug (LOG_DEFAULT, std::format ("Mono AOT mode: {}", mono_aot_mode_name)); + log_debug (LOG_DEFAULT, "Mono AOT mode: {}", mono_aot_mode_name); } else { if (!is_interpreter_enabled ()) { - log_warn (LOG_DEFAULT, std::format ("Unknown Mono AOT mode: {}", mono_aot_mode_name)); + log_warn (LOG_DEFAULT, "Unknown Mono AOT mode: {}", mono_aot_mode_name); } else { log_warn (LOG_DEFAULT, "Mono AOT mode: interpreter"sv); } @@ -613,7 +613,7 @@ AndroidSystem::setup_environment () noexcept } if (application_config.environment_variable_count % 2 != 0) { - log_warn (LOG_DEFAULT, std::format ("Corrupted environment variable array: does not contain an even number of entries ({})", application_config.environment_variable_count)); + log_warn (LOG_DEFAULT, "Corrupted environment variable array: does not contain an even number of entries ({})", application_config.environment_variable_count); return; } @@ -629,10 +629,10 @@ AndroidSystem::setup_environment () noexcept var_value = ""; #if defined (DEBUG) - log_info (LOG_DEFAULT, std::format ("Setting environment variable '{}' to '{}'", var_name, var_value)); + log_info (LOG_DEFAULT, "Setting environment variable '{}' to '{}'", var_name, var_value); #endif // def DEBUG if (setenv (var_name, var_value, 1) < 0) - log_warn (LOG_DEFAULT, std::format ("Failed to set environment variable: {}", strerror (errno))); + log_warn (LOG_DEFAULT, "Failed to set environment variable: {}", strerror (errno)); } #if defined (DEBUG) log_debug (LOG_DEFAULT, "Loading environment from override directories."sv); @@ -641,9 +641,9 @@ AndroidSystem::setup_environment () noexcept continue; } std::unique_ptr env_override_file {Util::path_combine (od, OVERRIDE_ENVIRONMENT_FILE_NAME.data ())}; - log_debug (LOG_DEFAULT, std::format ("{}", env_override_file.get ())); + log_debug (LOG_DEFAULT, "{}", env_override_file.get ()); if (Util::file_exists (env_override_file.get ())) { - log_debug (LOG_DEFAULT, std::format ("Loading {}", env_override_file.get ())); + log_debug (LOG_DEFAULT, "Loading {}", env_override_file.get ()); setup_environment_from_override_file (env_override_file.get ()); } } @@ -671,12 +671,12 @@ AndroidSystem::detect_embedded_dso_mode (jstring_array_wrapper& appDirs) noexcep { // appDirs[SharedConstants::APP_DIRS_DATA_DIR_INDEX] points to the native library directory std::unique_ptr libmonodroid_path {Util::path_combine (appDirs[SharedConstants::APP_DIRS_DATA_DIR_INDEX].get_cstr (), "libmonodroid.so")}; - log_debug (LOG_ASSEMBLY, std::format ("Checking if libmonodroid was unpacked to {}", libmonodroid_path.get ())); + log_debug (LOG_ASSEMBLY, "Checking if libmonodroid was unpacked to {}", libmonodroid_path.get ()); if (!Util::file_exists (libmonodroid_path.get ())) { - log_debug (LOG_ASSEMBLY, std::format ("{} not found, assuming application/android:extractNativeLibs == false", libmonodroid_path.get ())); + log_debug (LOG_ASSEMBLY, "{} not found, assuming application/android:extractNativeLibs == false", libmonodroid_path.get ()); set_embedded_dso_mode_enabled (true); } else { - log_debug (LOG_ASSEMBLY, std::format ("Native libs extracted to {}, assuming application/android:extractNativeLibs == true", appDirs[SharedConstants::APP_DIRS_DATA_DIR_INDEX].get_cstr ())); + log_debug (LOG_ASSEMBLY, "Native libs extracted to {}, assuming application/android:extractNativeLibs == true", appDirs[SharedConstants::APP_DIRS_DATA_DIR_INDEX].get_cstr ()); set_embedded_dso_mode_enabled (false); } } @@ -689,7 +689,7 @@ AndroidSystem::setup_app_library_directories (jstring_array_wrapper& runtimeApks AndroidSystem::app_lib_directories = std::span (single_app_lib_directory); AndroidSystem::app_lib_directories [0] = Util::strdup_new (appDirs[SharedConstants::APP_DIRS_DATA_DIR_INDEX].get_cstr ()); - log_debug (LOG_ASSEMBLY, std::format ("Added filesystem DSO lookup location: {}", appDirs[SharedConstants::APP_DIRS_DATA_DIR_INDEX].get_cstr ())); + log_debug (LOG_ASSEMBLY, "Added filesystem DSO lookup location: {}", appDirs[SharedConstants::APP_DIRS_DATA_DIR_INDEX].get_cstr ()); } else { log_debug (LOG_DEFAULT, "Setting up for DSO lookup directly in the APK"sv); @@ -725,7 +725,7 @@ AndroidSystem::add_apk_libdir (const char *apk, size_t &index, const char *abi) { abort_unless (index < app_lib_directories.size (), "Index out of range"); app_lib_directories [index] = Util::string_concat (apk, "!/lib/", abi); - log_debug (LOG_ASSEMBLY, std::format ("Added APK DSO lookup location: {}", app_lib_directories[index])); + log_debug (LOG_ASSEMBLY, "Added APK DSO lookup location: {}", app_lib_directories[index]); index++; } diff --git a/src/native/runtime-base/logger.cc b/src/native/runtime-base/logger.cc index cc2f2133a97..a331d7112bb 100644 --- a/src/native/runtime-base/logger.cc +++ b/src/native/runtime-base/logger.cc @@ -12,6 +12,7 @@ #include "android-system.hh" #include "cpp-util.hh" +#include "log_level.hh" #include "logger.hh" #include "shared-constants.hh" #include "util.hh" diff --git a/src/native/runtime-base/monodroid-dl.hh b/src/native/runtime-base/monodroid-dl.hh index 43e1b891a0e..4c3df81e077 100644 --- a/src/native/runtime-base/monodroid-dl.hh +++ b/src/native/runtime-base/monodroid-dl.hh @@ -48,11 +48,11 @@ namespace xamarin::android::internal size_t arr_size; if constexpr (WhichCache == CacheKind::AOT) { - log_debug (LOG_ASSEMBLY, std::format ("Looking for hash {:x} in AOT cache", hash)); + log_debug (LOG_ASSEMBLY, "Looking for hash {:x} in AOT cache", hash); arr = aot_dso_cache; arr_size = application_config.number_of_aot_cache_entries; } else if constexpr (WhichCache == CacheKind::DSO) { - log_debug (LOG_ASSEMBLY, std::format ("Looking for hash {:x} in DSO cache", hash)); + log_debug (LOG_ASSEMBLY, "Looking for hash {:x} in DSO cache", hash); arr = dso_cache; arr_size = application_config.number_of_dso_cache_entries; } @@ -102,7 +102,7 @@ namespace xamarin::android::internal if (MonodroidState::is_startup_in_progress ()) { auto ignore_component = [&](const char *label, MonoComponent component) -> bool { if ((application_config.mono_components_mask & component) != component) { - log_info (LOG_ASSEMBLY, std::format ("Mono '{}' component requested but not packaged, ignoring", label)); + log_info (LOG_ASSEMBLY, "Mono '{}' component requested but not packaged, ignoring", label); return true; } @@ -150,7 +150,7 @@ namespace xamarin::android::internal } hash_t name_hash = xxhash::hash (name, strlen (name)); - log_debug (LOG_ASSEMBLY, std::format ("monodroid_dlopen: hash for name '{}' is {:x}", name, name_hash)); + log_debug (LOG_ASSEMBLY, "monodroid_dlopen: hash for name '{}' is {:x}", name, name_hash); DSOCacheEntry *dso = nullptr; if (prefer_aot_cache) { @@ -167,7 +167,7 @@ namespace xamarin::android::internal dso = find_only_dso_cache_entry (name_hash); } - log_debug (LOG_ASSEMBLY, std::format ("monodroid_dlopen: hash match {}found, DSO name is '{}'", dso == nullptr ? "not "sv : ""sv, dso == nullptr ? ""sv : dso->name)); + log_debug (LOG_ASSEMBLY, "monodroid_dlopen: hash match {}found, DSO name is '{}'", dso == nullptr ? "not "sv : ""sv, dso == nullptr ? ""sv : dso->name); if (dso == nullptr) { // DSO not known at build time, try to load it @@ -177,7 +177,7 @@ namespace xamarin::android::internal } if (dso->ignore) { - log_info (LOG_ASSEMBLY, std::format ("Request to load '{}' ignored, it is known not to exist", dso->name)); + log_info (LOG_ASSEMBLY, "Request to load '{}' ignored, it is known not to exist", dso->name); return nullptr; } diff --git a/src/native/runtime-base/strings.hh b/src/native/runtime-base/strings.hh index 393a3783525..65f6603e501 100644 --- a/src/native/runtime-base/strings.hh +++ b/src/native/runtime-base/strings.hh @@ -156,7 +156,7 @@ namespace xamarin::android::internal } if (!can_access (start_index)) { - log_error (LOG_DEFAULT, std::format ("Cannot convert string to integer, index {} is out of range", start_index)); + log_error (LOG_DEFAULT, "Cannot convert string to integer, index {} is out of range", start_index); return false; } @@ -180,17 +180,17 @@ namespace xamarin::android::internal } if (out_of_range || errno == ERANGE) { - log_error (LOG_DEFAULT, std::format ("Value {} is out of range of this type ({}..{})", reinterpret_cast(s), static_cast(min), static_cast(max))); + log_error (LOG_DEFAULT, "Value {} is out of range of this type ({}..{})", reinterpret_cast(s), static_cast(min), static_cast(max)); return false; } if (endp == s) { - log_error (LOG_DEFAULT, std::format ("Value {} does not represent a base {} integer", reinterpret_cast(s), base)); + log_error (LOG_DEFAULT, "Value {} does not represent a base {} integer", reinterpret_cast(s), base); return false; } if (*endp != '\0') { - log_error (LOG_DEFAULT, std::format ("Value {} has non-numeric characters at the end", reinterpret_cast(s))); + log_error (LOG_DEFAULT, "Value {} has non-numeric characters at the end", reinterpret_cast(s)); return false; } diff --git a/src/native/runtime-base/timing-internal.cc b/src/native/runtime-base/timing-internal.cc index 7b23705d880..6efcfdae461 100644 --- a/src/native/runtime-base/timing-internal.cc +++ b/src/native/runtime-base/timing-internal.cc @@ -78,11 +78,11 @@ FastTiming::dump () noexcept log_write (LOG_TIMING, LogLevel::Info, "[2/4] Accumulated performance results"); ns_to_time (total_assembly_load_time, sec, ms, ns); - log_info_nocheck (LOG_TIMING, std::format (" [2/5] Assembly load: {}:{}::{}", sec, ms, ns)); + log_info_nocheck (LOG_TIMING, " [2/5] Assembly load: {}:{}::{}", sec, ms, ns); ns_to_time (total_java_to_managed_time, sec, ms, ns); - log_info_nocheck (LOG_TIMING, std::format (" [2/6] Java to Managed lookup: {}:{}::{}", sec, ms, ns)); + log_info_nocheck (LOG_TIMING, " [2/6] Java to Managed lookup: {}:{}::{}", sec, ms, ns); ns_to_time (total_managed_to_java_time, sec, ms, ns); - log_info_nocheck (LOG_TIMING, std::format (" [2/7] Managed to Java lookup: {}:{}::{}", sec, ms, ns)); + log_info_nocheck (LOG_TIMING, " [2/7] Managed to Java lookup: {}:{}::{}", sec, ms, ns); } diff --git a/src/native/runtime-base/timing-internal.hh b/src/native/runtime-base/timing-internal.hh index 27cc6da274f..d87595ac9bd 100644 --- a/src/native/runtime-base/timing-internal.hh +++ b/src/native/runtime-base/timing-internal.hh @@ -144,7 +144,7 @@ namespace xamarin::android::internal // likely we'll run out of memory way, way, way before that happens size_t old_size = events.capacity (); events.reserve (old_size << 1); - log_warn (LOG_TIMING, std::format ("Reallocated timing event buffer from {} to {}", old_size, events.size ())); + log_warn (LOG_TIMING, "Reallocated timing event buffer from {} to {}", old_size, events.size ()); } } @@ -246,7 +246,7 @@ namespace xamarin::android::internal force_inline bool is_valid_event_index (size_t index, const char *method_name) noexcept { if (index >= events.capacity ()) [[unlikely]] { - log_warn (LOG_TIMING, std::format ("Invalid event index passed to method '{}'", method_name)); + log_warn (LOG_TIMING, "Invalid event index passed to method '{}'", method_name); return false; } diff --git a/src/native/runtime-base/timing.hh b/src/native/runtime-base/timing.hh index 31f9892e918..191ec55df2f 100644 --- a/src/native/runtime-base/timing.hh +++ b/src/native/runtime-base/timing.hh @@ -93,14 +93,14 @@ namespace xamarin::android { timing_diff diff (period); - log_info_nocheck (LOG_TIMING, std::format (MESSAGE_FORMAT, message == nullptr ? ""sv : message, diff.sec, diff.ms, diff.ns)); + log_info_nocheck (LOG_TIMING, MESSAGE_FORMAT.data (), message == nullptr ? ""sv : message, diff.sec, diff.ms, diff.ns); } static void warn (timing_period const &period, const char *message) noexcept { timing_diff diff (period); - log_warn (LOG_TIMING, std::format (MESSAGE_FORMAT, message == nullptr ? ""sv : message, diff.sec, diff.ms, diff.ns)); + log_warn (LOG_TIMING, MESSAGE_FORMAT.data (), message == nullptr ? ""sv : message, diff.sec, diff.ms, diff.ns); } managed_timing_sequence* get_available_sequence () noexcept diff --git a/src/native/runtime-base/util.cc b/src/native/runtime-base/util.cc index f7350c82ba4..e0c568124ea 100644 --- a/src/native/runtime-base/util.cc +++ b/src/native/runtime-base/util.cc @@ -149,7 +149,7 @@ Util::create_public_directory (const char *dir) mode_t m = umask (0); int ret = mkdir (dir, 0777); if (ret < 0) { - log_warn (LOG_DEFAULT, std::format ("Failed to create directory '{}'. {}", dir, std::strerror (errno))); + log_warn (LOG_DEFAULT, "Failed to create directory '{}'. {}", dir, std::strerror (errno)); } umask (m); } @@ -197,7 +197,7 @@ Util::set_world_accessable ([[maybe_unused]] const char *path) } while (r == -1 && errno == EINTR); if (r == -1) { - log_error (LOG_DEFAULT, std::format ("chmod(\"{}\", 0664) failed: {}", path, strerror (errno))); + log_error (LOG_DEFAULT, "chmod(\"{}\", 0664) failed: {}", path, strerror (errno)); } } @@ -210,7 +210,7 @@ Util::set_user_executable ([[maybe_unused]] const char *path) } while (r == -1 && errno == EINTR); if (r == -1) { - log_error (LOG_DEFAULT, std::format ("chmod(\"{}\") failed: {}", path, strerror (errno))); + log_error (LOG_DEFAULT, "chmod(\"{}\") failed: {}", path, strerror (errno)); } } @@ -297,7 +297,7 @@ Util::monodroid_fopen (const char *filename, const char *mode) */ ret = fopen (filename, mode); if (ret == nullptr) { - log_error (LOG_DEFAULT, std::format ("fopen failed for file {}: {}", filename, strerror (errno))); + log_error (LOG_DEFAULT, "fopen failed for file {}: {}", filename, strerror (errno)); return nullptr; } diff --git a/src/native/runtime-base/util.hh b/src/native/runtime-base/util.hh index 35eb8c3c590..986f7f2e49a 100644 --- a/src/native/runtime-base/util.hh +++ b/src/native/runtime-base/util.hh @@ -79,7 +79,7 @@ namespace xamarin::android { struct stat sbuf; if (fstatat (dirfd, file_name, &sbuf, 0) == -1) { - log_warn (LOG_ASSEMBLY, std::format ("Failed to stat file '{}': {}", file_name, std::strerror (errno))); + log_warn (LOG_ASSEMBLY, "Failed to stat file '{}': {}", file_name, std::strerror (errno)); return std::nullopt; } @@ -90,7 +90,7 @@ namespace xamarin::android { int fd = openat (dirfd, file_name, O_RDONLY); if (fd < 0) { - log_error (LOG_ASSEMBLY, std::format ("Failed to open file '{}' for reading: {}", file_name, std::strerror (errno))); + log_error (LOG_ASSEMBLY, "Failed to open file '{}' for reading: {}", file_name, std::strerror (errno)); return std::nullopt; } diff --git a/src/native/shared/cpp-util.hh b/src/native/shared/cpp-util.hh index 8c2397218f5..3951b81f474 100644 --- a/src/native/shared/cpp-util.hh +++ b/src/native/shared/cpp-util.hh @@ -83,7 +83,7 @@ abort_if_negative_integer_argument (int arg, const char *arg_name, std::source_l // of the calls present. force_inline inline void pd_log_location (std::source_location sloc = std::source_location::current ()) noexcept { - log_info_nocheck (LOG_DEFAULT, std::format ("loc: {}:{} ('{}')", sloc.file_name (), sloc.line (), sloc.function_name ())); + log_info_nocheck (LOG_DEFAULT, "loc: {}:{} ('{}')", sloc.file_name (), sloc.line (), sloc.function_name ()); } namespace xamarin::android diff --git a/src/native/shared/helpers.cc b/src/native/shared/helpers.cc index 645f30e0d84..9638b16ebd5 100644 --- a/src/native/shared/helpers.cc +++ b/src/native/shared/helpers.cc @@ -11,7 +11,7 @@ using namespace xamarin::android; Helpers::abort_application (LogCategories category, const char *message, bool log_location, std::source_location sloc) noexcept { // Log it, but also... - log_fatal (category, std::string_view { message }); + log_fatal (category, "{}", message); // ...let android include it in the tombstone, debuggerd output, stack trace etc android_set_abort_message (message); @@ -35,12 +35,11 @@ Helpers::abort_application (LogCategories category, const char *message, bool lo log_fatal ( category, - std::format ("Abort at {}:{}:{} ('%s')", - file_name, - sloc.line (), - sloc.column (), - sloc.function_name () - ) + "Abort at {}:{}:{} ('%s')", + file_name, + sloc.line (), + sloc.column (), + sloc.function_name () ); } std::abort (); diff --git a/src/native/shared/log_functions.cc b/src/native/shared/log_functions.cc index e82f2bd5856..c6d61f54d0d 100644 --- a/src/native/shared/log_functions.cc +++ b/src/native/shared/log_functions.cc @@ -3,8 +3,8 @@ #include -//#include "java-interop-logger.h" -#include "log_types.hh" +#include "java-interop-logger.h" +#include "log_level.hh" // Must match the same ordering as LogCategories static constexpr std::array log_names = { diff --git a/src/native/shared/log_level.hh b/src/native/shared/log_level.hh new file mode 100644 index 00000000000..fc7a7566910 --- /dev/null +++ b/src/native/shared/log_level.hh @@ -0,0 +1,26 @@ +#pragma once + +#include + +namespace xamarin::android { + enum class LogTimingCategories : uint32_t + { + Default = 0, + Bare = 1 << 0, + FastBare = 1 << 1, + }; + + // Keep in sync with LogLevel defined in JNIEnv.cs + enum class LogLevel : unsigned int + { + Unknown = 0x00, + Default = 0x01, + Verbose = 0x02, + Debug = 0x03, + Info = 0x04, + Warn = 0x05, + Error = 0x06, + Fatal = 0x07, + Silent = 0x08 + }; +} diff --git a/src/native/shared/log_types.hh b/src/native/shared/log_types.hh index 31a1b22dac0..66b1cae5097 100644 --- a/src/native/shared/log_types.hh +++ b/src/native/shared/log_types.hh @@ -6,6 +6,7 @@ #include #include "java-interop-logger.h" +#include "log_level.hh" // We redeclare macros here #if defined(log_debug) @@ -16,59 +17,42 @@ #undef log_info #endif -#define DO_LOG_FMT(_level, _category_, _message_) \ +#define DO_LOG_FMT(_level, _category_, _fmt_, ...) \ do { \ if ((log_categories & ((_category_))) != 0) { \ - ::log_ ## _level ## _nocheck ((_category_), _message_); \ + ::log_ ## _level ## _nocheck_fmt ((_category_), _fmt_ __VA_OPT__(,) __VA_ARGS__); \ } \ } while (0) -#define log_debug(_category_, _message_) DO_LOG_FMT (debug, (_category_), (_message_)) -#define log_info(_category_, _message_) DO_LOG_FMT (info, (_category_), (_message_)) +// +// For std::format spec, see https://en.cppreference.com/w/cpp/utility/format/spec +// -namespace xamarin::android { - enum class LogTimingCategories : uint32_t - { - Default = 0, - Bare = 1 << 0, - FastBare = 1 << 1, - }; - - // Keep in sync with LogLevel defined in JNIEnv.cs - enum class LogLevel : unsigned int - { - Unknown = 0x00, - Default = 0x01, - Verbose = 0x02, - Debug = 0x03, - Info = 0x04, - Warn = 0x05, - Error = 0x06, - Fatal = 0x07, - Silent = 0x08 - }; +// NOTE: _fmt_ takes arguments in the std::format style not the POSIX printf style +#define log_debug(_category_, _fmt_, ...) DO_LOG_FMT (debug, (_category_), (_fmt_) __VA_OPT__(,) __VA_ARGS__) + +// NOTE: _fmt_ takes arguments in the std::format style not the POSIX printf style +#define log_info(_category_, _fmt_, ...) DO_LOG_FMT (info, (_category_), (_fmt_) __VA_OPT__(,) __VA_ARGS__) + +// NOTE: _fmt_ takes arguments in the std::format style not the POSIX printf style +#define log_warn(_category_, _fmt_, ...) log_warn_fmt ((_category_), (_fmt_) __VA_OPT__(,) __VA_ARGS__) +// NOTE: _fmt_ takes arguments in the std::format style not the POSIX printf style +#define log_error(_category_, _fmt_, ...) log_error_fmt ((_category_), (_fmt_) __VA_OPT__(,) __VA_ARGS__) + +// NOTE: _fmt_ takes arguments in the std::format style not the POSIX printf style +#define log_fatal(_category_, _fmt_, ...) log_fatal_fmt ((_category_), (_fmt_) __VA_OPT__(,) __VA_ARGS__) + +namespace xamarin::android { // A slightly faster alternative to other log functions as it doesn't parse the message // for format placeholders nor it uses variable arguments void log_write (LogCategories category, LogLevel level, const char *message) noexcept; } -// -// This will be enabled once all log_* calls are converted to std::format format -// -// template [[gnu::always_inline]] -// static inline constexpr void log_debug (LogCategories category, std::format_string fmt, Args&& ...args) -// { -// if (detail::_category_is_enabled (category)) { - -// log_debug_nocheck (category, std::format (fmt, std::forward(args)...).c_str ()); -// } -// } - -[[gnu::always_inline]] -static inline constexpr void log_debug_nocheck (LogCategories category, std::string const& message) noexcept +template [[gnu::always_inline]] +static inline constexpr void log_debug_nocheck_fmt (LogCategories category, std::format_string fmt, Args&& ...args) { - log_write (category, xamarin::android::LogLevel::Debug, message.c_str ()); + log_write (category, xamarin::android::LogLevel::Debug, std::format (fmt, std::forward(args)...).c_str ()); } [[gnu::always_inline]] @@ -77,10 +61,10 @@ static inline constexpr void log_debug_nocheck (LogCategories category, std::str log_write (category, xamarin::android::LogLevel::Debug, message.data ()); } -[[gnu::always_inline]] -static inline constexpr void log_info_nocheck (LogCategories category, std::string const& message) noexcept +template [[gnu::always_inline]] +static inline constexpr void log_info_nocheck_fmt (LogCategories category, std::format_string fmt, Args&& ...args) { - log_write (category, xamarin::android::LogLevel::Info, message.c_str ()); + log_write (category, xamarin::android::LogLevel::Info, std::format (fmt, std::forward(args)...).c_str ()); } [[gnu::always_inline]] @@ -89,38 +73,38 @@ static inline constexpr void log_info_nocheck (LogCategories category, std::stri log_write (category, xamarin::android::LogLevel::Info, message.data ()); } -[[gnu::always_inline]] -static inline constexpr void log_warn (LogCategories category, std::string const& message) noexcept +template [[gnu::always_inline]] +static inline constexpr void log_warn_fmt (LogCategories category, std::format_string fmt, Args&& ...args) noexcept { - log_write (category, xamarin::android::LogLevel::Warn, message.c_str ()); + log_write (category, xamarin::android::LogLevel::Warn, std::format (fmt, std::forward(args)...).c_str ()); } [[gnu::always_inline]] -static inline constexpr void log_warn (LogCategories category, std::string_view const& message) noexcept +static inline constexpr void log_warn_fmt (LogCategories category, std::string_view const& message) noexcept { log_write (category, xamarin::android::LogLevel::Warn, message.data ()); } -[[gnu::always_inline]] -static inline constexpr void log_error (LogCategories category, std::string const& message) noexcept +template [[gnu::always_inline]] +static inline constexpr void log_error_fmt (LogCategories category, std::format_string fmt, Args&& ...args) noexcept { - log_write (category, xamarin::android::LogLevel::Error, message.c_str ()); + log_write (category, xamarin::android::LogLevel::Error, std::format (fmt, std::forward(args)...).c_str ()); } [[gnu::always_inline]] -static inline constexpr void log_error (LogCategories category, std::string_view const& message) noexcept +static inline constexpr void log_error_fmt (LogCategories category, std::string_view const& message) noexcept { log_write (category, xamarin::android::LogLevel::Error, message.data ()); } -[[gnu::always_inline]] -static inline constexpr void log_fatal (LogCategories category, std::string const& message) noexcept +template [[gnu::always_inline]] +static inline constexpr void log_fatal_fmt (LogCategories category, std::format_string fmt, Args&& ...args) noexcept { - log_write (category, xamarin::android::LogLevel::Fatal, message.c_str ()); + log_write (category, xamarin::android::LogLevel::Fatal, std::format (fmt, std::forward(args)...).c_str ()); } [[gnu::always_inline]] -static inline constexpr void log_fatal (LogCategories category, std::string_view const& message) noexcept +static inline constexpr void log_fatal_fmt (LogCategories category, std::string_view const& message) noexcept { log_write (category, xamarin::android::LogLevel::Fatal, message.data ()); } diff --git a/src/native/xamarin-debug-app-helper/debug-app-helper.cc b/src/native/xamarin-debug-app-helper/debug-app-helper.cc index ae8c2cd4bc6..ac3e9e75e81 100644 --- a/src/native/xamarin-debug-app-helper/debug-app-helper.cc +++ b/src/native/xamarin-debug-app-helper/debug-app-helper.cc @@ -48,7 +48,7 @@ Java_mono_android_DebugRuntime_init (JNIEnv *env, [[maybe_unused]] jclass klass, if (runtimeNativeLibDir != nullptr) { jstr = runtimeNativeLibDir; AndroidSystem::set_runtime_libdir (Util::strdup_new (jstr.get_cstr ())); - log_warn (LOG_DEFAULT, std::format ("Using runtime path: {}", AndroidSystem::get_runtime_libdir ())); + log_warn (LOG_DEFAULT, "Using runtime path: {}", AndroidSystem::get_runtime_libdir ()); } const char *monosgen_path = get_libmonosgen_path (); @@ -74,10 +74,8 @@ copy_file_to_internal_location (char *to_dir, char *from_dir, char *file) break; log_warn (LOG_DEFAULT, - std::format ( - "Copying file `{}` from external location `{}` to internal location `{}`", - file, from_dir, to_dir - ) + "Copying file `{}` from external location `{}` to internal location `{}`", + file, from_dir, to_dir ); to_file = Util::path_combine (to_dir, file); @@ -86,12 +84,12 @@ copy_file_to_internal_location (char *to_dir, char *from_dir, char *file) int r = unlink (to_file); if (r < 0 && errno != ENOENT) { - log_warn (LOG_DEFAULT, std::format ("Unable to delete file `{}`: {}", to_file, strerror (errno))); + log_warn (LOG_DEFAULT, "Unable to delete file `{}`: {}", to_file, strerror (errno)); break; } if (!Util::file_copy (to_file, from_file)) { - log_warn (LOG_DEFAULT, std::format ("Copy failed from `{}` to `{}`: {}", from_file, to_file, strerror (errno))); + log_warn (LOG_DEFAULT, "Copy failed from `{}` to `{}`: {}", from_file, to_file, strerror (errno)); break; } @@ -110,22 +108,22 @@ copy_native_libraries_to_internal_location () dirent *e; char *dir_path = Util::path_combine (od, "lib"); - log_warn (LOG_DEFAULT, std::format ("checking directory: `{}`", dir_path)); + log_warn (LOG_DEFAULT, "checking directory: `{}`", dir_path); if (dir_path == nullptr || !Util::directory_exists (dir_path)) { - log_warn (LOG_DEFAULT, std::format ("directory does not exist: `{}`", dir_path)); + log_warn (LOG_DEFAULT, "directory does not exist: `{}`", dir_path); delete[] dir_path; continue; } if ((dir = ::opendir (dir_path)) == nullptr) { - log_warn (LOG_DEFAULT, std::format ("could not open directory: `{}`", dir_path)); + log_warn (LOG_DEFAULT, "could not open directory: `{}`", dir_path); delete[] dir_path; continue; } while ((e = readdir (dir)) != nullptr) { - log_warn (LOG_DEFAULT, std::format ("checking file: `{}`", e->d_name)); + log_warn (LOG_DEFAULT, "checking file: `{}`", e->d_name); if (Util::monodroid_dirent_hasextension (e, ".so")) { copy_file_to_internal_location (AndroidSystem::get_primary_override_dir (), dir_path, e->d_name); } @@ -142,9 +140,9 @@ runtime_exists (const char *dir, char*& libmonoso) return false; libmonoso = Util::path_combine (dir, SharedConstants::MONO_SGEN_SO); - log_warn (LOG_DEFAULT, std::format ("Checking whether Mono runtime exists at: {}", libmonoso)); + log_warn (LOG_DEFAULT, "Checking whether Mono runtime exists at: {}", libmonoso); if (Util::file_exists (libmonoso)) { - log_info (LOG_DEFAULT, std::format ("Mono runtime found at: {}", libmonoso)); + log_info (LOG_DEFAULT, "Mono runtime found at: {}", libmonoso); return true; } delete[] libmonoso; @@ -196,25 +194,25 @@ get_libmonosgen_path () if (!Util::file_exists (link)) { int result = symlink (libmonoso, link); if (result != 0 && errno == EEXIST) { - log_warn (LOG_DEFAULT, std::format ("symlink exists, recreating: {} -> {}", link, libmonoso)); + log_warn (LOG_DEFAULT, "symlink exists, recreating: {} -> {}", link, libmonoso); unlink (link); result = symlink (libmonoso, link); } if (result != 0) - log_warn (LOG_DEFAULT, std::format ("symlink failed with errno={} {}", errno, strerror (errno))); + log_warn (LOG_DEFAULT, "symlink failed with errno={} {}", errno, strerror (errno)); } delete[] libmonoso; libmonoso = link; } - log_warn (LOG_DEFAULT, std::format ("Trying to load sgen from: {}", libmonoso != nullptr ? libmonoso : ""sv)); + log_warn (LOG_DEFAULT, "Trying to load sgen from: {}", libmonoso != nullptr ? libmonoso : ""sv); if (libmonoso != nullptr && Util::file_exists (libmonoso)) return libmonoso; delete[] libmonoso; if (runtime_exists (AndroidSystem::SYSTEM_LIB_PATH.data (), libmonoso)) return libmonoso; - log_fatal (LOG_DEFAULT, std::format ("Cannot find '{}'. Looked in the following locations:", SharedConstants::MONO_SGEN_SO)); + log_fatal (LOG_DEFAULT, "Cannot find '{}'. Looked in the following locations:", SharedConstants::MONO_SGEN_SO); for (const char *od : AndroidSystem::override_dirs) { if (od == nullptr) From 886ef402920ed643636c7411a659f2c494292569 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Fri, 29 Nov 2024 09:54:16 +0100 Subject: [PATCH 20/54] Cleanup --- src/native/shared/helpers.hh | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/native/shared/helpers.hh b/src/native/shared/helpers.hh index 078da3afac0..c69d49d7ee3 100644 --- a/src/native/shared/helpers.hh +++ b/src/native/shared/helpers.hh @@ -2,14 +2,12 @@ #define __HELPERS_HH #include -#include #include #include #include #include #include "platform-compat.hh" -#include "log_types.hh" using namespace std::string_view_literals; From 15d864fcc78e4e9fdd7a00760e251d00278c5920 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Fri, 29 Nov 2024 10:01:06 +0100 Subject: [PATCH 21/54] Cleanup --- src/native/runtime-base/internal-pinvokes.hh | 1 - 1 file changed, 1 deletion(-) diff --git a/src/native/runtime-base/internal-pinvokes.hh b/src/native/runtime-base/internal-pinvokes.hh index 84477577de8..b8e7a4ae424 100644 --- a/src/native/runtime-base/internal-pinvokes.hh +++ b/src/native/runtime-base/internal-pinvokes.hh @@ -3,7 +3,6 @@ #include #include -//#include #include #include From 00f55b55b840df1d544dcc5fbb92891a9e862981 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Fri, 29 Nov 2024 10:11:56 +0100 Subject: [PATCH 22/54] Update apkdesc files --- .../BuildReleaseArm64SimpleDotNet.apkdesc | 14 +++--- .../BuildReleaseArm64XFormsDotNet.apkdesc | 45 +++++++++---------- 2 files changed, 28 insertions(+), 31 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleDotNet.apkdesc b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleDotNet.apkdesc index b94b94d9485..69f5f2ca92d 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleDotNet.apkdesc +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleDotNet.apkdesc @@ -5,7 +5,7 @@ "Size": 3036 }, "classes.dex": { - "Size": 389632 + "Size": 22444 }, "lib/arm64-v8a/lib__Microsoft.Android.Resource.Designer.dll.so": { "Size": 18296 @@ -14,10 +14,10 @@ "Size": 86352 }, "lib/arm64-v8a/lib_Mono.Android.dll.so": { - "Size": 116768 + "Size": 116920 }, "lib/arm64-v8a/lib_Mono.Android.Runtime.dll.so": { - "Size": 22416 + "Size": 22408 }, "lib/arm64-v8a/lib_System.Console.dll.so": { "Size": 24376 @@ -44,7 +44,7 @@ "Size": 87432 }, "lib/arm64-v8a/libmonodroid.so": { - "Size": 903032 + "Size": 1501240 }, "lib/arm64-v8a/libmonosgen-2.0.so": { "Size": 3196512 @@ -62,10 +62,10 @@ "Size": 160232 }, "lib/arm64-v8a/libxamarin-app.so": { - "Size": 13016 + "Size": 18264 }, "META-INF/BNDLTOOL.RSA": { - "Size": 1223 + "Size": 1221 }, "META-INF/BNDLTOOL.SF": { "Size": 3266 @@ -98,5 +98,5 @@ "Size": 1904 } }, - "PackageSize": 2984469 + "PackageSize": 3111445 } \ No newline at end of file diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsDotNet.apkdesc b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsDotNet.apkdesc index 40a70162747..eb04b2212b1 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsDotNet.apkdesc +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsDotNet.apkdesc @@ -5,10 +5,7 @@ "Size": 6652 }, "classes.dex": { - "Size": 9448880 - }, - "classes2.dex": { - "Size": 154180 + "Size": 9172764 }, "kotlin/annotation/annotation.kotlin_builtins": { "Size": 928 @@ -35,16 +32,16 @@ "Size": 19544 }, "lib/arm64-v8a/lib_FormsViewGroup.dll.so": { - "Size": 25184 + "Size": 25424 }, "lib/arm64-v8a/lib_Java.Interop.dll.so": { "Size": 94736 }, "lib/arm64-v8a/lib_Mono.Android.dll.so": { - "Size": 522832 + "Size": 524256 }, "lib/arm64-v8a/lib_Mono.Android.Runtime.dll.so": { - "Size": 22416 + "Size": 22408 }, "lib/arm64-v8a/lib_mscorlib.dll.so": { "Size": 21432 @@ -173,31 +170,31 @@ "Size": 22096 }, "lib/arm64-v8a/lib_Xamarin.AndroidX.Activity.dll.so": { - "Size": 34760 + "Size": 34960 }, "lib/arm64-v8a/lib_Xamarin.AndroidX.AppCompat.AppCompatResources.dll.so": { - "Size": 24296 + "Size": 24512 }, "lib/arm64-v8a/lib_Xamarin.AndroidX.AppCompat.dll.so": { - "Size": 163072 + "Size": 163240 }, "lib/arm64-v8a/lib_Xamarin.AndroidX.CardView.dll.so": { "Size": 24560 }, "lib/arm64-v8a/lib_Xamarin.AndroidX.CoordinatorLayout.dll.so": { - "Size": 35680 + "Size": 35912 }, "lib/arm64-v8a/lib_Xamarin.AndroidX.Core.dll.so": { - "Size": 151216 + "Size": 151408 }, "lib/arm64-v8a/lib_Xamarin.AndroidX.CursorAdapter.dll.so": { "Size": 27168 }, "lib/arm64-v8a/lib_Xamarin.AndroidX.DrawerLayout.dll.so": { - "Size": 33760 + "Size": 33944 }, "lib/arm64-v8a/lib_Xamarin.AndroidX.Fragment.dll.so": { - "Size": 72224 + "Size": 72528 }, "lib/arm64-v8a/lib_Xamarin.AndroidX.Legacy.Support.Core.UI.dll.so": { "Size": 23896 @@ -215,16 +212,16 @@ "Size": 31592 }, "lib/arm64-v8a/lib_Xamarin.AndroidX.RecyclerView.dll.so": { - "Size": 111896 + "Size": 112248 }, "lib/arm64-v8a/lib_Xamarin.AndroidX.SavedState.dll.so": { "Size": 23144 }, "lib/arm64-v8a/lib_Xamarin.AndroidX.SwipeRefreshLayout.dll.so": { - "Size": 31672 + "Size": 31952 }, "lib/arm64-v8a/lib_Xamarin.AndroidX.ViewPager.dll.so": { - "Size": 37752 + "Size": 38048 }, "lib/arm64-v8a/lib_Xamarin.Forms.Core.dll.so": { "Size": 581000 @@ -239,7 +236,7 @@ "Size": 80632 }, "lib/arm64-v8a/lib_Xamarin.Google.Android.Material.dll.so": { - "Size": 84400 + "Size": 84768 }, "lib/arm64-v8a/libarc.bin.so": { "Size": 18776 @@ -248,7 +245,7 @@ "Size": 87432 }, "lib/arm64-v8a/libmonodroid.so": { - "Size": 903032 + "Size": 1501240 }, "lib/arm64-v8a/libmonosgen-2.0.so": { "Size": 3196512 @@ -266,7 +263,7 @@ "Size": 160232 }, "lib/arm64-v8a/libxamarin-app.so": { - "Size": 120016 + "Size": 349440 }, "META-INF/androidx.activity_activity.version": { "Size": 6 @@ -419,10 +416,10 @@ "Size": 6 }, "META-INF/BNDLTOOL.RSA": { - "Size": 1221 + "Size": 1223 }, "META-INF/BNDLTOOL.SF": { - "Size": 98661 + "Size": 98577 }, "META-INF/com.android.tools/proguard/coroutines.pro": { "Size": 1345 @@ -449,7 +446,7 @@ "Size": 5 }, "META-INF/MANIFEST.MF": { - "Size": 98534 + "Size": 98450 }, "META-INF/maven/com.google.guava/listenablefuture/pom.properties": { "Size": 96 @@ -2489,5 +2486,5 @@ "Size": 812848 } }, - "PackageSize": 10796357 + "PackageSize": 10947851 } \ No newline at end of file From d383a44e3fb7878825c8a7df957e39d248a1f881 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Fri, 29 Nov 2024 18:10:25 +0100 Subject: [PATCH 23/54] std::format doesn't like null pointers when printing strings --- src/native/monodroid/debug.cc | 22 +- .../monodroid/embedded-assemblies-zip.cc | 33 +-- src/native/monodroid/embedded-assemblies.cc | 196 +++++++++++++----- src/native/monodroid/embedded-assemblies.hh | 9 +- src/native/monodroid/mono-image-loader.hh | 2 +- src/native/monodroid/monodroid-glue.cc | 40 ++-- src/native/monodroid/osbridge.cc | 75 +++---- .../monodroid/xamarin-android-app-context.cc | 10 +- src/native/monodroid/xamarin_getifaddrs.cc | 8 +- .../pinvoke-override-api-impl.hh | 8 +- src/native/pinvoke-override/precompiled.cc | 15 +- src/native/runtime-base/logger.cc | 18 +- src/native/shared/helpers.hh | 10 + .../debug-app-helper.cc | 30 +-- 14 files changed, 293 insertions(+), 183 deletions(-) diff --git a/src/native/monodroid/debug.cc b/src/native/monodroid/debug.cc index cbcdeec2e87..8839ded308a 100644 --- a/src/native/monodroid/debug.cc +++ b/src/native/monodroid/debug.cc @@ -96,8 +96,8 @@ Debug::monodroid_profiler_load (const char *libmono_path, const char *desc, cons if (!found) log_warn (LOG_DEFAULT, "The '{}' profiler wasn't found in the main executable nor could it be loaded from '{}'.", - mname.get (), - libname.get () + optional_string (mname.get ()), + optional_string (libname.get ()) ); } @@ -109,7 +109,7 @@ bool Debug::load_profiler (void *handle, const char *desc, const char *symbol) { ProfilerInitializer func = reinterpret_cast (java_interop_lib_symbol (handle, symbol, nullptr)); - log_warn (LOG_DEFAULT, "Looking for profiler init symbol '{}'? {:p}", symbol, reinterpret_cast(func)); + log_warn (LOG_DEFAULT, "Looking for profiler init symbol '{}'? {:p}", optional_string (symbol), reinterpret_cast(func)); if (func != nullptr) { func (desc); @@ -139,7 +139,7 @@ Debug::parse_options (char *options, ConnOptions *opts) { char **args, **ptr; - log_info (LOG_DEFAULT, "Connection options: '{}'", options); + log_info (LOG_DEFAULT, "Connection options: '{}'", optional_string (options)); args = Util::monodroid_strsplit (options, ",", 0); @@ -163,7 +163,7 @@ Debug::parse_options (char *options, ConnOptions *opts) if ((endp == arg) || (*endp != '\0')) log_error (LOG_DEFAULT, "Invalid --timeout argument."sv); } else { - log_info (LOG_DEFAULT, "Unknown connection option: '{}'", arg); + log_info (LOG_DEFAULT, "Unknown connection option: '{}'", optional_string (arg)); } } } @@ -275,7 +275,7 @@ Debug::process_connection (int fd) // null-terminate command [cmd_len] = 0; - log_info (LOG_DEFAULT, "Received cmd: '{}'.", command); + log_info (LOG_DEFAULT, "Received cmd: '{}'.", optional_string (command)); if (process_cmd (fd, command)) return true; @@ -487,7 +487,7 @@ Debug::process_cmd (int fd, char *cmd) profiler_fd = fd; profiler_description = Util::monodroid_strdup_printf ("%s,output=#%i", prof, profiler_fd); } else { - log_error (LOG_DEFAULT, "Unknown profiler: '{}'", prof); + log_error (LOG_DEFAULT, "Unknown profiler: '{}'", optional_string (prof)); } /* Notify the main thread (start_profiling ()) */ profiler_configured = true; @@ -496,7 +496,7 @@ Debug::process_cmd (int fd, char *cmd) pthread_mutex_unlock (&process_cmd_mutex); return use_fd; } else { - log_error (LOG_DEFAULT, "Unsupported command: '{}'", cmd); + log_error (LOG_DEFAULT, "Unsupported command: '{}'", optional_string (cmd)); } return false; @@ -526,7 +526,7 @@ Debug::start_debugging (void) // this text is used in unit tests to check the debugger started // do not change it without updating the test. - log_warn (LOG_DEBUGGER, "Trying to initialize the debugger with options: {}", debug_arg); + log_warn (LOG_DEBUGGER, "Trying to initialize the debugger with options: {}", optional_string (debug_arg)); if (enable_soft_breakpoints ()) { constexpr std::string_view soft_breakpoints { "--soft-breakpoints" }; @@ -588,10 +588,10 @@ Debug::enable_soft_breakpoints (void) bool ret; if (strcmp ("0", value) == 0) { ret = false; - log_info (LOG_DEBUGGER, "soft breakpoints disabled ({} property set to {})", SharedConstants::DEBUG_MONO_SOFT_BREAKPOINTS.data (), value); + log_info (LOG_DEBUGGER, "soft breakpoints disabled ({} property set to {})", SharedConstants::DEBUG_MONO_SOFT_BREAKPOINTS.data (), optional_string (value)); } else { ret = true; - log_info (LOG_DEBUGGER, "soft breakpoints enabled ({} property set to {})", SharedConstants::DEBUG_MONO_SOFT_BREAKPOINTS.data (), value); + log_info (LOG_DEBUGGER, "soft breakpoints enabled ({} property set to {})", SharedConstants::DEBUG_MONO_SOFT_BREAKPOINTS.data (), optional_string (value)); } delete[] value; return ret; diff --git a/src/native/monodroid/embedded-assemblies-zip.cc b/src/native/monodroid/embedded-assemblies-zip.cc index 2497cab1c83..453ff56d437 100644 --- a/src/native/monodroid/embedded-assemblies-zip.cc +++ b/src/native/monodroid/embedded-assemblies-zip.cc @@ -22,14 +22,14 @@ EmbeddedAssemblies::zip_load_entry_common (size_t entry_index, std::vector LOG_ASSEMBLY, std::format ( "Assembly store '{}' is not a valid .NET for Android assembly store file", - entry_name.get () + optional_string (entry_name.get ()) ) ); } @@ -232,7 +237,7 @@ EmbeddedAssemblies::map_assembly_store (dynamic_local_string LOG_ASSEMBLY, std::format ( "Assembly store '{}' uses format version {:x}, instead of the expected {:x}", - entry_name.get (), + optional_string (entry_name.get ()), header->version, ASSEMBLY_STORE_FORMAT_VERSION ) @@ -299,9 +304,9 @@ EmbeddedAssemblies::zip_load_assembly_store_entries (std::vector const& log_debug ( LOG_ASSEMBLY, "Found a shared library entry {} (index: {}; name: {}; hash: {:x}; apk offset: {})", - entry_name.get (), + optional_string (entry_name.get ()), number_of_zip_dso_entries, - name, + optional_string (name), apk_entry->name_hash, apk_entry->offset ); @@ -322,7 +327,7 @@ EmbeddedAssemblies::zip_load_entries (int fd, const char *apk_name, [[maybe_unus LOG_ASSEMBLY, std::format ( "Failed to read the EOCD record from APK file %s", - apk_name + optional_string (apk_name) ) ); } @@ -340,7 +345,7 @@ EmbeddedAssemblies::zip_load_entries (int fd, const char *apk_name, [[maybe_unus std::strerror (errno), retval, errno, - apk_name + optional_string (apk_name) ) ); } @@ -371,7 +376,7 @@ EmbeddedAssemblies::zip_load_entries (int fd, const char *apk_name, [[maybe_unus std::strerror (errno), nread, errno, - apk_name + optional_string (apk_name) ) ); } @@ -408,7 +413,9 @@ EmbeddedAssemblies::set_entry_data (XamarinAndroidBundledAssembly &entry, ZipEnt log_debug ( LOG_ASSEMBLY, "Set bundled assembly entry data. file name: '{}'; entry name: '{}'; data size: {}", - entry.file_name, entry.name, entry.data_size + optional_string (entry.file_name), + optional_string (entry.name), + entry.data_size ); } diff --git a/src/native/monodroid/embedded-assemblies.cc b/src/native/monodroid/embedded-assemblies.cc index c868da14469..6adb6f27fe6 100644 --- a/src/native/monodroid/embedded-assemblies.cc +++ b/src/native/monodroid/embedded-assemblies.cc @@ -124,13 +124,13 @@ EmbeddedAssemblies::get_assembly_data (uint8_t *data, uint32_t data_size, [[mayb LOG_ASSEMBLY, std::format ( "Compressed assembly '{}' is larger than when the application was built (expected at most {}, got {}). Assemblies don't grow just like that!", - name, + optional_string (name), cad.uncompressed_file_size, header->uncompressed_length ) ); } else { - log_debug (LOG_ASSEMBLY, "Compressed assembly '{}' is smaller than when the application was built. Adjusting accordingly.", name); + log_debug (LOG_ASSEMBLY, "Compressed assembly '{}' is smaller than when the application was built. Adjusting accordingly.", optional_string (name)); } cad.uncompressed_file_size = header->uncompressed_length; } @@ -143,7 +143,7 @@ EmbeddedAssemblies::get_assembly_data (uint8_t *data, uint32_t data_size, [[mayb LOG_ASSEMBLY, std::format ( "Decompression of assembly {} failed with code {}", - name, + optional_string (name), ret ) ); @@ -154,7 +154,7 @@ EmbeddedAssemblies::get_assembly_data (uint8_t *data, uint32_t data_size, [[mayb LOG_ASSEMBLY, std::format ( "Decompression of assembly {} yielded a different size (expected {}, got {})", - name, + optional_string (name), cad.uncompressed_file_size, static_cast(ret) ) @@ -228,7 +228,7 @@ EmbeddedAssemblies::map_runtime_file (XamarinAndroidBundledAssembly& file) noexc ); if (already_mapped) { - log_debug (LOG_ASSEMBLY, "Assembly {} already mmapped by another thread, unmapping our copy", file.name); + log_debug (LOG_ASSEMBLY, "Assembly {} already mmapped by another thread, unmapping our copy", optional_string (file.name)); munmap (map_info.area, file.data_size); map_info.area = nullptr; } @@ -250,8 +250,8 @@ EmbeddedAssemblies::map_runtime_file (XamarinAndroidBundledAssembly& file) noexc static_cast(file.data), pointer_add (file.data, file.data_size), file.data_size, - file.name, - file.name, + optional_string (file.name), + optional_string (file.name), header.data () ); } @@ -287,7 +287,7 @@ EmbeddedAssemblies::load_bundled_assembly ( if (strcmp (assembly.name, abi_name.get ()) != 0) { return nullptr; } else { - log_debug (LOG_ASSEMBLY, "open_from_bundles: found architecture-specific: '{}'", abi_name.get ()); + log_debug (LOG_ASSEMBLY, "open_from_bundles: found architecture-specific: '{}'", optional_string (abi_name.get ())); } } @@ -321,7 +321,7 @@ EmbeddedAssemblies::load_bundled_assembly ( if (debug_file.data != nullptr) { if (debug_file.data_size > std::numeric_limits::max ()) { - log_warn (LOG_ASSEMBLY, std::format ("Debug info file '{}' is too big for Mono to consume", debug_file.name)); + log_warn (LOG_ASSEMBLY, "Debug info file '{}' is too big for Mono to consume", optional_string (debug_file.name)); } else { mono_debug_open_image_from_memory (image, reinterpret_cast(debug_file.data), static_cast(debug_file.data_size)); } @@ -333,7 +333,7 @@ EmbeddedAssemblies::load_bundled_assembly ( MonoImageOpenStatus status; MonoAssembly *a = mono_assembly_load_from_full (image, name.get (), &status, ref_only); if (a == nullptr || status != MonoImageOpenStatus::MONO_IMAGE_OK) { - log_warn (LOG_ASSEMBLY, std::format ("Failed to load managed assembly '{}'. {}", name.get (), mono_image_strerror (status))); + log_warn (LOG_ASSEMBLY, "Failed to load managed assembly '{}'. {}", optional_string (name.get ()), optional_string (mono_image_strerror (status))); return nullptr; } @@ -348,7 +348,7 @@ EmbeddedAssemblies::individual_assemblies_open_from_bundles (dynamic_local_strin name.append (SharedConstants::DLL_EXTENSION); } - log_debug (LOG_ASSEMBLY, "individual_assemblies_open_from_bundles: looking for bundled name: '{}'", name.get ()); + log_debug (LOG_ASSEMBLY, "individual_assemblies_open_from_bundles: looking for bundled name: '{}'", optional_string (name.get ())); dynamic_local_string abi_name; abi_name @@ -395,11 +395,11 @@ force_inline MonoAssembly* EmbeddedAssemblies::assembly_store_open_from_bundles (dynamic_local_string& name, TLoaderData loader_data, bool ref_only) noexcept { hash_t name_hash = xxhash::hash (name.get (), name.length ()); - log_debug (LOG_ASSEMBLY, "assembly_store_open_from_bundles: looking for bundled name: '{}' (hash {:x})", name.get (), name_hash); + log_debug (LOG_ASSEMBLY, "assembly_store_open_from_bundles: looking for bundled name: '{}' (hash {:x})", optional_string (name.get ()), name_hash); const AssemblyStoreIndexEntry *hash_entry = find_assembly_store_entry (name_hash, assembly_store_hashes, assembly_store.index_entry_count); if (hash_entry == nullptr) { - log_warn (LOG_ASSEMBLY, std::format ("Assembly '{}' (hash {:x}) not found", name.get (), name_hash)); + log_warn (LOG_ASSEMBLY, "Assembly '{}' (hash {:x}) not found", optional_string (name.get ()), name_hash); return nullptr; } @@ -436,7 +436,7 @@ EmbeddedAssemblies::assembly_store_open_from_bundles (dynamic_local_stringdata_size, assembly_runtime_info.descriptor->debug_data_size, assembly_runtime_info.descriptor->config_data_size, - name.get () + optional_string (name.get ()) ); } @@ -446,7 +446,7 @@ EmbeddedAssemblies::assembly_store_open_from_bundles (dynamic_local_string(managed_type_name), nullptr); if (type == nullptr) [[unlikely]] { - log_info (LOG_ASSEMBLY, "typemap: managed type '{}' (mapped from Java type '{}') could not be loaded", managed_type_name, java_type_name.get ()); + log_info (LOG_ASSEMBLY, "typemap: managed type '{}' (mapped from Java type '{}') could not be loaded", optional_string (managed_type_name), java_type_name.get ()); return nullptr; } MonoReflectionType *ret = mono_type_get_object (Util::get_current_domain (), type); if (ret == nullptr) [[unlikely]] { - log_warn (LOG_ASSEMBLY, "typemap: unable to instantiate managed type '{}'", managed_type_name); + log_warn (LOG_ASSEMBLY, "typemap: unable to instantiate managed type '{}'", optional_string (managed_type_name)); return nullptr; } @@ -676,14 +676,14 @@ EmbeddedAssemblies::typemap_java_to_managed (hash_t hash, const MonoString *java module->image = mono_image_loaded (module->assembly_name); if (module->image == nullptr) { - log_debug (LOG_ASSEMBLY, "typemap: assembly '{}' hasn't been loaded yet, attempting a full load", module->assembly_name); + log_debug (LOG_ASSEMBLY, "typemap: assembly '{}' hasn't been loaded yet, attempting a full load", optional_string (module->assembly_name)); // Fake a request from MonoVM to load the assembly. MonoAssemblyName *assembly_name = mono_assembly_name_new (module->assembly_name); MonoAssembly *assm; if (assembly_name == nullptr) { - log_error (LOG_ASSEMBLY, std::format ("typemap: failed to create Mono assembly name for '{}'", module->assembly_name)); + log_error (LOG_ASSEMBLY, "typemap: failed to create Mono assembly name for '{}'", optional_string (module->assembly_name)); assm = nullptr; } else { MonoAssemblyLoadContextGCHandle alc_gchandle = mono_alc_get_default_gchandle (); @@ -692,14 +692,14 @@ EmbeddedAssemblies::typemap_java_to_managed (hash_t hash, const MonoString *java } if (assm == nullptr) { - log_warn (LOG_ASSEMBLY, std::format ("typemap: failed to load managed assembly '{}'", module->assembly_name)); + log_warn (LOG_ASSEMBLY, "typemap: failed to load managed assembly '{}'", optional_string (module->assembly_name)); } else { module->image = mono_assembly_get_image (assm); } } if (module->image == nullptr) { - log_error (LOG_ASSEMBLY, "typemap: unable to load assembly '{}' when looking up managed type corresponding to Java type '{}'", module->assembly_name, to_utf8 (java_type_name).get ()); + log_error (LOG_ASSEMBLY, "typemap: unable to load assembly '{}' when looking up managed type corresponding to Java type '{}'", optional_string (module->assembly_name), to_utf8 (java_type_name).get ()); return nullptr; } } @@ -707,7 +707,13 @@ EmbeddedAssemblies::typemap_java_to_managed (hash_t hash, const MonoString *java log_debug (LOG_ASSEMBLY, "typemap: java type '{}' corresponds to managed token id {} ({:x})", to_utf8 (java_type_name).get (), java_entry->type_token_id, java_entry->type_token_id); MonoClass *klass = mono_class_get (module->image, java_entry->type_token_id); if (klass == nullptr) [[unlikely]] { - log_error (LOG_ASSEMBLY, "typemap: unable to find managed type with token ID {} in assembly '{}', corresponding to Java type '{}'", java_entry->type_token_id, module->assembly_name, to_utf8 (java_type_name).get ()); + log_error ( + LOG_ASSEMBLY, + "typemap: unable to find managed type with token ID {} in assembly '{}', corresponding to Java type '{}'", + java_entry->type_token_id, + optional_string (module->assembly_name), + to_utf8 (java_type_name).get () + ); return nullptr; } @@ -718,7 +724,12 @@ EmbeddedAssemblies::typemap_java_to_managed (hash_t hash, const MonoString *java MonoReflectionType *ret = mono_type_get_object (domain, mono_class_get_type (klass)); if (ret == nullptr) { - log_warn (LOG_ASSEMBLY, "typemap: unable to instantiate managed type with token ID {} in assembly '{}', corresponding to Java type '{}'", java_entry->type_token_id, module->assembly_name, to_utf8 (java_type_name).get ()); + log_warn (LOG_ASSEMBLY, + "typemap: unable to instantiate managed type with token ID {} in assembly '{}', corresponding to Java type '{}'", + java_entry->type_token_id, + optional_string (module->assembly_name), + to_utf8 (java_type_name).get () + ); return nullptr; } @@ -783,7 +794,7 @@ EmbeddedAssemblies::typemap_managed_to_java ([[maybe_unused]] MonoType *type, Mo const TypeMapEntry *entry = typemap_managed_to_java (full_name.get ()); if (entry == nullptr) [[unlikely]] { - log_info (LOG_ASSEMBLY, "typemap: unable to find mapping to a Java type from managed type '{}'", full_name.get ()); + log_info (LOG_ASSEMBLY, "typemap: unable to find mapping to a Java type from managed type '{}'", optional_string (full_name.get ())); return nullptr; } @@ -815,7 +826,7 @@ EmbeddedAssemblies::typemap_managed_to_java ([[maybe_unused]] MonoType *type, Mo const TypeMapModuleEntry *entry = match->map != nullptr ? binary_search (token, match->map, match->entry_count) : nullptr; if (entry == nullptr) { if (match->map == nullptr) { - log_warn (LOG_ASSEMBLY, std::format ("typemap: module with MVID [{}] has no associated type map.", MonoGuidString (mvid).get ())); + log_warn (LOG_ASSEMBLY, "typemap: module with MVID [{}] has no associated type map.", MonoGuidString (mvid).get ()); return nullptr; } @@ -831,13 +842,30 @@ EmbeddedAssemblies::typemap_managed_to_java ([[maybe_unused]] MonoType *type, Mo } if (entry->java_map_index >= java_type_count) [[unlikely]] { - log_warn (LOG_ASSEMBLY, "typemap: type with token {} ({:x}) in module [{}] ({}) has invalid Java type index {}", token, token, MonoGuidString (mvid).get (), match->assembly_name, entry->java_map_index); + log_warn ( + LOG_ASSEMBLY, + "typemap: type with token {} ({:x}) in module [{}] ({}) has invalid Java type index {}", + token, + token, + MonoGuidString (mvid).get (), + optional_string (match->assembly_name), + entry->java_map_index + ); return nullptr; } TypeMapJava const& java_entry = map_java[entry->java_map_index]; if (java_entry.java_name_index >= java_type_count) [[unlikely]] { - log_warn (LOG_ASSEMBLY, "typemap: type with token {} ({:x}) in module [{}] ({}) points to invalid Java type at index {} (invalid type name index {})", token, token, MonoGuidString (mvid).get (), match->assembly_name, entry->java_map_index, java_entry.java_name_index); + log_warn ( + LOG_ASSEMBLY, + "typemap: type with token {} ({:x}) in module [{}] ({}) points to invalid Java type at index {} (invalid type name index {})", + token, + token, + MonoGuidString (mvid).get (), + optional_string (match->assembly_name), + entry->java_map_index, + java_entry.java_name_index + ); return nullptr; } const char *ret = java_type_names[java_entry.java_name_index]; @@ -852,7 +880,7 @@ EmbeddedAssemblies::typemap_managed_to_java ([[maybe_unused]] MonoType *type, Mo token, token, MonoGuidString (mvid).get (), - match->assembly_name, + optional_string (match->assembly_name), ret ); @@ -904,7 +932,7 @@ EmbeddedAssemblies::md_mmap_apk_file (int fd, uint32_t offset, size_t size, cons "Could not mmap APK fd {}: {}; File={}", fd, strerror (errno), - filename + optional_string (filename) ) ); } @@ -923,7 +951,7 @@ EmbeddedAssemblies::md_mmap_apk_file (int fd, uint32_t offset, size_t size, cons pointer_add (file_info.area, file_info.size), file_info.size, fd, - filename + optional_string (filename) ); return file_info; @@ -939,11 +967,11 @@ EmbeddedAssemblies::gather_bundled_assemblies_from_apk (const char* apk, monodro LOG_ASSEMBLY, std::format ( "ERROR: Unable to load application package {}.", - apk + optional_string (apk) ) ); } - log_debug (LOG_ASSEMBLY, "APK {} FD: {}", apk, fd); + log_debug (LOG_ASSEMBLY, "APK {} FD: {}", optional_string (apk), fd); zip_load_entries (fd, apk, should_register); } @@ -970,40 +998,90 @@ EmbeddedAssemblies::typemap_read_header ([[maybe_unused]] int dir_fd, const char struct stat sbuf; int res = fstatat (dir_fd, file_path, &sbuf, 0); if (res < 0) { - log_error (LOG_ASSEMBLY, "typemap: failed to stat {} file '{}/{}': {}", file_type, dir_path, file_path, strerror (errno)); + log_error ( + LOG_ASSEMBLY, + "typemap: failed to stat {} file '{}/{}': {}", + optional_string (file_type), + optional_string (dir_path), + optional_string (file_path), + strerror (errno) + ); return false; } file_size = static_cast(sbuf.st_size); if (file_size < sizeof (header)) { - log_error (LOG_ASSEMBLY, "typemap: {} file '{}/{}' is too small (must be at least {} bytes)", file_type, dir_path, file_path, sizeof (header)); + log_error ( + LOG_ASSEMBLY, + "typemap: {} file '{}/{}' is too small (must be at least {} bytes)", + optional_string (file_type), + optional_string (dir_path), + optional_string (file_path), + sizeof (header) + ); return false; } fd = openat (dir_fd, file_path, O_RDONLY); if (fd < 0) { - log_error (LOG_ASSEMBLY, "typemap: failed to open {} file {}/{} for reading: {}", file_type, dir_path, file_path, strerror (errno)); + log_error ( + LOG_ASSEMBLY, + "typemap: failed to open {} file {}/{} for reading: {}", + optional_string (file_type), + optional_string (dir_path), + optional_string (file_path), + strerror (errno) + ); return false; } ssize_t nread = do_read (fd, &header, sizeof (header)); if (nread <= 0) { if (nread < 0) { - log_error (LOG_ASSEMBLY, "typemap: failed to read {} file header from '{}/{}': {}", file_type, dir_path, file_path, strerror (errno)); + log_error ( + LOG_ASSEMBLY, + "typemap: failed to read {} file header from '{}/{}': {}", + optional_string (file_type), + optional_string (dir_path), + optional_string (file_path), + strerror (errno) + ); } else { - log_error (LOG_ASSEMBLY, "typemap: end of file while reading {} file header from '{}/{}'", file_type, dir_path, file_path); + log_error ( + LOG_ASSEMBLY, + "typemap: end of file while reading {} file header from '{}/{}'", + optional_string (file_type), + optional_string (dir_path), + optional_string (file_path) + ); } return false; } if (header.magic != expected_magic) { - log_error (LOG_ASSEMBLY, "typemap: invalid magic value in the {} file header from '{}/{}': expected {:x}, got {:x}", file_type, dir_path, file_path, expected_magic, header.magic); + log_error ( + LOG_ASSEMBLY, + "typemap: invalid magic value in the {} file header from '{}/{}': expected {:x}, got {:x}", + optional_string (file_type), + optional_string (dir_path), + optional_string (file_path), + expected_magic, + header.magic + ); return false; } if (header.version != MODULE_FORMAT_VERSION) { - log_error (LOG_ASSEMBLY, "typemap: incompatible {} format version. This build supports only version {}, file '{}/{}' uses version {}", file_type, MODULE_FORMAT_VERSION, dir_path, file_path, header.version); + log_error ( + LOG_ASSEMBLY, + "typemap: incompatible {} format version. This build supports only version {}, file '{}/{}' uses version {}", + optional_string (file_type), + MODULE_FORMAT_VERSION, + optional_string (dir_path), + optional_string (file_path), + header.version + ); return false; } @@ -1039,7 +1117,7 @@ EmbeddedAssemblies::typemap_load_index (TypeMapIndexHeader &header, size_t file_ std::unique_ptr EmbeddedAssemblies::typemap_load_index (int dir_fd, const char *dir_path, const char *index_path) { - log_debug (LOG_ASSEMBLY, "typemap: loading TypeMap index file '{}/{}'", dir_path, index_path); + log_debug (LOG_ASSEMBLY, "typemap: loading TypeMap index file '{}/{}'", optional_string (dir_path), optional_string (index_path)); TypeMapIndexHeader header; size_t file_size; @@ -1066,7 +1144,13 @@ EmbeddedAssemblies::typemap_load_file (BinaryTypeMapHeader &header, const char * ssize_t nread = do_read (file_fd, module.assembly_name, header.assembly_name_length); if (nread != static_cast(header.assembly_name_length)) { - log_error (LOG_ASSEMBLY, "typemap: failed to read map assembly name from '{}/{}': {}", dir_path, file_path, strerror (errno)); + log_error ( + LOG_ASSEMBLY, + "typemap: failed to read map assembly name from '{}/{}': {}", + optional_string (dir_path), + optional_string (file_path), + strerror (errno) + ); return false; } @@ -1076,13 +1160,13 @@ EmbeddedAssemblies::typemap_load_file (BinaryTypeMapHeader &header, const char * log_debug ( LOG_ASSEMBLY, "typemap: '{}/{}':: entry count == {}; Java name field width == {}; Managed name width == {}; assembly name length == {}; assembly name == {}", - dir_path, - file_path, + optional_string (dir_path), + optional_string (file_path), header.entry_count, header.java_name_width, header.managed_name_width, header.assembly_name_length, - module.assembly_name + optional_string (module.assembly_name) ); // [name][index] @@ -1096,7 +1180,7 @@ EmbeddedAssemblies::typemap_load_file (BinaryTypeMapHeader &header, const char * module.data = new uint8_t [data_size]; nread = do_read (file_fd, module.data, data_size); if (nread != static_cast(data_size)) { - log_error (LOG_ASSEMBLY, "typemap: failed to read map data from '{}/{}': {}", dir_path, file_path, strerror (errno)); + log_error (LOG_ASSEMBLY, "typemap: failed to read map data from '{}/{}': {}", optional_string (dir_path), optional_string (file_path), strerror (errno)); return false; } @@ -1140,7 +1224,7 @@ EmbeddedAssemblies::typemap_load_file (BinaryTypeMapHeader &header, const char * bool EmbeddedAssemblies::typemap_load_file (int dir_fd, const char *dir_path, const char *file_path, TypeMap &module) { - log_debug (LOG_ASSEMBLY, "typemap: loading TypeMap file '{}/{}'", dir_path, file_path); + log_debug (LOG_ASSEMBLY, "typemap: loading TypeMap file '{}/{}'", optional_string (dir_path), optional_string (file_path)); bool ret = true; BinaryTypeMapHeader header; @@ -1179,7 +1263,7 @@ EmbeddedAssemblies::register_from_apk (const char *apk_file, monodroid_should_re gather_bundled_assemblies_from_apk (apk_file, should_register); - log_info (LOG_ASSEMBLY, "Package '{}' contains {} assemblies", apk_file, number_of_found_assemblies - prev); + log_info (LOG_ASSEMBLY, "Package '{}' contains {} assemblies", optional_string (apk_file), number_of_found_assemblies - prev); return number_of_found_assemblies; } @@ -1283,10 +1367,10 @@ EmbeddedAssemblies::maybe_register_blob_from_filesystem ( force_inline size_t EmbeddedAssemblies::register_from_filesystem (const char *lib_dir_path,bool look_for_mangled_names, monodroid_should_register should_register) noexcept { - log_debug (LOG_ASSEMBLY, "Looking for assemblies in '{}'", lib_dir_path); + log_debug (LOG_ASSEMBLY, "Looking for assemblies in '{}'", optional_string (lib_dir_path)); DIR *lib_dir = opendir (lib_dir_path); // TODO: put it in a scope guard at some point if (lib_dir == nullptr) { - log_warn (LOG_ASSEMBLY, "Unable to open app library directory '{}': {}", lib_dir_path, std::strerror (errno)); + log_warn (LOG_ASSEMBLY, "Unable to open app library directory '{}': {}", optional_string (lib_dir_path), std::strerror (errno)); return 0; } @@ -1295,14 +1379,14 @@ EmbeddedAssemblies::register_from_filesystem (const char *lib_dir_path,bool look int dir_fd = dirfd (lib_dir); if (dir_fd < 0) [[unlikely]] { - log_warn (LOG_ASSEMBLY, "Unable to obtain file descriptor for directory '{}': {}", lib_dir_path, std::strerror (errno)); + log_warn (LOG_ASSEMBLY, "Unable to obtain file descriptor for directory '{}': {}", optional_string (lib_dir_path), std::strerror (errno)); closedir (lib_dir); return 0; } state.file_fd = dup (dir_fd); if (state.file_fd < 0) [[unlikely]] { - log_warn (LOG_ASSEMBLY, "Unable to duplicate file descriptor {} for directory '{}': {}", dir_fd, lib_dir_path, std::strerror (errno)); + log_warn (LOG_ASSEMBLY, "Unable to duplicate file descriptor {} for directory '{}': {}", dir_fd, optional_string (lib_dir_path), std::strerror (errno)); closedir (lib_dir); return 0; } @@ -1319,7 +1403,7 @@ EmbeddedAssemblies::register_from_filesystem (const char *lib_dir_path,bool look dirent *cur = readdir (lib_dir); if (cur == nullptr) { if (errno != 0) { - log_warn (LOG_ASSEMBLY, "Failed to open a directory entry from '{}': {}", lib_dir_path, std::strerror (errno)); + log_warn (LOG_ASSEMBLY, "Failed to open a directory entry from '{}': {}", optional_string (lib_dir_path), std::strerror (errno)); continue; // keep going, no harm } break; // No more entries, we're done @@ -1339,7 +1423,7 @@ EmbeddedAssemblies::register_from_filesystem (const char *lib_dir_path,bool look // ...and we can handle the runtime config entry if (!runtime_config_blob_found && std::strncmp (cur->d_name, SharedConstants::RUNTIME_CONFIG_BLOB_NAME.data (), SharedConstants::RUNTIME_CONFIG_BLOB_NAME.size ()) == 0) { - log_debug (LOG_ASSEMBLY, "Mapping runtime config blob from '{}'", cur->d_name); + log_debug (LOG_ASSEMBLY, "Mapping runtime config blob from '{}'", optional_string (cur->d_name)); auto file_size = Util::get_file_size_at (state.file_fd, cur->d_name); if (!file_size) { continue; diff --git a/src/native/monodroid/embedded-assemblies.hh b/src/native/monodroid/embedded-assemblies.hh index c17d957b4c2..341ecc2a086 100644 --- a/src/native/monodroid/embedded-assemblies.hh +++ b/src/native/monodroid/embedded-assemblies.hh @@ -310,7 +310,7 @@ namespace xamarin::android::internal { elf_header->e_ident[EI_MAG1] != ELFMAG1 || elf_header->e_ident[EI_MAG2] != ELFMAG2 || elf_header->e_ident[EI_MAG3] != ELFMAG3) { - log_debug (LOG_ASSEMBLY, "Not an ELF image: {}", file_name); + log_debug (LOG_ASSEMBLY, "Not an ELF image: {}", optional_string (file_name)); // Not an ELF image, just return what we mmapped before return { map_info.area, map_info.size }; } @@ -357,6 +357,11 @@ namespace xamarin::android::internal { force_inline static c_unique_ptr to_utf8 (const MonoString *s) noexcept { + if (s == nullptr) [[unlikely]] { + // We need to duplicate mono_string_to_utf8 behavior + return c_unique_ptr (strdup ("")); + } + return c_unique_ptr (mono_string_to_utf8 (const_cast(s))); } @@ -431,7 +436,7 @@ namespace xamarin::android::internal { } } } - log_debug (LOG_ASSEMBLY, "Unmangled name to '{}'", name.get ()); + log_debug (LOG_ASSEMBLY, "Unmangled name to '{}'", optional_string (name.get ())); }; private: diff --git a/src/native/monodroid/mono-image-loader.hh b/src/native/monodroid/mono-image-loader.hh index d843bf32188..48812d223b2 100644 --- a/src/native/monodroid/mono-image-loader.hh +++ b/src/native/monodroid/mono-image-loader.hh @@ -110,7 +110,7 @@ namespace xamarin::android::internal { force_inline static MonoImage* stash_and_return (MonoImage *image, MonoImageOpenStatus status, [[maybe_unused]] hash_t hash) noexcept { if (image == nullptr || status != MonoImageOpenStatus::MONO_IMAGE_OK) { - log_warn (LOG_ASSEMBLY, std::format ("Failed to open assembly image. {}", mono_image_strerror (status))); + log_warn (LOG_ASSEMBLY, "Failed to open assembly image. {}", optional_string (mono_image_strerror (status))); return nullptr; } diff --git a/src/native/monodroid/monodroid-glue.cc b/src/native/monodroid/monodroid-glue.cc index 49e614a4455..7a28622554f 100644 --- a/src/native/monodroid/monodroid-glue.cc +++ b/src/native/monodroid/monodroid-glue.cc @@ -174,12 +174,12 @@ MonodroidRuntime::open_from_update_dir (MonoAssemblyName *aname, [[maybe_unused] fullpath.append (SharedConstants::DLL_EXTENSION); } - log_debug (LOG_ASSEMBLY, "open_from_update_dir: trying to open assembly: {}", fullpath.get ()); + log_debug (LOG_ASSEMBLY, "open_from_update_dir: trying to open assembly: {}", optional_string (fullpath.get ())); if (Util::file_exists (fullpath.get ())) { MonoImageOpenStatus status{}; result = mono_assembly_open_full (fullpath.get (), &status, 0); if (result == nullptr || status != MonoImageOpenStatus::MONO_IMAGE_OK) { - log_warn (LOG_ASSEMBLY, "Failed to load managed assembly '{}'. {}", fullpath.get (), mono_image_strerror (status)); + log_warn (LOG_ASSEMBLY, "Failed to load managed assembly '{}'. {}", optional_string (fullpath.get ()), mono_image_strerror (status)); } } else { log_warn (LOG_ASSEMBLY, "open_from_update_dir: assembly file DOES NOT EXIST"sv); @@ -480,7 +480,7 @@ MonodroidRuntime::parse_runtime_args (dynamic_local_string arg (token); - log_error (LOG_DEFAULT, "Unknown runtime argument: '{}'", arg.get ()); + log_error (LOG_DEFAULT, "Unknown runtime argument: '{}'", optional_string (arg.get ())); ret = false; } } @@ -509,7 +509,7 @@ MonodroidRuntime::mono_runtime_init ([[maybe_unused]] JNIEnv *env, [[maybe_unuse cur_time = time (nullptr); if (!parse_runtime_args (runtime_args, &options)) { - log_error (LOG_DEFAULT, "Failed to parse runtime args: '{}'", runtime_args.get ()); + log_error (LOG_DEFAULT, "Failed to parse runtime args: '{}'", optional_string (runtime_args.get ())); } else if (options.debug && cur_time > options.timeout_time) { log_warn (LOG_DEBUGGER, "Not starting the debugger as the timeout value has been reached; current-time: {}; timeout: {}", cur_time, options.timeout_time); } else if (options.debug && cur_time <= options.timeout_time) { @@ -537,7 +537,7 @@ MonodroidRuntime::mono_runtime_init ([[maybe_unused]] JNIEnv *env, [[maybe_unuse // this text is used in unit tests to check the debugger started // do not change it without updating the test. - log_warn (LOG_DEBUGGER, "Trying to initialize the debugger with options: {}", debug_arg); + log_warn (LOG_DEBUGGER, "Trying to initialize the debugger with options: {}", optional_string (debug_arg)); if (options.out_port > 0) { int sock = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP); @@ -576,7 +576,7 @@ MonodroidRuntime::mono_runtime_init ([[maybe_unused]] JNIEnv *env, [[maybe_unuse LOG_DEBUGGER, std::format ( "Error accepting stdout and stderr ({}:{}): {}", - options.host, + optional_string (options.host), options.out_port, strerror (errno) ) @@ -591,7 +591,7 @@ MonodroidRuntime::mono_runtime_init ([[maybe_unused]] JNIEnv *env, [[maybe_unuse LOG_DEBUGGER, std::format ( "Error connecting stdout and stderr ({}:{}): {}", - options.host, + optional_string (options.host), options.out_port, strerror (errno) ) @@ -662,7 +662,7 @@ MonodroidRuntime::mono_runtime_init ([[maybe_unused]] JNIEnv *env, [[maybe_unuse if (AndroidSystem::monodroid_get_system_property (SharedConstants::DEBUG_MONO_RUNTIME_ARGS_PROPERTY, prop_val) > 0) { char **ptr; - log_warn (LOG_DEBUGGER, "passing '{}' as extra arguments to the runtime.", prop_val.get ()); + log_warn (LOG_DEBUGGER, "passing '{}' as extra arguments to the runtime.", optional_string (prop_val.get ())); char **args = Util::monodroid_strsplit (prop_val.get (), " ", 0); int argc = 0; @@ -731,8 +731,8 @@ MonodroidRuntime::create_domain (JNIEnv *env, jstring_array_wrapper &runtimeApks #if defined (DEBUG) log_fatal (LOG_DEFAULT, "No assemblies found in '{}' or '{}'. Assuming this is part of Fast Deployment. Exiting...", - AndroidSystem::override_dirs [0], - (AndroidSystem::override_dirs.size () > 1 && AndroidSystem::override_dirs [1] != nullptr) ? AndroidSystem::override_dirs [1] : ""sv + optional_string (AndroidSystem::override_dirs [0]), + (AndroidSystem::override_dirs.size () > 1 && AndroidSystem::override_dirs [1] != nullptr) ? optional_string (AndroidSystem::override_dirs [1]) : "" ); #else log_fatal (LOG_DEFAULT, "No assemblies (or assembly blobs) were found in the application APK file(s) or on the filesystem"sv); @@ -741,7 +741,7 @@ MonodroidRuntime::create_domain (JNIEnv *env, jstring_array_wrapper &runtimeApks Helpers::abort_application ( std::format ( "ALL entries in APK named `{}` MUST be STORED. Gradle's minification may COMPRESS such entries.", - assemblies_prefix + optional_string (assemblies_prefix) ) ); } @@ -942,7 +942,7 @@ MonodroidRuntime::init_android_runtime (JNIEnv *env, jclass runtimeClass, jobjec auto initialize = reinterpret_cast (mono_method_get_unmanaged_callers_only_ftnptr (method, &error)); if (initialize == nullptr) { - log_fatal (LOG_DEFAULT, "Failed to get pointer to Initialize. Mono error: {}", mono_error_get_message (&error)); + log_fatal (LOG_DEFAULT, "Failed to get pointer to Initialize. Mono error: {}", optional_string (mono_error_get_message (&error))); } abort_unless ( @@ -998,7 +998,7 @@ MonodroidRuntime::set_environment_variable_for_directory (const char *name, jstr if (createDirectory) { int rv = Util::create_directory (value.get_cstr (), mode); if (rv < 0 && errno != EEXIST) - log_warn (LOG_DEFAULT, "Failed to create directory for environment variable {}. {}", name, strerror (errno)); + log_warn (LOG_DEFAULT, "Failed to create directory for environment variable {}. {}", optional_string (name), strerror (errno)); } setenv (name, value.get_cstr (), 1); } @@ -1008,10 +1008,10 @@ MonodroidRuntime::create_xdg_directory (jstring_wrapper& home, size_t home_len, { static_local_string dir (home_len + relative_path.length ()); Util::path_combine (dir, home.get_cstr (), home_len, relative_path.data (), relative_path.length ()); - log_debug (LOG_DEFAULT, "Creating XDG directory: {}", dir.get ()); + log_debug (LOG_DEFAULT, "Creating XDG directory: {}", optional_string (dir.get ())); int rv = Util::create_directory (dir.get (), DEFAULT_DIRECTORY_MODE); if (rv < 0 && errno != EEXIST) - log_warn (LOG_DEFAULT, "Failed to create XDG directory {}. {}", dir.get (), strerror (errno)); + log_warn (LOG_DEFAULT, "Failed to create XDG directory {}. {}", optional_string (dir.get ()), strerror (errno)); if (!environment_variable_name.empty ()) { setenv (environment_variable_name.data (), dir.get (), 1); } @@ -1040,7 +1040,7 @@ MonodroidRuntime::set_debug_env_vars (void) noexcept return; auto log_envvar = [](const char *name, const char *v) { - log_debug (LOG_DEFAULT, "Env variable '{}' set to '{}'.", name, v); + log_debug (LOG_DEFAULT, "Env variable '{}' set to '{}'.", optional_string (name), optional_string (v)); }; string_segment arg_token; @@ -1060,7 +1060,7 @@ MonodroidRuntime::set_debug_env_vars (void) noexcept log_envvar (arg.get (), one.data ()); } else if (index == 0) { // ’=value’ - log_warn (LOG_DEFAULT, "Attempt to set environment variable without specifying name: '{}'", arg.get ()); + log_warn (LOG_DEFAULT, "Attempt to set environment variable without specifying name: '{}'", optional_string (arg.get ())); } else { // ’name=value’ arg[index] = '\0'; @@ -1140,10 +1140,10 @@ MonodroidRuntime::set_profile_options () noexcept .append (output_path.get (), output_path.length ()); } if (Util::create_directory (AndroidSystem::override_dirs[0], 0) < 0) { - log_warn (LOG_DEFAULT, "Failed to create directory '{}'. {}", AndroidSystem::override_dirs[0], std::strerror (errno)); + log_warn (LOG_DEFAULT, "Failed to create directory '{}'. {}", optional_string (AndroidSystem::override_dirs[0]), std::strerror (errno)); } - log_warn (LOG_DEFAULT, "Initializing profiler with options: {}", value.get ()); + log_warn (LOG_DEFAULT, "Initializing profiler with options: {}", optional_string (value.get ())); debug.monodroid_profiler_load (AndroidSystem::get_runtime_libdir (), value.get (), output_path.get ()); } @@ -1468,7 +1468,7 @@ MonodroidRuntime::Java_mono_android_Runtime_initInternal (JNIEnv *env, jclass kl if (runtimeNativeLibDir != nullptr) { jstr = runtimeNativeLibDir; AndroidSystem::set_runtime_libdir (strdup (jstr.get_cstr ())); - log_debug (LOG_DEFAULT, "Using runtime path: {}", AndroidSystem::get_runtime_libdir ()); + log_debug (LOG_DEFAULT, "Using runtime path: {}", optional_string (AndroidSystem::get_runtime_libdir ())); } AndroidSystem::setup_process_args (runtimeApks); diff --git a/src/native/monodroid/osbridge.cc b/src/native/monodroid/osbridge.cc index e909ab51ec2..4d03b3600bb 100644 --- a/src/native/monodroid/osbridge.cc +++ b/src/native/monodroid/osbridge.cc @@ -188,10 +188,10 @@ OSBridge::_write_stack_trace (FILE *to, char *from, LogCategories category) *end = '\0'; if ((category == LOG_GREF && gref_to_logcat) || (category == LOG_LREF && lref_to_logcat)) { - log_debug (category, "{}", m); + log_debug (category, "{}", optional_string (m)); } if (to != nullptr) { - fprintf (to, "%s\n", m); + fprintf (to, "%s\n", optional_string (m)); fflush (to); } *end = c; @@ -202,11 +202,11 @@ void OSBridge::_monodroid_gref_log (const char *message) { if (gref_to_logcat) { - log_debug (LOG_GREF, "{}", message); + log_debug (LOG_GREF, "{}", optional_string (message)); } if (!gref_log) return; - fprintf (gref_log, "%s", message); + fprintf (gref_log, "%s", optional_string (message)); fflush (gref_log); } @@ -216,6 +216,7 @@ OSBridge::_monodroid_gref_log_new (jobject curHandle, char curType, jobject newH int c = _monodroid_gref_inc (); if ((log_categories & LOG_GREF) == 0) return c; + log_info (LOG_GREF, "+g+ grefc {} gwrefc {} obj-handle {:p}/{} -> new-handle {:p}/{} from thread '{}'({})", c, @@ -224,14 +225,14 @@ OSBridge::_monodroid_gref_log_new (jobject curHandle, char curType, jobject newH curType, reinterpret_cast(newHandle), newType, - threadName, + optional_string (threadName), threadId ); if (gref_to_logcat) { if (from_writable) { _write_stack_trace (nullptr, const_cast(from), LOG_GREF); } else { - log_info (LOG_GREF, "{}", from); + log_info (LOG_GREF, "{}", optional_string (from)); } } if (!gref_log) @@ -243,7 +244,7 @@ OSBridge::_monodroid_gref_log_new (jobject curHandle, char curType, jobject newH curType, newHandle, newType, - threadName, + optional_string (threadName), threadId); if (from_writable) _write_stack_trace (gref_log, const_cast(from)); @@ -267,14 +268,14 @@ OSBridge::_monodroid_gref_log_delete (jobject handle, char type, const char *thr gc_weak_gref_count, reinterpret_cast(handle), type, - threadName, + optional_string (threadName), threadId ); if (gref_to_logcat) { if (from_writable) { _write_stack_trace (nullptr, const_cast(from), LOG_GREF); } else { - log_info (LOG_GREF, "{}", from); + log_info (LOG_GREF, "{}", optional_string (from)); } } if (!gref_log) @@ -284,12 +285,12 @@ OSBridge::_monodroid_gref_log_delete (jobject handle, char type, const char *thr gc_weak_gref_count, handle, type, - threadName, + optional_string (threadName), threadId); if (from_writable) _write_stack_trace (gref_log, const_cast(from)); else - fprintf (gref_log, "%s\n", from); + fprintf (gref_log, "%s\n", optional_string (from)); fflush (gref_log); } @@ -308,14 +309,14 @@ OSBridge::_monodroid_weak_gref_new (jobject curHandle, char curType, jobject new curType, reinterpret_cast(newHandle), newType, - threadName, + optional_string (threadName), threadId ); if (gref_to_logcat) { if (from_writable) { _write_stack_trace (nullptr, const_cast(from), LOG_GREF); } else { - log_info (LOG_GREF, "{}", from); + log_info (LOG_GREF, "{}", optional_string (from)); } } if (!gref_log) @@ -327,12 +328,12 @@ OSBridge::_monodroid_weak_gref_new (jobject curHandle, char curType, jobject new curType, newHandle, newType, - threadName, + optional_string (threadName), threadId); if (from_writable) _write_stack_trace (gref_log, const_cast(from)); else - fprintf (gref_log, "%s\n", from); + fprintf (gref_log, "%s\n", optional_string (from)); fflush (gref_log); } @@ -349,14 +350,14 @@ OSBridge::_monodroid_weak_gref_delete (jobject handle, char type, const char *th gc_weak_gref_count, reinterpret_cast(handle), type, - threadName, + optional_string (threadName), threadId ); if (gref_to_logcat) { if (from_writable) { _write_stack_trace (nullptr, const_cast(from), LOG_GREF); } else { - log_info (LOG_GREF, "{}", from); + log_info (LOG_GREF, "{}", optional_string (from)); } } if (!gref_log) @@ -366,12 +367,12 @@ OSBridge::_monodroid_weak_gref_delete (jobject handle, char type, const char *th gc_weak_gref_count, handle, type, - threadName, + optional_string (threadName), threadId); if (from_writable) _write_stack_trace (gref_log, const_cast(from)); else - fprintf (gref_log, "%s\n", from); + fprintf (gref_log, "%s\n", optional_string (from)); fflush (gref_log); } @@ -386,14 +387,14 @@ OSBridge::_monodroid_lref_log_new (int lrefc, jobject handle, char type, const c lrefc, reinterpret_cast(handle), type, - threadName, + optional_string (threadName), threadId ); if (lref_to_logcat) { if (from_writable) { _write_stack_trace (nullptr, const_cast(from), LOG_GREF); } else { - log_info (LOG_GREF, "{}", from); + log_info (LOG_GREF, "{}", optional_string (from)); } } if (!lref_log) @@ -402,12 +403,12 @@ OSBridge::_monodroid_lref_log_new (int lrefc, jobject handle, char type, const c lrefc, handle, type, - threadName, + optional_string (threadName), threadId); if (from_writable) _write_stack_trace (lref_log, const_cast(from)); else - fprintf (lref_log, "%s\n", from); + fprintf (lref_log, "%s\n", optional_string (from)); fflush (lref_log); } @@ -422,14 +423,14 @@ OSBridge::_monodroid_lref_log_delete (int lrefc, jobject handle, char type, cons lrefc, reinterpret_cast(handle), type, - threadName, + optional_string (threadName), threadId ); if (lref_to_logcat) { if (from_writable) { _write_stack_trace (nullptr, const_cast(from), LOG_GREF); } else { - log_info (LOG_GREF, "{}", from); + log_info (LOG_GREF, "{}", optional_string (from)); } } if (!lref_log) @@ -438,12 +439,12 @@ OSBridge::_monodroid_lref_log_delete (int lrefc, jobject handle, char type, cons lrefc, handle, type, - threadName, + optional_string (threadName), threadId); if (from_writable) _write_stack_trace (lref_log, const_cast(from)); else - fprintf (lref_log, "%s\n", from); + fprintf (lref_log, "%s\n", optional_string (from)); fflush (lref_log); } @@ -543,8 +544,8 @@ OSBridge::gc_bridge_class_kind (MonoClass *klass) if (i == static_cast (-NUM_GC_BRIDGE_TYPES)) { log_info (LOG_GC, "asked if a class {}.{} is a bridge before we inited java.lang.Object", - mono_class_get_namespace (klass), - mono_class_get_name (klass) + optional_string (mono_class_get_namespace (klass)), + optional_string (mono_class_get_name (klass)) ); return MonoGCBridgeObjectKind::GC_BRIDGE_TRANSPARENT_CLASS; } @@ -571,8 +572,8 @@ OSBridge::gc_is_bridge_object (MonoObject *object) MonoClass *mclass = mono_object_get_class (object); log_info (LOG_GC, "object of class {}.{} with null handle", - mono_class_get_namespace (mclass), - mono_class_get_name (mclass) + optional_string (mono_class_get_namespace (mclass)), + optional_string (mono_class_get_name (mclass)) ); #endif return 0; @@ -659,9 +660,9 @@ OSBridge::add_reference (JNIEnv *env, OSBridge::AddReferenceTarget target, OSBri *reffed_description = describe_target (reffed_target); if (success) - log_warn (LOG_GC, "Added reference for {} to {}", description, reffed_description); + log_warn (LOG_GC, "Added reference for {} to {}", optional_string (description), optional_string (reffed_description)); else - log_error (LOG_GC, "Missing monodroidAddReference method for {}", description); + log_error (LOG_GC, "Missing monodroidAddReference method for {}", optional_string (description)); free (description); free (reffed_description); @@ -899,8 +900,8 @@ OSBridge::gc_cleanup_after_java_collection (JNIEnv *env, int num_sccs, MonoGCBri klass = mono_object_get_class (obj); log_error (LOG_GC, "Missing monodroidClearReferences method for object of class {}.{}", - mono_class_get_namespace (klass), - mono_class_get_name (klass) + optional_string (mono_class_get_namespace (klass)), + optional_string (mono_class_get_name (klass)) ); } #endif @@ -965,8 +966,8 @@ OSBridge::gc_cross_references (int num_sccs, MonoGCBridgeSCC **sccs, int num_xre log_info (LOG_GC, "\tobj {:p} [{}::{}] handle {:p} key_handle {:p}", reinterpret_cast(obj), - mono_class_get_namespace (klass), - mono_class_get_name (klass), + optional_string (mono_class_get_namespace (klass)), + optional_string (mono_class_get_name (klass)), reinterpret_cast(handle), key_handle ); diff --git a/src/native/monodroid/xamarin-android-app-context.cc b/src/native/monodroid/xamarin-android-app-context.cc index 75973eb020e..9ef193ddeb7 100644 --- a/src/native/monodroid/xamarin-android-app-context.cc +++ b/src/native/monodroid/xamarin-android-app-context.cc @@ -44,8 +44,8 @@ MonodroidRuntime::get_function_pointer (uint32_t mono_image_index, uint32_t clas log_debug ( LOG_ASSEMBLY, "MM: Trying to look up pointer to method '{}' (token {:x}) in class '{}' (index {})", - get_method_name (mono_image_index, method_token), method_token, - get_class_name (class_index), class_index + optional_string (get_method_name (mono_image_index, method_token)), method_token, + optional_string (get_class_name (class_index)), class_index ); if (class_index >= marshal_methods_number_of_classes) [[unlikely]] { @@ -81,7 +81,7 @@ MonodroidRuntime::get_function_pointer (uint32_t mono_image_index, uint32_t clas log_debug ( LOG_ASSEMBLY, "Loaded pointer to method {} ({:p}) (mono_image_index == {}; class_index == {}; method_token == {:x})", - mono_method_full_name (method, true), + optional_string (mono_method_full_name (method, true)), ret, mono_image_index, class_index, @@ -93,8 +93,8 @@ MonodroidRuntime::get_function_pointer (uint32_t mono_image_index, uint32_t clas log_fatal ( LOG_DEFAULT, "Failed to obtain function pointer to method '{}' in class '{}'", - get_method_name (mono_image_index, method_token), - get_class_name (class_index) + optional_string (get_method_name (mono_image_index, method_token)), + optional_string (get_class_name (class_index)) ); log_fatal ( diff --git a/src/native/monodroid/xamarin_getifaddrs.cc b/src/native/monodroid/xamarin_getifaddrs.cc index 57c4935a7bf..23848f9910b 100644 --- a/src/native/monodroid/xamarin_getifaddrs.cc +++ b/src/native/monodroid/xamarin_getifaddrs.cc @@ -962,7 +962,7 @@ get_link_address (const struct nlmsghdr *message, struct _monodroid_ifaddrs **if log_debug (LOG_NETLINK, " address has no name/label, getting one from interface"sv); ifa->ifa_name = name ? strdup (name) : NULL; } - log_debug (LOG_NETLINK, " address label: {}", ifa->ifa_name); + log_debug (LOG_NETLINK, " address label: {}", optional_string (ifa->ifa_name)); if (calculate_address_netmask (ifa, net_address) < 0) { goto error; @@ -1017,7 +1017,7 @@ get_link_info (const struct nlmsghdr *message) } if (Util::should_log (LOG_NETLINK)) { log_debug_nocheck_fmt (LOG_NETLINK, " interface name (payload length: {}; string length: {})", RTA_PAYLOAD (attribute), strlen (ifa->ifa_name)); - log_debug_nocheck_fmt (LOG_NETLINK, " {}", ifa->ifa_name); + log_debug_nocheck_fmt (LOG_NETLINK, " {}", optional_string (ifa->ifa_name)); } break; @@ -1150,7 +1150,7 @@ print_ifla_name (int id) i++; continue; } - log_info_nocheck_fmt (LOG_NETLINK, "ifla->name: {} ({})", iflas [i].name, iflas [i].value); + log_info_nocheck_fmt (LOG_NETLINK, "ifla->name: {} ({})", optional_string (iflas [i].name), iflas [i].value); break; } } @@ -1180,7 +1180,7 @@ print_address_list (const char title[], struct _monodroid_ifaddrs *list) cur = cur->ifa_next; } - log_info_nocheck_fmt (LOG_NETLINK, "{}: {}", title, msg ? msg : "[no addresses]"sv); + log_info_nocheck_fmt (LOG_NETLINK, "{}: {}", title, optional_string (msg, "[no addresses]")); free (msg); } #endif diff --git a/src/native/pinvoke-override/pinvoke-override-api-impl.hh b/src/native/pinvoke-override/pinvoke-override-api-impl.hh index f6c402c46e7..259a0d5c879 100644 --- a/src/native/pinvoke-override/pinvoke-override-api-impl.hh +++ b/src/native/pinvoke-override/pinvoke-override-api-impl.hh @@ -23,21 +23,21 @@ namespace xamarin::android { constexpr bool PREFER_AOT_CACHE = false; lib_handle = internal::MonodroidDl::monodroid_dlopen (library_name, MONO_DL_LOCAL, nullptr, PREFER_AOT_CACHE); if (lib_handle == nullptr) { - log_warn (LOG_ASSEMBLY, "Shared library '{}' not loaded, p/invoke '{}' may fail", library_name, symbol_name); + log_warn (LOG_ASSEMBLY, "Shared library '{}' not loaded, p/invoke '{}' may fail", optional_string (library_name), optional_string (symbol_name)); return nullptr; } if (dso_handle != nullptr) { void *expected_null = nullptr; if (!__atomic_compare_exchange (dso_handle, &expected_null, &lib_handle, false /* weak */, __ATOMIC_ACQUIRE /* success_memorder */, __ATOMIC_RELAXED /* xxxfailure_memorder */)) { - log_debug (LOG_ASSEMBLY, "Library '{}' handle already cached by another thread", library_name); + log_debug (LOG_ASSEMBLY, "Library '{}' handle already cached by another thread", optional_string (library_name)); } } } void *entry_handle = internal::MonodroidDl::monodroid_dlsym (lib_handle, symbol_name, nullptr, nullptr); if (entry_handle == nullptr) { - log_warn (LOG_ASSEMBLY, "Symbol '{}' not found in shared library '{}', p/invoke may fail", symbol_name, library_name); + log_warn (LOG_ASSEMBLY, "Symbol '{}' not found in shared library '{}', p/invoke may fail", optional_string (library_name), optional_string (symbol_name)); return nullptr; } @@ -147,7 +147,7 @@ namespace xamarin::android { handle = fetch_or_create_pinvoke_map_entry (lib_name, entry_name, entrypoint_name_hash, lib_map, /* need_lock */ false); } else { if (iter->second == nullptr) [[unlikely]] { - log_warn (LOG_ASSEMBLY, "Internal error: null entry in p/invoke map for key '{}'", library_name); + log_warn (LOG_ASSEMBLY, "Internal error: null entry in p/invoke map for key '{}'", optional_string (library_name)); return nullptr; // fall back to `monodroid_dlopen` } diff --git a/src/native/pinvoke-override/precompiled.cc b/src/native/pinvoke-override/precompiled.cc index e5c54608ff3..29ac736e433 100644 --- a/src/native/pinvoke-override/precompiled.cc +++ b/src/native/pinvoke-override/precompiled.cc @@ -22,18 +22,19 @@ PinvokeOverride::monodroid_pinvoke_override (const char *library_name, const cha PinvokeEntry *entry = find_pinvoke_address (entrypoint_hash, internal_pinvokes.data (), internal_pinvokes_count); if (entry == nullptr) [[unlikely]] { - log_fatal (LOG_ASSEMBLY, "Internal p/invoke symbol '{} @ {}' (hash: {:x}) not found in compile-time map.", library_name, entrypoint_name, entrypoint_hash); + log_fatal (LOG_ASSEMBLY, "Internal p/invoke symbol '{} @ {}' (hash: {:x}) not found in compile-time map.", + optional_string (library_name), optional_string (entrypoint_name), entrypoint_hash); log_fatal (LOG_ASSEMBLY, "compile-time map contents:"sv); for (size_t i = 0uz; i < internal_pinvokes_count; i++) { PinvokeEntry const& e = internal_pinvokes[i]; - log_fatal (LOG_ASSEMBLY, "\t'{}'={:p} (hash: {:x})", e.name, e.func, e.hash); + log_fatal (LOG_ASSEMBLY, "\t'{}'={:p} (hash: {:x})", optional_string (e.name), e.func, e.hash); } Helpers::abort_application ( LOG_ASSEMBLY, std::format ( "Failure handling a p/invoke request for '{}'@'{}'", - entrypoint_name, - library_name + optional_string (entrypoint_name), + optional_string (library_name) ) ); } @@ -67,7 +68,8 @@ PinvokeOverride::monodroid_pinvoke_override (const char *library_name, const cha load_library_entry (library_name, entrypoint_name, *entry, dotnet_dso_handle); if (entry->func == nullptr) { - log_fatal (LOG_ASSEMBLY, "Failed to load symbol '{}' from shared library '{}'", entrypoint_name, library_name); + log_fatal (LOG_ASSEMBLY, "Failed to load symbol '{}' from shared library '{}'", + optional_string (entrypoint_name), optional_string (library_name)); return nullptr; // let Mono deal with the fallout } @@ -75,7 +77,8 @@ PinvokeOverride::monodroid_pinvoke_override (const char *library_name, const cha } // It's possible we don't have an entry for some `dotnet` p/invoke, fall back to the slow path below - log_debug (LOG_ASSEMBLY, "Symbol '{}' in library '{}' not found in the generated tables, falling back to slow path", entrypoint_name, library_name); + log_debug (LOG_ASSEMBLY, "Symbol '{}' in library '{}' not found in the generated tables, falling back to slow path", + optional_string (entrypoint_name), optional_string (library_name)); } return handle_other_pinvoke_request (library_name, library_name_hash, entrypoint_name, entrypoint_hash); diff --git a/src/native/runtime-base/logger.cc b/src/native/runtime-base/logger.cc index a331d7112bb..dcc93d08d7e 100644 --- a/src/native/runtime-base/logger.cc +++ b/src/native/runtime-base/logger.cc @@ -29,13 +29,11 @@ namespace { if (path && access (path, W_OK) < 0) { log_warn (category, - std::format ( - "Could not open path '{}' for logging (\"{}\"). Using '{}/{}' instead.", - path, - strerror (errno), - override_dir, - filename - ) + "Could not open path '{}' for logging (\"{}\"). Using '{}/{}' instead.", + optional_string (path), + strerror (errno), + optional_string (override_dir), + optional_string (filename) ); path = NULL; } @@ -53,7 +51,7 @@ namespace { if (f) { Util::set_world_accessable (path); } else { - log_warn (category, std::format ("Could not open path '{}' for logging: {}", path, strerror (errno))); + log_warn (category, "Could not open path '{}' for logging: {}", optional_string (path), strerror (errno)); } free (p); @@ -79,12 +77,12 @@ Logger::set_debugger_log_level (const char *level) noexcept unsigned long v = strtoul (level, nullptr, 0); if (v == std::numeric_limits::max () && errno == ERANGE) { - log_error (LOG_DEFAULT, std::format ("Invalid debugger log level value '{}', expecting a positive integer or zero", level)); + log_error (LOG_DEFAULT, "Invalid debugger log level value '{}', expecting a positive integer or zero", level); return; } if (v > std::numeric_limits::max ()) { - log_warn (LOG_DEFAULT, std::format ("Debugger log level value is higher than the maximum of {}, resetting to the maximum value.", std::numeric_limits::max ())); + log_warn (LOG_DEFAULT, "Debugger log level value is higher than the maximum of {}, resetting to the maximum value.", std::numeric_limits::max ()); v = std::numeric_limits::max (); } diff --git a/src/native/shared/helpers.hh b/src/native/shared/helpers.hh index c69d49d7ee3..62aeea9e00e 100644 --- a/src/native/shared/helpers.hh +++ b/src/native/shared/helpers.hh @@ -86,5 +86,15 @@ namespace xamarin::android { return reinterpret_cast(reinterpret_cast(ptr) + offset); } + + [[gnu::always_inline]] + static inline constexpr auto optional_string (const char* s, const char *replacement = nullptr) noexcept -> const char* + { + if (s != nullptr) [[likely]] { + return s; + } + + return replacement == nullptr ? "" : replacement; + } } #endif // __HELPERS_HH diff --git a/src/native/xamarin-debug-app-helper/debug-app-helper.cc b/src/native/xamarin-debug-app-helper/debug-app-helper.cc index ac3e9e75e81..e64c42750c8 100644 --- a/src/native/xamarin-debug-app-helper/debug-app-helper.cc +++ b/src/native/xamarin-debug-app-helper/debug-app-helper.cc @@ -48,7 +48,7 @@ Java_mono_android_DebugRuntime_init (JNIEnv *env, [[maybe_unused]] jclass klass, if (runtimeNativeLibDir != nullptr) { jstr = runtimeNativeLibDir; AndroidSystem::set_runtime_libdir (Util::strdup_new (jstr.get_cstr ())); - log_warn (LOG_DEFAULT, "Using runtime path: {}", AndroidSystem::get_runtime_libdir ()); + log_warn (LOG_DEFAULT, "Using runtime path: {}", optional_string (AndroidSystem::get_runtime_libdir ())); } const char *monosgen_path = get_libmonosgen_path (); @@ -75,7 +75,9 @@ copy_file_to_internal_location (char *to_dir, char *from_dir, char *file) log_warn (LOG_DEFAULT, "Copying file `{}` from external location `{}` to internal location `{}`", - file, from_dir, to_dir + optional_string (file), + optional_string (from_dir), + optional_string (to_dir) ); to_file = Util::path_combine (to_dir, file); @@ -84,12 +86,12 @@ copy_file_to_internal_location (char *to_dir, char *from_dir, char *file) int r = unlink (to_file); if (r < 0 && errno != ENOENT) { - log_warn (LOG_DEFAULT, "Unable to delete file `{}`: {}", to_file, strerror (errno)); + log_warn (LOG_DEFAULT, "Unable to delete file `{}`: {}", optional_string (to_file), strerror (errno)); break; } if (!Util::file_copy (to_file, from_file)) { - log_warn (LOG_DEFAULT, "Copy failed from `{}` to `{}`: {}", from_file, to_file, strerror (errno)); + log_warn (LOG_DEFAULT, "Copy failed from `{}` to `{}`: {}", optional_string (from_file), optional_string (to_file), strerror (errno)); break; } @@ -108,22 +110,22 @@ copy_native_libraries_to_internal_location () dirent *e; char *dir_path = Util::path_combine (od, "lib"); - log_warn (LOG_DEFAULT, "checking directory: `{}`", dir_path); + log_warn (LOG_DEFAULT, "checking directory: `{}`", optional_string (dir_path)); if (dir_path == nullptr || !Util::directory_exists (dir_path)) { - log_warn (LOG_DEFAULT, "directory does not exist: `{}`", dir_path); + log_warn (LOG_DEFAULT, "directory does not exist: `{}`", optional_string (dir_path)); delete[] dir_path; continue; } if ((dir = ::opendir (dir_path)) == nullptr) { - log_warn (LOG_DEFAULT, "could not open directory: `{}`", dir_path); + log_warn (LOG_DEFAULT, "could not open directory: `{}`", optional_string (dir_path)); delete[] dir_path; continue; } while ((e = readdir (dir)) != nullptr) { - log_warn (LOG_DEFAULT, "checking file: `{}`", e->d_name); + log_warn (LOG_DEFAULT, "checking file: `{}`", optional_string (e->d_name)); if (Util::monodroid_dirent_hasextension (e, ".so")) { copy_file_to_internal_location (AndroidSystem::get_primary_override_dir (), dir_path, e->d_name); } @@ -140,9 +142,9 @@ runtime_exists (const char *dir, char*& libmonoso) return false; libmonoso = Util::path_combine (dir, SharedConstants::MONO_SGEN_SO); - log_warn (LOG_DEFAULT, "Checking whether Mono runtime exists at: {}", libmonoso); + log_warn (LOG_DEFAULT, "Checking whether Mono runtime exists at: {}", optional_string (libmonoso)); if (Util::file_exists (libmonoso)) { - log_info (LOG_DEFAULT, "Mono runtime found at: {}", libmonoso); + log_info (LOG_DEFAULT, "Mono runtime found at: {}", optional_string (libmonoso)); return true; } delete[] libmonoso; @@ -194,7 +196,7 @@ get_libmonosgen_path () if (!Util::file_exists (link)) { int result = symlink (libmonoso, link); if (result != 0 && errno == EEXIST) { - log_warn (LOG_DEFAULT, "symlink exists, recreating: {} -> {}", link, libmonoso); + log_warn (LOG_DEFAULT, "symlink exists, recreating: {} -> {}", optional_string (link), optional_string (libmonoso)); unlink (link); result = symlink (libmonoso, link); } @@ -205,7 +207,7 @@ get_libmonosgen_path () libmonoso = link; } - log_warn (LOG_DEFAULT, "Trying to load sgen from: {}", libmonoso != nullptr ? libmonoso : ""sv); + log_warn (LOG_DEFAULT, "Trying to load sgen from: {}", optional_string (libmonoso)); if (libmonoso != nullptr && Util::file_exists (libmonoso)) return libmonoso; delete[] libmonoso; @@ -217,11 +219,11 @@ get_libmonosgen_path () for (const char *od : AndroidSystem::override_dirs) { if (od == nullptr) continue; - log_fatal (LOG_DEFAULT, " %s", od); + log_fatal (LOG_DEFAULT, " {}", optional_string (od)); } for (const char *app_lib_dir : AndroidSystem::app_lib_directories) { - log_fatal (LOG_DEFAULT, " %s", app_lib_dir); + log_fatal (LOG_DEFAULT, " {}", optional_string (app_lib_dir)); } Helpers::abort_application ( From 5a4d188eb451000f4e2c7a3b8426208fbb30b9a2 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Tue, 3 Dec 2024 13:38:51 +0100 Subject: [PATCH 24/54] Address feedback --- src/native/shared/cpp-util.hh | 63 +++++++++++++++++++++++++++++++++-- 1 file changed, 61 insertions(+), 2 deletions(-) diff --git a/src/native/shared/cpp-util.hh b/src/native/shared/cpp-util.hh index 3951b81f474..6e77d98f5f7 100644 --- a/src/native/shared/cpp-util.hh +++ b/src/native/shared/cpp-util.hh @@ -7,9 +7,12 @@ #include #include #include +#include #include +#include #include #include +#include #include #include @@ -30,6 +33,50 @@ namespace xamarin::android::detail { va_end (ap); return ret == -1 ? "Out of memory" : message; } + + [[gnu::always_inline]] + static inline std::string get_function_name (const char *signature) + { + using std::operator""sv; + + std::string_view sig { signature }; + if (sig.length () == 0) { + return ""; + } + + auto splitSignature = sig | std::views::split ("::"sv) | std::ranges::to> (); + + std::string ret; + if (splitSignature.size () > 1) { + ret.append (splitSignature [splitSignature.size () - 2]); + ret.append ("::"sv); + } + std::string_view func_name { splitSignature[splitSignature.size () - 1] }; + std::string_view::size_type args_pos = func_name.find ('('); + std::string_view::size_type name_start_pos = func_name.find (' '); + + if (name_start_pos == std::string_view::npos) { + name_start_pos = 0; + } else { + name_start_pos++; // point to after the space which separates return type from name + if (name_start_pos >= func_name.length ()) [[unlikely]] { + name_start_pos = 0; + } + } + + if (args_pos == std::string_view::npos) { + ret.append (func_name.substr (name_start_pos)); + } else { + // If there's a snafu with positions, start from 0 + if (name_start_pos >= args_pos || name_start_pos > func_name.length ()) [[unlikely]] { + name_start_pos = 0; + } + + ret.append (func_name.substr (name_start_pos, args_pos - name_start_pos)); + } + + return ret; + } } template F> @@ -63,7 +110,13 @@ abort_if_invalid_pointer_argument (T *ptr, const char *ptr_name, std::source_loc { abort_unless ( ptr != nullptr, - [&ptr_name] { return xamarin::android::detail::_format_message ("Parameter '%s' must be a valid pointer", ptr_name); }, + [&ptr_name, &sloc] { + return xamarin::android::detail::_format_message ( + "%s: parameter '%s' must be a valid pointer", + xamarin::android::detail::get_function_name (sloc.function_name ()).c_str (), + ptr_name + ); + }, sloc ); } @@ -74,7 +127,13 @@ abort_if_negative_integer_argument (int arg, const char *arg_name, std::source_l { abort_unless ( arg > 0, - [&arg_name] { return xamarin::android::detail::_format_message ("Parameter '%s' must be a valid pointer", arg_name); }, + [&arg_name, &sloc] { + return xamarin::android::detail::_format_message ( + "%s: parameter '%s' must be a valid pointer", + xamarin::android::detail::get_function_name (sloc.function_name ()).c_str (), + arg_name + ); + }, sloc ); } From 18fd98726a4f43bcad754f9f120b699aecea11de Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Tue, 26 Nov 2024 11:04:09 +0100 Subject: [PATCH 25/54] Enable static linking with libc++ * Add a version script which hides all the symbols except for the handful we have to export. * Enable exceptions --- src/native/CMakeLists.txt | 9 ++------- src/native/CMakePresets.json.in | 4 ++-- src/native/libmono-android.map.txt | 15 +++++++++++++++ src/native/monodroid/CMakeLists.txt | 6 ++++++ 4 files changed, 25 insertions(+), 9 deletions(-) create mode 100644 src/native/libmono-android.map.txt diff --git a/src/native/CMakeLists.txt b/src/native/CMakeLists.txt index 6abbe4f5a03..f5be63f38d6 100644 --- a/src/native/CMakeLists.txt +++ b/src/native/CMakeLists.txt @@ -120,13 +120,8 @@ else() set(USES_LIBSTDCPP True) endif() -if(ANALYZERS_ENABLED) - message(STATUS "Analyzers enabled") - set(SHARED_LIB_NAME xa::shared-no-abi) -else() - message(STATUS "NO analyzers enabled") - set(SHARED_LIB_NAME xa::shared) -endif() +set(SHARED_LIB_NAME xa::shared-no-abi) + # # Needed modules # diff --git a/src/native/CMakePresets.json.in b/src/native/CMakePresets.json.in index e7b90193064..33c910f6845 100644 --- a/src/native/CMakePresets.json.in +++ b/src/native/CMakePresets.json.in @@ -48,8 +48,8 @@ "hidden": true, "inherits": "common", "cacheVariables": { - "ANDROID_STL": "none", - "ANDROID_CPP_FEATURES": "no-rtti no-exceptions" + "ANDROID_STL": "c++_static", + "ANDROID_CPP_FEATURES": "no-rtti exceptions" } }, diff --git a/src/native/libmono-android.map.txt b/src/native/libmono-android.map.txt new file mode 100644 index 00000000000..18bcab675ef --- /dev/null +++ b/src/native/libmono-android.map.txt @@ -0,0 +1,15 @@ +LIBMONO_ANDROID { + global: + JNI_OnLoad; + Java_mono_android_Runtime_dumpTimingData; + Java_mono_android_Runtime_init; + Java_mono_android_Runtime_initInternal; + Java_mono_android_Runtime_notifyTimeZoneChanged; + Java_mono_android_Runtime_propagateUncaughtException; + Java_mono_android_Runtime_register; + _monodroid_freeifaddrs; + _monodroid_getifaddrs; + + local: + *; +}; diff --git a/src/native/monodroid/CMakeLists.txt b/src/native/monodroid/CMakeLists.txt index 8a5ebc0ec12..c191a6103bb 100644 --- a/src/native/monodroid/CMakeLists.txt +++ b/src/native/monodroid/CMakeLists.txt @@ -243,6 +243,12 @@ endmacro () lib_target_options(${XAMARIN_MONO_ANDROID_LIB}) xa_add_compile_definitions(${XAMARIN_MONO_ANDROID_LIB}) +target_link_options(${XAMARIN_MONO_ANDROID_LIB} + PRIVATE + -Wl,--version-script,${CMAKE_SOURCE_DIR}/libmono-android.map.txt + -Wl,--no-undefined-version +) + if(BUILD_STATIC_LIBRARY) lib_target_options(${XAMARIN_MONO_ANDROID_STATIC_LIB}) xa_add_compile_definitions(${XAMARIN_MONO_ANDROID_STATIC_LIB}) From 3f2b0788cd302137afc8a3bb613028063c5d8ece Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Tue, 26 Nov 2024 11:11:57 +0100 Subject: [PATCH 26/54] Remove C++ ABI compatibility sources --- src-ThirdParty/llvm/verbose_abort.cpp | 77 -------------------------- src/native/CMakeLists.txt | 2 +- src/native/shared/CMakeLists.txt | 21 +------ src/native/shared/cxx-abi/string.cc | 12 ---- src/native/shared/cxx-abi/terminate.cc | 17 ------ src/native/tracing/CMakeLists.txt | 2 +- 6 files changed, 3 insertions(+), 128 deletions(-) delete mode 100644 src-ThirdParty/llvm/verbose_abort.cpp delete mode 100644 src/native/shared/cxx-abi/string.cc delete mode 100644 src/native/shared/cxx-abi/terminate.cc diff --git a/src-ThirdParty/llvm/verbose_abort.cpp b/src-ThirdParty/llvm/verbose_abort.cpp deleted file mode 100644 index 719134e2ae5..00000000000 --- a/src-ThirdParty/llvm/verbose_abort.cpp +++ /dev/null @@ -1,77 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include <__config> -#include <__verbose_abort> -#include -#include -#include - -#ifdef __BIONIC__ -# include -# if __ANDROID_API__ >= 21 -# include -extern "C" void android_set_abort_message(const char* msg); -# else -# include -# endif // __ANDROID_API__ >= 21 -#endif // __BIONIC__ - -#if defined(__APPLE__) && __has_include() -# include -#endif - -_LIBCPP_BEGIN_NAMESPACE_STD - -_LIBCPP_WEAK void __libcpp_verbose_abort(char const* format, ...) { - // Write message to stderr. We do this before formatting into a - // buffer so that we still get some information out if that fails. - { - va_list list; - va_start(list, format); - std::vfprintf(stderr, format, list); - va_end(list); - } - - // Format the arguments into an allocated buffer for CrashReport & friends. - // We leak the buffer on purpose, since we're about to abort() anyway. - char* buffer; - (void)buffer; - va_list list; - va_start(list, format); - -#if defined(__APPLE__) && __has_include() - // Note that we should technically synchronize accesses here (by e.g. taking a lock), - // however concretely we're only setting a pointer, so the likelihood of a race here - // is low. - vasprintf(&buffer, format, list); - CRSetCrashLogMessage(buffer); -#elif defined(__BIONIC__) - vasprintf(&buffer, format, list); - -# if __ANDROID_API__ >= 21 - // Show error in tombstone. - android_set_abort_message(buffer); - - // Show error in logcat. - openlog("libc++", 0, 0); - syslog(LOG_CRIT, "%s", buffer); - closelog(); -# else - // The good error reporting wasn't available in Android until L. Since we're - // about to abort anyway, just call __assert2, which will log _somewhere_ - // (tombstone and/or logcat) in older releases. - __assert2(__FILE__, __LINE__, __func__, buffer); -# endif // __ANDROID_API__ >= 21 -#endif - va_end(list); - - std::abort(); -} - -_LIBCPP_END_NAMESPACE_STD diff --git a/src/native/CMakeLists.txt b/src/native/CMakeLists.txt index f5be63f38d6..b6109634c19 100644 --- a/src/native/CMakeLists.txt +++ b/src/native/CMakeLists.txt @@ -120,7 +120,7 @@ else() set(USES_LIBSTDCPP True) endif() -set(SHARED_LIB_NAME xa::shared-no-abi) +set(SHARED_LIB_NAME xa::shared) # # Needed modules diff --git a/src/native/shared/CMakeLists.txt b/src/native/shared/CMakeLists.txt index 958c474f63c..4a3bb7ece18 100644 --- a/src/native/shared/CMakeLists.txt +++ b/src/native/shared/CMakeLists.txt @@ -1,21 +1,12 @@ set(LIB_NAME xa-shared-bits) set(LIB_ALIAS xa::shared) -set(LIB_NAME_NO_ABI ${LIB_NAME}-no-abi) -set(LIB_ALIAS_NO_ABI ${LIB_ALIAS}-no-abi) - -set(XA_SHARED_CXX_ABI_SOURCES - cxx-abi/string.cc - cxx-abi/terminate.cc - ${REPO_ROOT_DIR}/src-ThirdParty/llvm/verbose_abort.cpp -) - set(XA_SHARED_SOURCES helpers.cc log_functions.cc new_delete.cc ) -add_clang_check_sources("${XA_SHARED_SOURCES};${XA_SHARED_CXX_ABI_SOURCES}") +add_clang_check_sources("${XA_SHARED_SOURCES};") set(XXHASH_DIR "${EXTERNAL_DIR}/xxHash") set(CONSTEXPR_XXH3_DIR "${EXTERNAL_DIR}/constexpr-xxh3") @@ -30,15 +21,6 @@ add_library(${LIB_ALIAS} ALIAS ${LIB_NAME}) set_static_library_suffix(${LIB_NAME}) -add_library( - ${LIB_NAME_NO_ABI} - STATIC - ${XA_SHARED_SOURCES} -) -add_library(${LIB_ALIAS_NO_ABI} ALIAS ${LIB_NAME_NO_ABI}) - -set_static_library_suffix(${LIB_NAME_NO_ABI}) - macro(lib_target_options TARGET_NAME) target_include_directories( ${TARGET_NAME} @@ -81,4 +63,3 @@ macro(lib_target_options TARGET_NAME) endmacro() lib_target_options(${LIB_NAME}) -lib_target_options(${LIB_NAME_NO_ABI}) diff --git a/src/native/shared/cxx-abi/string.cc b/src/native/shared/cxx-abi/string.cc deleted file mode 100644 index 30d528e14ac..00000000000 --- a/src/native/shared/cxx-abi/string.cc +++ /dev/null @@ -1,12 +0,0 @@ -// -// Defining the macro will make the the explicit instantations below truely hidden -// -#define _LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS - -#include - -_LIBCPP_BEGIN_NAMESPACE_STD - -template class __attribute__ ((__visibility__("hidden"))) basic_string; - -_LIBCPP_END_NAMESPACE_STD diff --git a/src/native/shared/cxx-abi/terminate.cc b/src/native/shared/cxx-abi/terminate.cc deleted file mode 100644 index 04dc890fb61..00000000000 --- a/src/native/shared/cxx-abi/terminate.cc +++ /dev/null @@ -1,17 +0,0 @@ -// -// Simple implementation of std::terminate() for Xamarin.Android -// -// Does NOT support terminate handlers, since we don't use them. -// -#include -#include - -#include "helpers.hh" - -namespace std { - [[noreturn]] void - terminate () noexcept - { - xamarin::android::Helpers::abort_application ("std::terminate() called. Aborting."); - } -} diff --git a/src/native/tracing/CMakeLists.txt b/src/native/tracing/CMakeLists.txt index cc91cb2fa78..558b3513659 100644 --- a/src/native/tracing/CMakeLists.txt +++ b/src/native/tracing/CMakeLists.txt @@ -62,7 +62,7 @@ target_link_options( target_link_libraries( ${LIB_NAME} PRIVATE - xa::shared-no-abi + xa::shared xa::unwind xa::runtime-base xa::java-interop From 541c402b61bcd6be407a3c0dd1de8b0cab36aa82 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Tue, 26 Nov 2024 16:05:55 +0100 Subject: [PATCH 27/54] Update apkdesc files --- .../BuildReleaseArm64SimpleDotNet.apkdesc | 28 ++--- .../BuildReleaseArm64XFormsDotNet.apkdesc | 101 +++++++++--------- 2 files changed, 66 insertions(+), 63 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleDotNet.apkdesc b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleDotNet.apkdesc index 54d10a91441..b94b94d9485 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleDotNet.apkdesc +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleDotNet.apkdesc @@ -5,34 +5,34 @@ "Size": 3036 }, "classes.dex": { - "Size": 22488 + "Size": 389632 }, "lib/arm64-v8a/lib__Microsoft.Android.Resource.Designer.dll.so": { - "Size": 18208 + "Size": 18296 }, "lib/arm64-v8a/lib_Java.Interop.dll.so": { - "Size": 86368 + "Size": 86352 }, "lib/arm64-v8a/lib_Mono.Android.dll.so": { - "Size": 115752 + "Size": 116768 }, "lib/arm64-v8a/lib_Mono.Android.Runtime.dll.so": { - "Size": 22408 + "Size": 22416 }, "lib/arm64-v8a/lib_System.Console.dll.so": { - "Size": 24384 + "Size": 24376 }, "lib/arm64-v8a/lib_System.Linq.dll.so": { "Size": 26480 }, "lib/arm64-v8a/lib_System.Private.CoreLib.dll.so": { - "Size": 633792 + "Size": 634384 }, "lib/arm64-v8a/lib_System.Runtime.dll.so": { - "Size": 20048 + "Size": 20040 }, "lib/arm64-v8a/lib_System.Runtime.InteropServices.dll.so": { - "Size": 21592 + "Size": 21584 }, "lib/arm64-v8a/lib_UnnamedProject.dll.so": { "Size": 20024 @@ -44,10 +44,10 @@ "Size": 87432 }, "lib/arm64-v8a/libmonodroid.so": { - "Size": 485800 + "Size": 903032 }, "lib/arm64-v8a/libmonosgen-2.0.so": { - "Size": 3196336 + "Size": 3196512 }, "lib/arm64-v8a/libSystem.Globalization.Native.so": { "Size": 67248 @@ -62,10 +62,10 @@ "Size": 160232 }, "lib/arm64-v8a/libxamarin-app.so": { - "Size": 17912 + "Size": 13016 }, "META-INF/BNDLTOOL.RSA": { - "Size": 1221 + "Size": 1223 }, "META-INF/BNDLTOOL.SF": { "Size": 3266 @@ -98,5 +98,5 @@ "Size": 1904 } }, - "PackageSize": 2791957 + "PackageSize": 2984469 } \ No newline at end of file diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsDotNet.apkdesc b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsDotNet.apkdesc index 43092050ff6..40a70162747 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsDotNet.apkdesc +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsDotNet.apkdesc @@ -5,7 +5,10 @@ "Size": 6652 }, "classes.dex": { - "Size": 9172800 + "Size": 9448880 + }, + "classes2.dex": { + "Size": 154180 }, "kotlin/annotation/annotation.kotlin_builtins": { "Size": 928 @@ -29,28 +32,28 @@ "Size": 2396 }, "lib/arm64-v8a/lib__Microsoft.Android.Resource.Designer.dll.so": { - "Size": 19456 + "Size": 19544 }, "lib/arm64-v8a/lib_FormsViewGroup.dll.so": { - "Size": 25424 + "Size": 25184 }, "lib/arm64-v8a/lib_Java.Interop.dll.so": { - "Size": 94768 + "Size": 94736 }, "lib/arm64-v8a/lib_Mono.Android.dll.so": { - "Size": 523568 + "Size": 522832 }, "lib/arm64-v8a/lib_Mono.Android.Runtime.dll.so": { - "Size": 22408 + "Size": 22416 }, "lib/arm64-v8a/lib_mscorlib.dll.so": { "Size": 21432 }, "lib/arm64-v8a/lib_netstandard.dll.so": { - "Size": 23080 + "Size": 23072 }, "lib/arm64-v8a/lib_System.Collections.Concurrent.dll.so": { - "Size": 29808 + "Size": 29792 }, "lib/arm64-v8a/lib_System.Collections.dll.so": { "Size": 36288 @@ -59,7 +62,7 @@ "Size": 25760 }, "lib/arm64-v8a/lib_System.Collections.Specialized.dll.so": { - "Size": 23848 + "Size": 23840 }, "lib/arm64-v8a/lib_System.ComponentModel.dll.so": { "Size": 19584 @@ -71,31 +74,31 @@ "Size": 42456 }, "lib/arm64-v8a/lib_System.Console.dll.so": { - "Size": 24424 + "Size": 24416 }, "lib/arm64-v8a/lib_System.Core.dll.so": { - "Size": 19456 + "Size": 19448 }, "lib/arm64-v8a/lib_System.Diagnostics.DiagnosticSource.dll.so": { "Size": 28440 }, "lib/arm64-v8a/lib_System.Diagnostics.TraceSource.dll.so": { - "Size": 24696 + "Size": 24688 }, "lib/arm64-v8a/lib_System.dll.so": { - "Size": 19856 + "Size": 19848 }, "lib/arm64-v8a/lib_System.Drawing.dll.so": { - "Size": 19432 + "Size": 19424 }, "lib/arm64-v8a/lib_System.Drawing.Primitives.dll.so": { - "Size": 30048 + "Size": 30040 }, "lib/arm64-v8a/lib_System.Formats.Asn1.dll.so": { - "Size": 49936 + "Size": 49928 }, "lib/arm64-v8a/lib_System.IO.Compression.Brotli.dll.so": { - "Size": 29488 + "Size": 29472 }, "lib/arm64-v8a/lib_System.IO.Compression.dll.so": { "Size": 33784 @@ -107,7 +110,7 @@ "Size": 38736 }, "lib/arm64-v8a/lib_System.Linq.Expressions.dll.so": { - "Size": 185816 + "Size": 185800 }, "lib/arm64-v8a/lib_System.Net.Http.dll.so": { "Size": 89488 @@ -116,85 +119,85 @@ "Size": 41112 }, "lib/arm64-v8a/lib_System.Net.Requests.dll.so": { - "Size": 21552 + "Size": 21544 }, "lib/arm64-v8a/lib_System.ObjectModel.dll.so": { - "Size": 27072 + "Size": 27064 }, "lib/arm64-v8a/lib_System.Private.CoreLib.dll.so": { - "Size": 956368 + "Size": 956552 }, "lib/arm64-v8a/lib_System.Private.DataContractSerialization.dll.so": { - "Size": 216688 + "Size": 216720 }, "lib/arm64-v8a/lib_System.Private.Uri.dll.so": { "Size": 62184 }, "lib/arm64-v8a/lib_System.Private.Xml.dll.so": { - "Size": 237096 + "Size": 237120 }, "lib/arm64-v8a/lib_System.Private.Xml.Linq.dll.so": { - "Size": 35592 + "Size": 35584 }, "lib/arm64-v8a/lib_System.Runtime.dll.so": { "Size": 20200 }, "lib/arm64-v8a/lib_System.Runtime.InteropServices.dll.so": { - "Size": 21592 + "Size": 21584 }, "lib/arm64-v8a/lib_System.Runtime.Numerics.dll.so": { - "Size": 54400 + "Size": 54408 }, "lib/arm64-v8a/lib_System.Runtime.Serialization.dll.so": { - "Size": 19360 + "Size": 19352 }, "lib/arm64-v8a/lib_System.Runtime.Serialization.Formatters.dll.so": { - "Size": 20336 + "Size": 20328 }, "lib/arm64-v8a/lib_System.Runtime.Serialization.Primitives.dll.so": { - "Size": 21456 + "Size": 21448 }, "lib/arm64-v8a/lib_System.Security.Cryptography.dll.so": { "Size": 80496 }, "lib/arm64-v8a/lib_System.Text.RegularExpressions.dll.so": { - "Size": 183600 + "Size": 183584 }, "lib/arm64-v8a/lib_System.Xml.dll.so": { - "Size": 19256 + "Size": 19248 }, "lib/arm64-v8a/lib_System.Xml.Linq.dll.so": { - "Size": 19272 + "Size": 19264 }, "lib/arm64-v8a/lib_UnnamedProject.dll.so": { "Size": 22096 }, "lib/arm64-v8a/lib_Xamarin.AndroidX.Activity.dll.so": { - "Size": 34960 + "Size": 34760 }, "lib/arm64-v8a/lib_Xamarin.AndroidX.AppCompat.AppCompatResources.dll.so": { - "Size": 24520 + "Size": 24296 }, "lib/arm64-v8a/lib_Xamarin.AndroidX.AppCompat.dll.so": { - "Size": 163240 + "Size": 163072 }, "lib/arm64-v8a/lib_Xamarin.AndroidX.CardView.dll.so": { "Size": 24560 }, "lib/arm64-v8a/lib_Xamarin.AndroidX.CoordinatorLayout.dll.so": { - "Size": 35912 + "Size": 35680 }, "lib/arm64-v8a/lib_Xamarin.AndroidX.Core.dll.so": { - "Size": 151408 + "Size": 151216 }, "lib/arm64-v8a/lib_Xamarin.AndroidX.CursorAdapter.dll.so": { "Size": 27168 }, "lib/arm64-v8a/lib_Xamarin.AndroidX.DrawerLayout.dll.so": { - "Size": 33944 + "Size": 33760 }, "lib/arm64-v8a/lib_Xamarin.AndroidX.Fragment.dll.so": { - "Size": 72528 + "Size": 72224 }, "lib/arm64-v8a/lib_Xamarin.AndroidX.Legacy.Support.Core.UI.dll.so": { "Size": 23896 @@ -212,16 +215,16 @@ "Size": 31592 }, "lib/arm64-v8a/lib_Xamarin.AndroidX.RecyclerView.dll.so": { - "Size": 112256 + "Size": 111896 }, "lib/arm64-v8a/lib_Xamarin.AndroidX.SavedState.dll.so": { "Size": 23144 }, "lib/arm64-v8a/lib_Xamarin.AndroidX.SwipeRefreshLayout.dll.so": { - "Size": 31952 + "Size": 31672 }, "lib/arm64-v8a/lib_Xamarin.AndroidX.ViewPager.dll.so": { - "Size": 38056 + "Size": 37752 }, "lib/arm64-v8a/lib_Xamarin.Forms.Core.dll.so": { "Size": 581000 @@ -236,7 +239,7 @@ "Size": 80632 }, "lib/arm64-v8a/lib_Xamarin.Google.Android.Material.dll.so": { - "Size": 84768 + "Size": 84400 }, "lib/arm64-v8a/libarc.bin.so": { "Size": 18776 @@ -245,10 +248,10 @@ "Size": 87432 }, "lib/arm64-v8a/libmonodroid.so": { - "Size": 485800 + "Size": 903032 }, "lib/arm64-v8a/libmonosgen-2.0.so": { - "Size": 3196336 + "Size": 3196512 }, "lib/arm64-v8a/libSystem.Globalization.Native.so": { "Size": 67248 @@ -263,7 +266,7 @@ "Size": 160232 }, "lib/arm64-v8a/libxamarin-app.so": { - "Size": 349352 + "Size": 120016 }, "META-INF/androidx.activity_activity.version": { "Size": 6 @@ -419,7 +422,7 @@ "Size": 1221 }, "META-INF/BNDLTOOL.SF": { - "Size": 98577 + "Size": 98661 }, "META-INF/com.android.tools/proguard/coroutines.pro": { "Size": 1345 @@ -446,7 +449,7 @@ "Size": 5 }, "META-INF/MANIFEST.MF": { - "Size": 98450 + "Size": 98534 }, "META-INF/maven/com.google.guava/listenablefuture/pom.properties": { "Size": 96 @@ -2486,5 +2489,5 @@ "Size": 812848 } }, - "PackageSize": 10628363 + "PackageSize": 10796357 } \ No newline at end of file From cadc2b5ab1c6a41ff36e3fa72cfeb22050f2bf7a Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Thu, 31 Oct 2024 19:19:59 +0100 Subject: [PATCH 28/54] Playing around with some ideas --- src/native/monodroid/debug.cc | 2 +- src/native/monodroid/embedded-assemblies.hh | 9 +++- src/native/monodroid/monodroid-glue.cc | 15 +++++-- src/native/monodroid/osbridge.cc | 23 +++++++--- src/native/monodroid/xamarin_getifaddrs.cc | 32 ++++++------- src/native/runtime-base/android-system.cc | 2 +- src/native/runtime-base/cpu-arch-detect.cc | 8 ++-- src/native/runtime-base/jni-wrappers.hh | 8 ++-- src/native/shared/cpp-util.hh | 50 ++++++++++++++++++--- 9 files changed, 107 insertions(+), 42 deletions(-) diff --git a/src/native/monodroid/debug.cc b/src/native/monodroid/debug.cc index 139e8a24aae..add61468747 100644 --- a/src/native/monodroid/debug.cc +++ b/src/native/monodroid/debug.cc @@ -603,7 +603,7 @@ Debug::enable_soft_breakpoints (void) void* xamarin::android::conn_thread (void *arg) { - abort_if_invalid_pointer_argument (arg); + abort_if_invalid_pointer_argument (arg, "arg"); int res; Debug *instance = static_cast (arg); diff --git a/src/native/monodroid/embedded-assemblies.hh b/src/native/monodroid/embedded-assemblies.hh index 1bf6b358705..cfaaf4b9e40 100644 --- a/src/native/monodroid/embedded-assemblies.hh +++ b/src/native/monodroid/embedded-assemblies.hh @@ -26,6 +26,7 @@ #include "cppcompat.hh" #include "shared-constants.hh" #include "xxhash.hh" +#include "util.hh" #include @@ -158,7 +159,13 @@ namespace xamarin::android::internal { { area = static_cast(runtime_config_data); - abort_unless (runtime_config_data_size < std::numeric_limits::max (), "Runtime config binary blob size exceeds %u bytes", std::numeric_limits::max ()); + abort_unless ( + runtime_config_data_size < std::numeric_limits::max (), + [] { + return Util::monodroid_strdup_printf ("Runtime config binary blob size exceeds %u bytes", + std::numeric_limits::max ()); + } + ); size = static_cast(runtime_config_data_size); } diff --git a/src/native/monodroid/monodroid-glue.cc b/src/native/monodroid/monodroid-glue.cc index cd8d899a35d..a4d92ba1461 100644 --- a/src/native/monodroid/monodroid-glue.cc +++ b/src/native/monodroid/monodroid-glue.cc @@ -912,7 +912,12 @@ MonodroidRuntime::init_android_runtime (JNIEnv *env, jclass runtimeClass, jobjec jnienv_register_jni_natives = reinterpret_cast(mono_method_get_unmanaged_callers_only_ftnptr (registerType, &error)); } } - abort_unless (registerType != nullptr, "INTERNAL ERROR: Unable to find Android.Runtime.JNIEnvInit.RegisterJniNatives! %s", mono_error_get_message (&error)); + abort_unless ( + registerType != nullptr, + [&error] { + return Util::monodroid_strdup_printf("INTERNAL ERROR: Unable to find Android.Runtime.JNIEnvInit.RegisterJniNatives! %s", mono_error_get_message (&error)); + } + ); jclass lrefLoaderClass = env->GetObjectClass (loader); init.Loader_loadClass = env->GetMethodID (lrefLoaderClass, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;"); @@ -937,8 +942,12 @@ MonodroidRuntime::init_android_runtime (JNIEnv *env, jclass runtimeClass, jobjec abort_unless ( initialize != nullptr, - "Failed to obtain unmanaged-callers-only pointer to the Android.Runtime.JNIEnvInit.Initialize method. %s", - mono_error_get_message (&error) + [&error] { + return Util::monodroid_strdup_printf ( + "Failed to obtain unmanaged-callers-only pointer to the Android.Runtime.JNIEnvInit.Initialize method. %s", + mono_error_get_message (&error) + ); + } ); initialize (&init); diff --git a/src/native/monodroid/osbridge.cc b/src/native/monodroid/osbridge.cc index fe68ce59d06..cc900a30906 100644 --- a/src/native/monodroid/osbridge.cc +++ b/src/native/monodroid/osbridge.cc @@ -683,7 +683,7 @@ OSBridge::target_from_jobject (jobject jobj) int OSBridge::scc_get_stashed_index (MonoGCBridgeSCC *scc) { - abort_if_invalid_pointer_argument (scc); + abort_if_invalid_pointer_argument (scc, "scc"); abort_unless (scc->num_objs < 0, "Attempted to load stashed index from an object which does not contain one."); return -scc->num_objs - 1; @@ -862,8 +862,14 @@ OSBridge::gc_cleanup_after_java_collection (JNIEnv *env, int num_sccs, MonoGCBri mono_field_get_value (obj, bridge_info->handle, &jref); if (jref) { alive++; - if (j > 0) - abort_unless (sccs [i]->is_alive, "Bridge SCC at index %d must be alive", i); + if (j > 0) { + abort_unless ( + sccs [i]->is_alive, + [&i] { + return Util::monodroid_strdup_printf ("Bridge SCC at index %d must be alive", i); + } + ); + } sccs [i]->is_alive = 1; mono_field_get_value (obj, bridge_info->refs_added, &refs_added); if (refs_added) { @@ -885,7 +891,10 @@ OSBridge::gc_cleanup_after_java_collection (JNIEnv *env, int num_sccs, MonoGCBri } } } else { - abort_unless (!sccs [i]->is_alive, "Bridge SCC at index %d must NOT be alive", i); + abort_unless ( + !sccs [i]->is_alive, + [&i] { return Util::monodroid_strdup_printf ("Bridge SCC at index %d must NOT be alive", i); } + ); } } } @@ -993,8 +1002,8 @@ OSBridge::ensure_jnienv (void) void OSBridge::initialize_on_onload (JavaVM *vm, JNIEnv *env) { - abort_if_invalid_pointer_argument (env); - abort_if_invalid_pointer_argument (vm); + abort_if_invalid_pointer_argument (env, "env"); + abort_if_invalid_pointer_argument (vm, "vm"); jvm = vm; jclass lref = env->FindClass ("java/lang/Runtime"); @@ -1018,7 +1027,7 @@ OSBridge::initialize_on_onload (JavaVM *vm, JNIEnv *env) void OSBridge::initialize_on_runtime_init (JNIEnv *env, jclass runtimeClass) { - abort_if_invalid_pointer_argument (env); + abort_if_invalid_pointer_argument (env, "env"); GCUserPeer_class = RuntimeUtil::get_class_from_runtime_field(env, runtimeClass, "mono_android_GCUserPeer", true); GCUserPeer_ctor = env->GetMethodID (GCUserPeer_class, "", "()V"); abort_unless (GCUserPeer_class != nullptr && GCUserPeer_ctor != nullptr, "Failed to load mono.android.GCUserPeer!"); diff --git a/src/native/monodroid/xamarin_getifaddrs.cc b/src/native/monodroid/xamarin_getifaddrs.cc index 17f0f8a7ba6..9f071132976 100644 --- a/src/native/monodroid/xamarin_getifaddrs.cc +++ b/src/native/monodroid/xamarin_getifaddrs.cc @@ -370,8 +370,8 @@ get_ifaddrs_impl (int (**getifaddrs_implementation) (struct _monodroid_ifaddrs * { void *libc; - abort_if_invalid_pointer_argument (getifaddrs_implementation); - abort_if_invalid_pointer_argument (freeifaddrs_implementation); + abort_if_invalid_pointer_argument (getifaddrs_implementation, "getifaddrs_implementation"); + abort_if_invalid_pointer_argument (freeifaddrs_implementation, "freeifaddrs_implementation"); libc = dlopen ("libc.so", RTLD_NOW); if (libc) { @@ -416,7 +416,7 @@ free_single_xamarin_ifaddrs (struct _monodroid_ifaddrs **ifap) static int open_netlink_session (netlink_session *session) { - abort_if_invalid_pointer_argument (session); + abort_if_invalid_pointer_argument (session, "session"); memset (session, 0, sizeof (*session)); session->sock_fd = socket (AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); @@ -488,9 +488,9 @@ send_netlink_dump_request (netlink_session *session, int type) static int append_ifaddr (struct _monodroid_ifaddrs *addr, struct _monodroid_ifaddrs **ifaddrs_head, struct _monodroid_ifaddrs **last_ifaddr) { - abort_if_invalid_pointer_argument (addr); - abort_if_invalid_pointer_argument (ifaddrs_head); - abort_if_invalid_pointer_argument (last_ifaddr); + abort_if_invalid_pointer_argument (addr, "addr"); + abort_if_invalid_pointer_argument (ifaddrs_head, "ifaddrs_head"); + abort_if_invalid_pointer_argument (last_ifaddr, "last_ifaddr"); if (!*ifaddrs_head) { *ifaddrs_head = *last_ifaddr = addr; @@ -524,9 +524,9 @@ parse_netlink_reply (netlink_session *session, struct _monodroid_ifaddrs **ifadd int ret = -1; unsigned char *response = NULL; - abort_if_invalid_pointer_argument (session); - abort_if_invalid_pointer_argument (ifaddrs_head); - abort_if_invalid_pointer_argument (last_ifaddr); + abort_if_invalid_pointer_argument (session, "session"); + abort_if_invalid_pointer_argument (ifaddrs_head, "ifaddrs_head"); + abort_if_invalid_pointer_argument (last_ifaddr, "last_ifaddr"); size_t buf_size = static_cast(getpagesize ()); log_debug (LOG_NETLINK, "receive buffer size == %d", buf_size); @@ -626,9 +626,9 @@ parse_netlink_reply (netlink_session *session, struct _monodroid_ifaddrs **ifadd static int fill_sa_address (struct sockaddr **sa, struct ifaddrmsg *net_address, void *rta_data, size_t rta_payload_length) { - abort_if_invalid_pointer_argument (sa); - abort_if_invalid_pointer_argument (net_address); - abort_if_invalid_pointer_argument (rta_data); + abort_if_invalid_pointer_argument (sa, "sa"); + abort_if_invalid_pointer_argument (net_address, "net_address"); + abort_if_invalid_pointer_argument (rta_data, "rta_data"); switch (net_address->ifa_family) { case AF_INET: { @@ -688,8 +688,8 @@ fill_sa_address (struct sockaddr **sa, struct ifaddrmsg *net_address, void *rta_ static int fill_ll_address (struct sockaddr_ll_extended **sa, struct ifinfomsg *net_interface, void *rta_data, size_t rta_payload_length) { - abort_if_invalid_pointer_argument (sa); - abort_if_invalid_pointer_argument (net_interface); + abort_if_invalid_pointer_argument (sa, "sa"); + abort_if_invalid_pointer_argument (net_interface, "net_interface"); /* Always allocate, do not free - caller may reuse the same variable */ *sa = reinterpret_cast(calloc (1, sizeof (**sa))); @@ -845,7 +845,7 @@ get_link_address (const struct nlmsghdr *message, struct _monodroid_ifaddrs **if struct sockaddr **sa; size_t payload_size; - abort_if_invalid_pointer_argument (message); + abort_if_invalid_pointer_argument (message, "message"); net_address = reinterpret_cast (NLMSG_DATA (message)); length = static_cast(IFA_PAYLOAD (message)); log_debug (LOG_NETLINK, " address data length: %u", length); @@ -995,7 +995,7 @@ get_link_info (const struct nlmsghdr *message) struct _monodroid_ifaddrs *ifa = NULL; struct sockaddr_ll_extended *sa = NULL; - abort_if_invalid_pointer_argument (message); + abort_if_invalid_pointer_argument (message, "message"); net_interface = reinterpret_cast (NLMSG_DATA (message)); length = static_cast(message->nlmsg_len - NLMSG_LENGTH (sizeof (*net_interface))); if (length <= 0) { diff --git a/src/native/runtime-base/android-system.cc b/src/native/runtime-base/android-system.cc index 025362628ae..44745a7f34f 100644 --- a/src/native/runtime-base/android-system.cc +++ b/src/native/runtime-base/android-system.cc @@ -323,7 +323,7 @@ AndroidSystem::load_dso (const char *path, unsigned int dl_flags, bool skip_exis void* AndroidSystem::load_dso_from_specified_dirs (const char **directories, size_t num_entries, const char *dso_name, unsigned int dl_flags) noexcept { - abort_if_invalid_pointer_argument (directories); + abort_if_invalid_pointer_argument (directories, "directories"); if (dso_name == nullptr) return nullptr; diff --git a/src/native/runtime-base/cpu-arch-detect.cc b/src/native/runtime-base/cpu-arch-detect.cc index d8bcb7dd5fc..7a7a47b0059 100644 --- a/src/native/runtime-base/cpu-arch-detect.cc +++ b/src/native/runtime-base/cpu-arch-detect.cc @@ -10,7 +10,7 @@ static inline constexpr size_t BUF_SIZE = 512uz; static int find_in_maps (const char *str) { - abort_if_invalid_pointer_argument (str); + abort_if_invalid_pointer_argument (str, "str"); FILE *maps = fopen ("/proc/self/maps", "r"); char *line; @@ -112,9 +112,9 @@ get_running_on_cpu (unsigned short *running_on_cpu) void _monodroid_detect_cpu_and_architecture (unsigned short *built_for_cpu, unsigned short *running_on_cpu, unsigned char *is64bit) { - abort_if_invalid_pointer_argument (built_for_cpu); - abort_if_invalid_pointer_argument (running_on_cpu); - abort_if_invalid_pointer_argument (is64bit); + abort_if_invalid_pointer_argument (built_for_cpu, "built_for_cpu"); + abort_if_invalid_pointer_argument (running_on_cpu, "running_on_cpu"); + abort_if_invalid_pointer_argument (is64bit, "is64bit"); *is64bit = is_64_bit (); get_built_for_cpu (built_for_cpu); diff --git a/src/native/runtime-base/jni-wrappers.hh b/src/native/runtime-base/jni-wrappers.hh index afe95e25b7b..e9dde0eb083 100644 --- a/src/native/runtime-base/jni-wrappers.hh +++ b/src/native/runtime-base/jni-wrappers.hh @@ -20,21 +20,21 @@ namespace xamarin::android : env (_env), jstr (nullptr) { - abort_if_invalid_pointer_argument (_env); + abort_if_invalid_pointer_argument (_env, "_env"); } explicit jstring_wrapper (JNIEnv *_env, const jobject jo) noexcept : env (_env), jstr (reinterpret_cast (jo)) { - abort_if_invalid_pointer_argument (_env); + abort_if_invalid_pointer_argument (_env, "_env"); } explicit jstring_wrapper (JNIEnv *_env, const jstring js) noexcept : env (_env), jstr (js) { - abort_if_invalid_pointer_argument (_env); + abort_if_invalid_pointer_argument (_env, "_env"); } jstring_wrapper (const jstring_wrapper&) = delete; @@ -137,7 +137,7 @@ namespace xamarin::android : env (_env), arr (_arr) { - abort_if_invalid_pointer_argument (_env); + abort_if_invalid_pointer_argument (_env, "_env"); if (_arr != nullptr) { len = static_cast(_env->GetArrayLength (_arr)); if (len > sizeof (static_wrappers) / sizeof (jstring_wrapper)) diff --git a/src/native/shared/cpp-util.hh b/src/native/shared/cpp-util.hh index 160fa844e36..8e83c409e85 100644 --- a/src/native/shared/cpp-util.hh +++ b/src/native/shared/cpp-util.hh @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -14,6 +15,7 @@ #include "helpers.hh" + static inline void do_abort_unless (const char* fmt, ...) { @@ -27,13 +29,51 @@ do_abort_unless (const char* fmt, ...) xamarin::android::Helpers::abort_application (n == -1 ? "Unable to allocate memory for abort message" : message); } -#define abort_unless(_condition_, _fmt_, ...) \ - if (!(_condition_)) [[unlikely]] { \ - do_abort_unless ("%s:%d (%s): " _fmt_, __FILE__, __LINE__, __FUNCTION__, ## __VA_ARGS__); \ +// #define abort_unless(_condition_, _fmt_, ...) \ +// if (!(_condition_)) [[unlikely]] { \ +// do_abort_unless ("%s:%d (%s): " _fmt_, __FILE__, __LINE__, __FUNCTION__, ## __VA_ARGS__); \ +// } + +template F> +[[gnu::always_inline, gnu::flatten]] +static inline void +abort_unless (bool condition, F&& get_message, std::source_location sloc = std::source_location::current ()) noexcept +{ + if (condition) [[likely]] { + return; } -#define abort_if_invalid_pointer_argument(_ptr_) abort_unless ((_ptr_) != nullptr, "Parameter '%s' must be a valid pointer", #_ptr_) -#define abort_if_negative_integer_argument(_arg_) abort_unless ((_arg_) > 0, "Parameter '%s' must be larger than 0", #_arg_) +// static_assert (std::is_same, char*>::value, "get_message must return 'char*'"); + xamarin::android::Helpers::abort_application (std::invoke (get_message), true /* log_location */, sloc); +} + +[[gnu::always_inline, gnu::flatten]] +static inline void +abort_unless (bool condition, const char *message, std::source_location sloc = std::source_location::current ()) noexcept +{ + if (condition) [[likely]] { + return; + } + xamarin::android::Helpers::abort_application (message, true /* log_location */, sloc); +} + +// #define abort_if_invalid_pointer_argument(_ptr_) abort_unless ((_ptr_) != nullptr, "Parameter '%s' must be a valid pointer", #_ptr_) +// #define abort_if_negative_integer_argument(_arg_) abort_unless ((_arg_) > 0, "Parameter '%s' must be larger than 0", #_arg_) + +template +[[gnu::always_inline, gnu::flatten]] +static inline void +abort_if_invalid_pointer_argument (T *ptr, const char *ptr_name, std::source_location sloc = std::source_location::current ()) noexcept +{ + abort_unless (ptr != nullptr, "Parameter '%s' must be a valid pointer", sloc); +} + +[[gnu::always_inline, gnu::flatten]] +static inline void +abort_if_negative_integer_argument (int arg, const char *arg_name, std::source_location sloc = std::source_location::current ()) noexcept +{ + abort_unless (arg > 0, "Parameter '%s' must be a valid pointer", sloc); +} // Helper to use in "printf debugging". Normally not used in code anywhere. No code should be shipped with any // of the calls present. From 0d4b21b8071bda3b14549773eac4834ebd7e561e Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Mon, 4 Nov 2024 20:55:16 +0100 Subject: [PATCH 29/54] More consistent use of std::string_view + remove unused code --- src/native/monodroid/embedded-assemblies.hh | 17 +++-- src/native/monodroid/monodroid-glue.cc | 7 +- src/native/monodroid/osbridge.cc | 6 +- src/native/runtime-base/shared-constants.hh | 5 +- src/native/runtime-base/util.hh | 23 ------- src/native/shared/cpp-util.hh | 72 +++++++-------------- 6 files changed, 47 insertions(+), 83 deletions(-) diff --git a/src/native/monodroid/embedded-assemblies.hh b/src/native/monodroid/embedded-assemblies.hh index cfaaf4b9e40..6aad3fd223b 100644 --- a/src/native/monodroid/embedded-assemblies.hh +++ b/src/native/monodroid/embedded-assemblies.hh @@ -88,23 +88,28 @@ namespace xamarin::android::internal { static constexpr std::string_view zip_path_separator { "/" }; static constexpr std::string_view apk_lib_dir_name { "lib" }; + static constexpr size_t assemblies_prefix_size = calc_size(apk_lib_dir_name, zip_path_separator, SharedConstants::android_lib_abi, zip_path_separator); - static constexpr auto assemblies_prefix = concat_string_views (apk_lib_dir_name, zip_path_separator, SharedConstants::android_lib_abi, zip_path_separator); + static constexpr auto assemblies_prefix_array = concat_string_views (apk_lib_dir_name, zip_path_separator, SharedConstants::android_lib_abi, zip_path_separator); + static constexpr std::string_view assemblies_prefix { assemblies_prefix_array }; // We have two records for each assembly, for names with and without the extension static constexpr uint32_t assembly_store_index_entries_per_assembly = 2; static constexpr uint32_t number_of_assembly_store_files = 1; static constexpr std::string_view dso_suffix { ".so" }; - static constexpr auto apk_lib_prefix = assemblies_prefix; // concat_const (apk_lib_dir_name, zip_path_separator, SharedConstants::android_lib_abi, zip_path_separator); + static constexpr std::string_view apk_lib_prefix = assemblies_prefix; // concat_const (apk_lib_dir_name, zip_path_separator, SharedConstants::android_lib_abi, zip_path_separator); static constexpr std::string_view assembly_store_prefix { "libassemblies." }; static constexpr std::string_view assembly_store_extension { ".blob" }; static constexpr size_t assembly_store_file_name_size = calc_size (assembly_store_prefix, SharedConstants::android_lib_abi, assembly_store_extension, dso_suffix); - static constexpr auto assembly_store_file_name = concat_string_views (assembly_store_prefix, SharedConstants::android_lib_abi, assembly_store_extension, dso_suffix); + static constexpr auto assembly_store_file_name_array = concat_string_views (assembly_store_prefix, SharedConstants::android_lib_abi, assembly_store_extension, dso_suffix); + static constexpr std::string_view assembly_store_file_name { assembly_store_file_name_array }; static constexpr size_t assembly_store_file_path_size = calc_size(apk_lib_dir_name, zip_path_separator, SharedConstants::android_lib_abi, zip_path_separator, assembly_store_prefix, SharedConstants::android_lib_abi, assembly_store_extension, dso_suffix); - static constexpr auto assembly_store_file_path = concat_string_views (apk_lib_dir_name, zip_path_separator, SharedConstants::android_lib_abi, zip_path_separator, assembly_store_prefix, SharedConstants::android_lib_abi, assembly_store_extension, dso_suffix); + static constexpr auto assembly_store_file_path_array = concat_string_views (apk_lib_dir_name, zip_path_separator, SharedConstants::android_lib_abi, zip_path_separator, assembly_store_prefix, SharedConstants::android_lib_abi, assembly_store_extension, dso_suffix); + static constexpr std::string_view assembly_store_file_path { assembly_store_file_path_array }; + static constexpr size_t dso_size_overhead = ArchiveDSOStubConfig::PayloadSectionOffset + (ArchiveDSOStubConfig::SectionHeaderEntryCount * ArchiveDSOStubConfig::SectionHeaderEntrySize); public: @@ -162,8 +167,8 @@ namespace xamarin::android::internal { abort_unless ( runtime_config_data_size < std::numeric_limits::max (), [] { - return Util::monodroid_strdup_printf ("Runtime config binary blob size exceeds %u bytes", - std::numeric_limits::max ()); + return detail::_format_message ("Runtime config binary blob size exceeds %u bytes", + std::numeric_limits::max ()); } ); size = static_cast(runtime_config_data_size); diff --git a/src/native/monodroid/monodroid-glue.cc b/src/native/monodroid/monodroid-glue.cc index a4d92ba1461..09a4dba28f2 100644 --- a/src/native/monodroid/monodroid-glue.cc +++ b/src/native/monodroid/monodroid-glue.cc @@ -915,7 +915,10 @@ MonodroidRuntime::init_android_runtime (JNIEnv *env, jclass runtimeClass, jobjec abort_unless ( registerType != nullptr, [&error] { - return Util::monodroid_strdup_printf("INTERNAL ERROR: Unable to find Android.Runtime.JNIEnvInit.RegisterJniNatives! %s", mono_error_get_message (&error)); + return detail::_format_message ( + "INTERNAL ERROR: Unable to find Android.Runtime.JNIEnvInit.RegisterJniNatives! %s", + mono_error_get_message (&error) + ); } ); @@ -943,7 +946,7 @@ MonodroidRuntime::init_android_runtime (JNIEnv *env, jclass runtimeClass, jobjec abort_unless ( initialize != nullptr, [&error] { - return Util::monodroid_strdup_printf ( + return detail::_format_message ( "Failed to obtain unmanaged-callers-only pointer to the Android.Runtime.JNIEnvInit.Initialize method. %s", mono_error_get_message (&error) ); diff --git a/src/native/monodroid/osbridge.cc b/src/native/monodroid/osbridge.cc index cc900a30906..d2725d278e2 100644 --- a/src/native/monodroid/osbridge.cc +++ b/src/native/monodroid/osbridge.cc @@ -865,9 +865,7 @@ OSBridge::gc_cleanup_after_java_collection (JNIEnv *env, int num_sccs, MonoGCBri if (j > 0) { abort_unless ( sccs [i]->is_alive, - [&i] { - return Util::monodroid_strdup_printf ("Bridge SCC at index %d must be alive", i); - } + [&i] { return detail::_format_message ("Bridge SCC at index %d must be alive", i); } ); } sccs [i]->is_alive = 1; @@ -893,7 +891,7 @@ OSBridge::gc_cleanup_after_java_collection (JNIEnv *env, int num_sccs, MonoGCBri } else { abort_unless ( !sccs [i]->is_alive, - [&i] { return Util::monodroid_strdup_printf ("Bridge SCC at index %d must NOT be alive", i); } + [&i] { return detail::_format_message ("Bridge SCC at index %d must NOT be alive", i); } ); } } diff --git a/src/native/runtime-base/shared-constants.hh b/src/native/runtime-base/shared-constants.hh index 001a53651e9..a3355963b59 100644 --- a/src/native/runtime-base/shared-constants.hh +++ b/src/native/runtime-base/shared-constants.hh @@ -40,10 +40,13 @@ namespace xamarin::android::internal static constexpr std::string_view DLL_EXTENSION { ".dll" }; static constexpr std::string_view PDB_EXTENSION { ".pdb" }; + private: static constexpr std::string_view RUNTIME_CONFIG_BLOB_BASE_NAME { "libarc.bin" }; static constexpr size_t runtime_config_blob_name_size = calc_size (RUNTIME_CONFIG_BLOB_BASE_NAME, MANGLED_ASSEMBLY_NAME_EXT); - static constexpr auto RUNTIME_CONFIG_BLOB_NAME = concat_string_views (RUNTIME_CONFIG_BLOB_BASE_NAME, MANGLED_ASSEMBLY_NAME_EXT); + static constexpr auto RUNTIME_CONFIG_BLOB_NAME_ARRAY = concat_string_views (RUNTIME_CONFIG_BLOB_BASE_NAME, MANGLED_ASSEMBLY_NAME_EXT); + public: + static constexpr std::string_view RUNTIME_CONFIG_BLOB_NAME { RUNTIME_CONFIG_BLOB_NAME_ARRAY }; static constexpr std::string_view MONO_SGEN_SO { "libmonosgen-2.0.so" }; static constexpr std::string_view MONO_SGEN_ARCH_SO { "libmonosgen-" __BITNESS__ "-2.0.so" }; static constexpr std::string_view OVERRIDE_DIRECTORY_NAME { ".__override__" }; diff --git a/src/native/runtime-base/util.hh b/src/native/runtime-base/util.hh index 8dd7f432664..97db495dbea 100644 --- a/src/native/runtime-base/util.hh +++ b/src/native/runtime-base/util.hh @@ -47,9 +47,6 @@ namespace xamarin::android { class Util { - static constexpr std::array hex_chars = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; - static constexpr uint32_t ms_in_nsec = 1000000ULL; - public: static void initialize () noexcept; @@ -197,13 +194,6 @@ namespace xamarin::android return p != nullptr && p [N - 1] == '\0'; } - template - static bool ends_with (const char *str, helper_char_array const& end) noexcept - { - char *p = const_cast (strstr (str, end.data ())); - return p != nullptr && p [N - 1] == '\0'; - } - template static bool ends_with (internal::string_base const& str, const char (&end)[N]) noexcept { @@ -230,19 +220,6 @@ namespace xamarin::android return memcmp (str.get () + len - end_length, end.data (), end_length) == 0; } - template - static bool ends_with (internal::string_base const& str, helper_char_array const& end) noexcept - { - constexpr size_t end_length = N - 1uz; - - size_t len = str.length (); - if (len < end_length) [[unlikely]] { - return false; - } - - return memcmp (str.get () + len - end_length, end.data (), end_length) == 0; - } - template static const TChar* find_last (internal::string_base const& str, const char ch) noexcept { diff --git a/src/native/shared/cpp-util.hh b/src/native/shared/cpp-util.hh index 8e83c409e85..f893d6614e3 100644 --- a/src/native/shared/cpp-util.hh +++ b/src/native/shared/cpp-util.hh @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -15,35 +16,33 @@ #include "helpers.hh" +namespace xamarin::android::detail { + [[gnu::always_inline, gnu::flatten]] + static inline const char* + _format_message (const char *format, ...) noexcept + { + va_list ap; + va_start (ap, format); -static inline void -do_abort_unless (const char* fmt, ...) -{ - va_list ap; - - va_start (ap, fmt); - char *message = nullptr; - int n = vasprintf (&message, fmt, ap); - va_end (ap); + char *message; + int ret = vasprintf (&message, format, ap); - xamarin::android::Helpers::abort_application (n == -1 ? "Unable to allocate memory for abort message" : message); + va_end (ap); + return ret == -1 ? "Out of memory" : message; + } } -// #define abort_unless(_condition_, _fmt_, ...) \ -// if (!(_condition_)) [[unlikely]] { \ -// do_abort_unless ("%s:%d (%s): " _fmt_, __FILE__, __LINE__, __FUNCTION__, ## __VA_ARGS__); \ -// } - template F> [[gnu::always_inline, gnu::flatten]] static inline void abort_unless (bool condition, F&& get_message, std::source_location sloc = std::source_location::current ()) noexcept { + static_assert (std::is_same::type, const char*>::value, "get_message must return 'const char*'"); + if (condition) [[likely]] { return; } -// static_assert (std::is_same, char*>::value, "get_message must return 'char*'"); xamarin::android::Helpers::abort_application (std::invoke (get_message), true /* log_location */, sloc); } @@ -57,22 +56,27 @@ abort_unless (bool condition, const char *message, std::source_location sloc = s xamarin::android::Helpers::abort_application (message, true /* log_location */, sloc); } -// #define abort_if_invalid_pointer_argument(_ptr_) abort_unless ((_ptr_) != nullptr, "Parameter '%s' must be a valid pointer", #_ptr_) -// #define abort_if_negative_integer_argument(_arg_) abort_unless ((_arg_) > 0, "Parameter '%s' must be larger than 0", #_arg_) - template [[gnu::always_inline, gnu::flatten]] static inline void abort_if_invalid_pointer_argument (T *ptr, const char *ptr_name, std::source_location sloc = std::source_location::current ()) noexcept { - abort_unless (ptr != nullptr, "Parameter '%s' must be a valid pointer", sloc); + abort_unless ( + ptr != nullptr, + [&ptr_name] { return xamarin::android::detail::_format_message ("Parameter '%s' must be a valid pointer", ptr_name); }, + sloc + ); } [[gnu::always_inline, gnu::flatten]] static inline void abort_if_negative_integer_argument (int arg, const char *arg_name, std::source_location sloc = std::source_location::current ()) noexcept { - abort_unless (arg > 0, "Parameter '%s' must be a valid pointer", sloc); + abort_unless ( + arg > 0, + [&arg_name] { return xamarin::android::detail::_format_message ("Parameter '%s' must be a valid pointer", arg_name); }, + sloc + ); } // Helper to use in "printf debugging". Normally not used in code anywhere. No code should be shipped with any @@ -106,32 +110,6 @@ namespace xamarin::android template using c_unique_ptr = std::unique_ptr>; - template - struct helper_char_array final - { - constexpr char* data () noexcept - { - return _elems; - } - - constexpr const char* data () const noexcept - { - return _elems; - } - - constexpr char const& operator[] (size_t n) const noexcept - { - return _elems[n]; - } - - constexpr char& operator[] (size_t n) noexcept - { - return _elems[n]; - } - - char _elems[Size]{}; - }; - template using char_array = std::array; From 7db3b37d3c615cd5e1a4be8a31a1b943a38dd2d8 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Thu, 7 Nov 2024 14:13:30 +0100 Subject: [PATCH 30/54] Making EmbeddedAssemblies a static type In process to remove object instances for a slightly faster startup --- .../monodroid/embedded-assemblies-zip.cc | 20 +-- src/native/monodroid/embedded-assemblies.cc | 14 +- src/native/monodroid/embedded-assemblies.hh | 140 +++++++++--------- src/native/monodroid/monodroid-glue.cc | 2 +- 4 files changed, 87 insertions(+), 89 deletions(-) diff --git a/src/native/monodroid/embedded-assemblies-zip.cc b/src/native/monodroid/embedded-assemblies-zip.cc index 3f91b71dc9a..82a56859d88 100644 --- a/src/native/monodroid/embedded-assemblies-zip.cc +++ b/src/native/monodroid/embedded-assemblies-zip.cc @@ -298,7 +298,7 @@ EmbeddedAssemblies::zip_load_assembly_store_entries (std::vector const& } void -EmbeddedAssemblies::zip_load_entries (int fd, const char *apk_name, [[maybe_unused]] monodroid_should_register should_register) +EmbeddedAssemblies::zip_load_entries (int fd, const char *apk_name, [[maybe_unused]] monodroid_should_register should_register) noexcept { uint32_t cd_offset; uint32_t cd_size; @@ -412,7 +412,7 @@ EmbeddedAssemblies::set_debug_entry_data (XamarinAndroidBundledAssembly &entry, } bool -EmbeddedAssemblies::zip_read_cd_info (int fd, uint32_t& cd_offset, uint32_t& cd_size, uint16_t& cd_entries) +EmbeddedAssemblies::zip_read_cd_info (int fd, uint32_t& cd_offset, uint32_t& cd_size, uint16_t& cd_entries) noexcept { // The simplest case - no file comment off_t ret = ::lseek (fd, -ZIP_EOCD_LEN, SEEK_END); @@ -478,7 +478,7 @@ EmbeddedAssemblies::zip_read_cd_info (int fd, uint32_t& cd_offset, uint32_t& cd_ } bool -EmbeddedAssemblies::zip_adjust_data_offset (int fd, ZipEntryLoadState &state) +EmbeddedAssemblies::zip_adjust_data_offset (int fd, ZipEntryLoadState &state) noexcept { static constexpr size_t LH_FILE_NAME_LENGTH_OFFSET = 26uz; static constexpr size_t LH_EXTRA_LENGTH_OFFSET = 28uz; @@ -530,7 +530,7 @@ EmbeddedAssemblies::zip_adjust_data_offset (int fd, ZipEntryLoadState &state) template bool -EmbeddedAssemblies::zip_extract_cd_info (std::array const& buf, uint32_t& cd_offset, uint32_t& cd_size, uint16_t& cd_entries) +EmbeddedAssemblies::zip_extract_cd_info (std::array const& buf, uint32_t& cd_offset, uint32_t& cd_size, uint16_t& cd_entries) noexcept { constexpr size_t EOCD_TOTAL_ENTRIES_OFFSET = 10uz; constexpr size_t EOCD_CD_SIZE_OFFSET = 12uz; @@ -558,7 +558,7 @@ EmbeddedAssemblies::zip_extract_cd_info (std::array const& buf template force_inline bool -EmbeddedAssemblies::zip_ensure_valid_params (T const& buf, size_t index, size_t to_read) const noexcept +EmbeddedAssemblies::zip_ensure_valid_params (T const& buf, size_t index, size_t to_read) noexcept { if (index + to_read > buf.size ()) { log_error (LOG_ASSEMBLY, "Buffer too short to read %u bytes of data", to_read); @@ -570,7 +570,7 @@ EmbeddedAssemblies::zip_ensure_valid_params (T const& buf, size_t index, size_t template bool -EmbeddedAssemblies::zip_read_field (T const& src, size_t source_index, uint16_t& dst) const noexcept +EmbeddedAssemblies::zip_read_field (T const& src, size_t source_index, uint16_t& dst) noexcept { if (!zip_ensure_valid_params (src, source_index, sizeof (dst))) { return false; @@ -583,7 +583,7 @@ EmbeddedAssemblies::zip_read_field (T const& src, size_t source_index, uint16_t& template bool -EmbeddedAssemblies::zip_read_field (T const& src, size_t source_index, uint32_t& dst) const noexcept +EmbeddedAssemblies::zip_read_field (T const& src, size_t source_index, uint32_t& dst) noexcept { if (!zip_ensure_valid_params (src, source_index, sizeof (dst))) { return false; @@ -600,7 +600,7 @@ EmbeddedAssemblies::zip_read_field (T const& src, size_t source_index, uint32_t& template bool -EmbeddedAssemblies::zip_read_field (T const& src, size_t source_index, std::array& dst_sig) const noexcept +EmbeddedAssemblies::zip_read_field (T const& src, size_t source_index, std::array& dst_sig) noexcept { if (!zip_ensure_valid_params (src, source_index, dst_sig.size ())) { return false; @@ -612,7 +612,7 @@ EmbeddedAssemblies::zip_read_field (T const& src, size_t source_index, std::arra template bool -EmbeddedAssemblies::zip_read_field (T const& buf, size_t index, size_t count, dynamic_local_string& characters) const noexcept +EmbeddedAssemblies::zip_read_field (T const& buf, size_t index, size_t count, dynamic_local_string& characters) noexcept { if (!zip_ensure_valid_params (buf, index, count)) { return false; @@ -623,7 +623,7 @@ EmbeddedAssemblies::zip_read_field (T const& buf, size_t index, size_t count, dy } bool -EmbeddedAssemblies::zip_read_entry_info (std::vector const& buf, dynamic_local_string& file_name, ZipEntryLoadState &state) +EmbeddedAssemblies::zip_read_entry_info (std::vector const& buf, dynamic_local_string& file_name, ZipEntryLoadState &state) noexcept { constexpr size_t CD_COMPRESSION_METHOD_OFFSET = 10uz; constexpr size_t CD_UNCOMPRESSED_SIZE_OFFSET = 24uz; diff --git a/src/native/monodroid/embedded-assemblies.cc b/src/native/monodroid/embedded-assemblies.cc index 6a20df0bc59..f5855dfd832 100644 --- a/src/native/monodroid/embedded-assemblies.cc +++ b/src/native/monodroid/embedded-assemblies.cc @@ -65,7 +65,7 @@ class MonoGuidString final char *guid = nullptr; }; -void EmbeddedAssemblies::set_assemblies_prefix (const char *prefix) +void EmbeddedAssemblies::set_assemblies_prefix (const char *prefix) noexcept { if (assemblies_prefix_override != nullptr) delete[] assemblies_prefix_override; @@ -912,7 +912,7 @@ EmbeddedAssemblies::md_mmap_apk_file (int fd, uint32_t offset, size_t size, cons } void -EmbeddedAssemblies::gather_bundled_assemblies_from_apk (const char* apk, monodroid_should_register should_register) +EmbeddedAssemblies::gather_bundled_assemblies_from_apk (const char* apk, monodroid_should_register should_register) noexcept { int fd; @@ -1284,12 +1284,10 @@ EmbeddedAssemblies::register_from_filesystem (const char *lib_dir_path,bool look } auto register_fn = - application_config.have_assembly_store ? std::mem_fn (&EmbeddedAssemblies::maybe_register_blob_from_filesystem) : + application_config.have_assembly_store ? &EmbeddedAssemblies::maybe_register_blob_from_filesystem : (look_for_mangled_names ? - std::mem_fn (&EmbeddedAssemblies::maybe_register_assembly_from_filesystem) : - std::mem_fn (&EmbeddedAssemblies::maybe_register_assembly_from_filesystem - ) - ); + &EmbeddedAssemblies::maybe_register_assembly_from_filesystem : + &EmbeddedAssemblies::maybe_register_assembly_from_filesystem); size_t assembly_count = 0uz; do { @@ -1334,7 +1332,7 @@ EmbeddedAssemblies::register_from_filesystem (const char *lib_dir_path,bool look } // We get `true` if it's time to terminate - if (register_fn (this, should_register, assembly_count, cur, state)) { + if (register_fn (should_register, assembly_count, cur, state)) { break; } } while (true); diff --git a/src/native/monodroid/embedded-assemblies.hh b/src/native/monodroid/embedded-assemblies.hh index 6aad3fd223b..1ac42b9d1de 100644 --- a/src/native/monodroid/embedded-assemblies.hh +++ b/src/native/monodroid/embedded-assemblies.hh @@ -130,14 +130,14 @@ namespace xamarin::android::internal { /* returns current number of *all* assemblies found from all invocations */ template - size_t register_from_apk (const char *apk_file) noexcept + static size_t register_from_apk (const char *apk_file) noexcept { static_assert (should_register_fn != nullptr, "should_register_fn is a required template parameter"); return register_from_apk (apk_file, should_register_fn); } template - size_t register_from_filesystem () noexcept + static size_t register_from_filesystem () noexcept { static_assert (should_register_fn != nullptr, "should_register_fn is a required template parameter"); return register_from_filesystem (should_register_fn); @@ -148,19 +148,19 @@ namespace xamarin::android::internal { return assemblies_prefix; } - bool get_register_debug_symbols () const + static bool get_register_debug_symbols () noexcept { return register_debug_symbols; } - void set_register_debug_symbols (bool value) + static void set_register_debug_symbols (bool value) noexcept { register_debug_symbols = value; } - void set_assemblies_prefix (const char *prefix); + static void set_assemblies_prefix (const char *prefix) noexcept; - void get_runtime_config_blob (const char *& area, uint32_t& size) const + static void get_runtime_config_blob (const char *& area, uint32_t& size) noexcept { area = static_cast(runtime_config_data); @@ -174,7 +174,7 @@ namespace xamarin::android::internal { size = static_cast(runtime_config_data_size); } - void unmap_runtime_config_blob () + static void unmap_runtime_config_blob () noexcept { if (runtime_config_blob_mmap.area == nullptr) { return; @@ -185,17 +185,17 @@ namespace xamarin::android::internal { runtime_config_blob_mmap.size = 0; } - bool have_runtime_config_blob () const noexcept + static bool have_runtime_config_blob () noexcept { return application_config.have_runtime_config_blob && runtime_config_blob_mmap.area != nullptr; } - bool keep_scanning () const noexcept + static bool keep_scanning () noexcept { return need_to_scan_more_apks; } - void ensure_valid_assembly_stores () const noexcept + static void ensure_valid_assembly_stores () noexcept { if (!application_config.have_assembly_store) { return; @@ -207,32 +207,32 @@ namespace xamarin::android::internal { private: STATIC_IN_ANDROID_RELEASE const char* typemap_managed_to_java (MonoType *type, MonoClass *klass, const uint8_t *mvid) noexcept; STATIC_IN_ANDROID_RELEASE MonoReflectionType* typemap_java_to_managed (hash_t hash, const MonoString *java_type_name) noexcept; - size_t register_from_apk (const char *apk_file, monodroid_should_register should_register) noexcept; - size_t register_from_filesystem (monodroid_should_register should_register) noexcept; - size_t register_from_filesystem (const char *dir, bool look_for_mangled_names, monodroid_should_register should_register) noexcept; + static size_t register_from_apk (const char *apk_file, monodroid_should_register should_register) noexcept; + static size_t register_from_filesystem (monodroid_should_register should_register) noexcept; + static size_t register_from_filesystem (const char *dir, bool look_for_mangled_names, monodroid_should_register should_register) noexcept; template - bool maybe_register_assembly_from_filesystem (monodroid_should_register should_register, size_t& assembly_count, const dirent* dir_entry, ZipEntryLoadState& state) noexcept; - bool maybe_register_blob_from_filesystem (monodroid_should_register should_register, size_t& assembly_count, const dirent* dir_entry, ZipEntryLoadState& state) noexcept; + static bool maybe_register_assembly_from_filesystem (monodroid_should_register should_register, size_t& assembly_count, const dirent* dir_entry, ZipEntryLoadState& state) noexcept; + static bool maybe_register_blob_from_filesystem (monodroid_should_register should_register, size_t& assembly_count, const dirent* dir_entry, ZipEntryLoadState& state) noexcept; - void gather_bundled_assemblies_from_apk (const char* apk, monodroid_should_register should_register); + static void gather_bundled_assemblies_from_apk (const char* apk, monodroid_should_register should_register) noexcept; template - MonoAssembly* individual_assemblies_open_from_bundles (dynamic_local_string& name, TLoaderData loader_data, bool ref_only) noexcept; + static MonoAssembly* individual_assemblies_open_from_bundles (dynamic_local_string& name, TLoaderData loader_data, bool ref_only) noexcept; template - MonoAssembly* assembly_store_open_from_bundles (dynamic_local_string& name, TLoaderData loader_data, bool ref_only) noexcept; + static MonoAssembly* assembly_store_open_from_bundles (dynamic_local_string& name, TLoaderData loader_data, bool ref_only) noexcept; template - MonoAssembly* open_from_bundles (MonoAssemblyName* aname, TLoaderData loader_data, MonoError *error, bool ref_only) noexcept; + static MonoAssembly* open_from_bundles (MonoAssemblyName* aname, TLoaderData loader_data, MonoError *error, bool ref_only) noexcept; template - void map_runtime_file (XamarinAndroidBundledAssembly& file) noexcept; - void map_assembly (XamarinAndroidBundledAssembly& file) noexcept; - void map_debug_data (XamarinAndroidBundledAssembly& file) noexcept; + static void map_runtime_file (XamarinAndroidBundledAssembly& file) noexcept; + static void map_assembly (XamarinAndroidBundledAssembly& file) noexcept; + static void map_debug_data (XamarinAndroidBundledAssembly& file) noexcept; template - MonoAssembly* load_bundled_assembly ( + static MonoAssembly* load_bundled_assembly ( XamarinAndroidBundledAssembly& assembly, dynamic_local_string const& name, dynamic_local_string const& abi_name, @@ -254,37 +254,37 @@ namespace xamarin::android::internal { static MonoAssembly* open_from_bundles_full (MonoAssemblyName *aname, char **assemblies_path, void *user_data); static MonoAssembly* open_from_bundles (MonoAssemblyLoadContextGCHandle alc_gchandle, MonoAssemblyName *aname, char **assemblies_path, void *user_data, MonoError *error); - void set_assembly_data_and_size (uint8_t* source_assembly_data, uint32_t source_assembly_data_size, uint8_t*& dest_assembly_data, uint32_t& dest_assembly_data_size) noexcept; - void get_assembly_data (uint8_t *data, uint32_t data_size, const char *name, uint8_t*& assembly_data, uint32_t& assembly_data_size) noexcept; - void get_assembly_data (XamarinAndroidBundledAssembly const& e, uint8_t*& assembly_data, uint32_t& assembly_data_size) noexcept; - void get_assembly_data (AssemblyStoreSingleAssemblyRuntimeData const& e, uint8_t*& assembly_data, uint32_t& assembly_data_size) noexcept; + static void set_assembly_data_and_size (uint8_t* source_assembly_data, uint32_t source_assembly_data_size, uint8_t*& dest_assembly_data, uint32_t& dest_assembly_data_size) noexcept; + static void get_assembly_data (uint8_t *data, uint32_t data_size, const char *name, uint8_t*& assembly_data, uint32_t& assembly_data_size) noexcept; + static void get_assembly_data (XamarinAndroidBundledAssembly const& e, uint8_t*& assembly_data, uint32_t& assembly_data_size) noexcept; + static void get_assembly_data (AssemblyStoreSingleAssemblyRuntimeData const& e, uint8_t*& assembly_data, uint32_t& assembly_data_size) noexcept; - void zip_load_entries (int fd, const char *apk_name, monodroid_should_register should_register); - void zip_load_individual_assembly_entries (std::vector const& buf, uint32_t num_entries, monodroid_should_register should_register, ZipEntryLoadState &state) noexcept; - void zip_load_assembly_store_entries (std::vector const& buf, uint32_t num_entries, ZipEntryLoadState &state) noexcept; - bool zip_load_entry_common (size_t entry_index, std::vector const& buf, dynamic_local_string &entry_name, ZipEntryLoadState &state) noexcept; - bool zip_read_cd_info (int fd, uint32_t& cd_offset, uint32_t& cd_size, uint16_t& cd_entries); - bool zip_adjust_data_offset (int fd, ZipEntryLoadState &state); + static void zip_load_entries (int fd, const char *apk_name, monodroid_should_register should_register) noexcept; + static void zip_load_individual_assembly_entries (std::vector const& buf, uint32_t num_entries, monodroid_should_register should_register, ZipEntryLoadState &state) noexcept; + static void zip_load_assembly_store_entries (std::vector const& buf, uint32_t num_entries, ZipEntryLoadState &state) noexcept; + static bool zip_load_entry_common (size_t entry_index, std::vector const& buf, dynamic_local_string &entry_name, ZipEntryLoadState &state) noexcept; + static bool zip_read_cd_info (int fd, uint32_t& cd_offset, uint32_t& cd_size, uint16_t& cd_entries) noexcept; + static bool zip_adjust_data_offset (int fd, ZipEntryLoadState &state) noexcept; template - bool zip_extract_cd_info (std::array const& buf, uint32_t& cd_offset, uint32_t& cd_size, uint16_t& cd_entries); + static bool zip_extract_cd_info (std::array const& buf, uint32_t& cd_offset, uint32_t& cd_size, uint16_t& cd_entries) noexcept; template - bool zip_ensure_valid_params (T const& buf, size_t index, size_t to_read) const noexcept; + static bool zip_ensure_valid_params (T const& buf, size_t index, size_t to_read) noexcept; template - bool zip_read_field (T const& src, size_t source_index, uint16_t& dst) const noexcept; + static bool zip_read_field (T const& src, size_t source_index, uint16_t& dst) noexcept; template - bool zip_read_field (T const& src, size_t source_index, uint32_t& dst) const noexcept; + static bool zip_read_field (T const& src, size_t source_index, uint32_t& dst) noexcept; template - bool zip_read_field (T const& src, size_t source_index, std::array& dst_sig) const noexcept; + static bool zip_read_field (T const& src, size_t source_index, std::array& dst_sig) noexcept; template - bool zip_read_field (T const& buf, size_t index, size_t count, dynamic_local_string& characters) const noexcept; + static bool zip_read_field (T const& buf, size_t index, size_t count, dynamic_local_string& characters) noexcept; - bool zip_read_entry_info (std::vector const& buf, dynamic_local_string& file_name, ZipEntryLoadState &state); + static bool zip_read_entry_info (std::vector const& buf, dynamic_local_string& file_name, ZipEntryLoadState &state) noexcept; [[gnu::always_inline]] static std::tuple get_wrapper_dso_payload_pointer_and_size (md_mmap_info const& map_info, const char *file_name) noexcept @@ -318,7 +318,7 @@ namespace xamarin::android::internal { } [[gnu::always_inline]] - void store_mapped_runtime_config_data (md_mmap_info const& map_info, const char *file_name) noexcept + static void store_mapped_runtime_config_data (md_mmap_info const& map_info, const char *file_name) noexcept { auto [payload_start, payload_size] = get_wrapper_dso_payload_pointer_and_size (map_info, file_name); log_debug (LOG_ASSEMBLY, "Runtime config: payload pointer %p ; size %zu", payload_start, payload_size); @@ -327,7 +327,7 @@ namespace xamarin::android::internal { runtime_config_blob_found = true; } - std::tuple get_assemblies_prefix_and_length () const noexcept + static std::tuple get_assemblies_prefix_and_length () noexcept { if (assemblies_prefix_override != nullptr) { return { assemblies_prefix_override, static_cast(strlen (assemblies_prefix_override)) }; @@ -340,7 +340,7 @@ namespace xamarin::android::internal { return {assemblies_prefix.data (), assemblies_prefix.size () - 1}; } - bool all_required_zip_entries_found () const noexcept + static bool all_required_zip_entries_found () noexcept { return number_of_mapped_assembly_stores == number_of_assembly_store_files && number_of_zip_dso_entries >= application_config.number_of_shared_libraries @@ -362,21 +362,21 @@ namespace xamarin::android::internal { static const TypeMapModuleEntry* binary_search (uint32_t key, const TypeMapModuleEntry *arr, uint32_t n) noexcept; #endif template - void set_entry_data (XamarinAndroidBundledAssembly &entry, ZipEntryLoadState const& state, dynamic_local_string const& entry_name) noexcept; - void set_assembly_entry_data (XamarinAndroidBundledAssembly &entry, ZipEntryLoadState const& state, dynamic_local_string const& entry_name) noexcept; - void set_debug_entry_data (XamarinAndroidBundledAssembly &entry, ZipEntryLoadState const& state, dynamic_local_string const& entry_name) noexcept; - void map_assembly_store (dynamic_local_string const& entry_name, ZipEntryLoadState &state) noexcept; - const AssemblyStoreIndexEntry* find_assembly_store_entry (hash_t hash, const AssemblyStoreIndexEntry *entries, size_t entry_count) noexcept; - void store_individual_assembly_data (dynamic_local_string const& entry_name, ZipEntryLoadState const& state, monodroid_should_register should_register) noexcept; - - constexpr size_t get_mangled_name_max_size_overhead () + static void set_entry_data (XamarinAndroidBundledAssembly &entry, ZipEntryLoadState const& state, dynamic_local_string const& entry_name) noexcept; + static void set_assembly_entry_data (XamarinAndroidBundledAssembly &entry, ZipEntryLoadState const& state, dynamic_local_string const& entry_name) noexcept; + static void set_debug_entry_data (XamarinAndroidBundledAssembly &entry, ZipEntryLoadState const& state, dynamic_local_string const& entry_name) noexcept; + static void map_assembly_store (dynamic_local_string const& entry_name, ZipEntryLoadState &state) noexcept; + static const AssemblyStoreIndexEntry* find_assembly_store_entry (hash_t hash, const AssemblyStoreIndexEntry *entries, size_t entry_count) noexcept; + static void store_individual_assembly_data (dynamic_local_string const& entry_name, ZipEntryLoadState const& state, monodroid_should_register should_register) noexcept; + + constexpr static size_t get_mangled_name_max_size_overhead () { return SharedConstants::MANGLED_ASSEMBLY_NAME_EXT.size() + std::max (SharedConstants::MANGLED_ASSEMBLY_REGULAR_ASSEMBLY_MARKER.size(), SharedConstants::MANGLED_ASSEMBLY_SATELLITE_ASSEMBLY_MARKER.size()) + 1; // For the extra `-` char in the culture portion of satellite assembly's name } - void configure_state_for_individual_assembly_load (ZipEntryLoadState& state) noexcept + static void configure_state_for_individual_assembly_load (ZipEntryLoadState& state) noexcept { state.bundled_assemblies_slow_path = bundled_assembly_index >= application_config.number_of_assemblies_in_apk; state.max_assembly_name_size = application_config.bundled_assembly_name_width - 1; @@ -430,13 +430,13 @@ namespace xamarin::android::internal { static inline constexpr bool UnmangleSatelliteAssembly = true; static inline constexpr bool UnmangleRegularAssembly = false; - std::vector *bundled_debug_data = nullptr; - std::vector *extra_bundled_assemblies = nullptr; + static inline std::vector *bundled_debug_data = nullptr; + static inline std::vector *extra_bundled_assemblies = nullptr; - bool register_debug_symbols; - bool have_and_want_debug_symbols; - size_t bundled_assembly_index = 0uz; - size_t number_of_found_assemblies = 0uz; + static inline bool register_debug_symbols; + static inline bool have_and_want_debug_symbols; + static inline size_t bundled_assembly_index = 0uz; + static inline size_t number_of_found_assemblies = 0uz; #if defined (DEBUG) TypeMappingInfo *java_to_managed_maps; @@ -444,18 +444,18 @@ namespace xamarin::android::internal { TypeMap *type_maps; size_t type_map_count; #endif // DEBUG - const char *assemblies_prefix_override = nullptr; - - md_mmap_info runtime_config_blob_mmap{}; - void *runtime_config_data = nullptr; - size_t runtime_config_data_size = 0uz; - bool runtime_config_blob_found = false; - uint32_t number_of_mapped_assembly_stores = 0u; - uint32_t number_of_zip_dso_entries = 0u; - bool need_to_scan_more_apks = true; - - AssemblyStoreIndexEntry *assembly_store_hashes; - xamarin::android::mutex assembly_decompress_mutex; + static inline const char *assemblies_prefix_override = nullptr; + + static inline md_mmap_info runtime_config_blob_mmap{}; + static inline void *runtime_config_data = nullptr; + static inline size_t runtime_config_data_size = 0uz; + static inline bool runtime_config_blob_found = false; + static inline uint32_t number_of_mapped_assembly_stores = 0u; + static inline uint32_t number_of_zip_dso_entries = 0u; + static inline bool need_to_scan_more_apks = true; + + static inline AssemblyStoreIndexEntry *assembly_store_hashes; + static inline xamarin::android::mutex assembly_decompress_mutex; }; } diff --git a/src/native/monodroid/monodroid-glue.cc b/src/native/monodroid/monodroid-glue.cc index 09a4dba28f2..d9eca63b7a4 100644 --- a/src/native/monodroid/monodroid-glue.cc +++ b/src/native/monodroid/monodroid-glue.cc @@ -256,7 +256,7 @@ MonodroidRuntime::gather_bundled_assemblies (jstring_array_wrapper &runtimeApks, } } - size_t cur_num_assemblies = embeddedAssemblies.register_from_apk (apk_file.get_cstr ()); + size_t cur_num_assemblies = EmbeddedAssemblies::register_from_apk (apk_file.get_cstr ()); *out_user_assemblies_count += (cur_num_assemblies - prev_num_assemblies); prev_num_assemblies = cur_num_assemblies; From a449f89edf43f175e8b6964a8eb29af05534f992 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Wed, 13 Nov 2024 10:39:59 -0800 Subject: [PATCH 31/54] More cleanup --- src/native/runtime-base/android-system.hh | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/native/runtime-base/android-system.hh b/src/native/runtime-base/android-system.hh index 3afe52debb3..4ff2afe982d 100644 --- a/src/native/runtime-base/android-system.hh +++ b/src/native/runtime-base/android-system.hh @@ -174,13 +174,15 @@ namespace xamarin::android::internal { static bool is_interpreter_enabled () noexcept { - return get_mono_aot_mode () == MonoAotMode::MONO_AOT_MODE_INTERP_ONLY; - } - - // Hack, see comment for `aot_mode_last_is_interpreter` at the bottom of the class declaration - static bool is_aot_mode_last_really_interpreter_mode () noexcept - { - return false; + switch (get_mono_aot_mode ()) { + case MonoAotMode::MONO_AOT_MODE_INTERP: + case MonoAotMode::MONO_AOT_MODE_INTERP_ONLY: + case MonoAotMode::MONO_AOT_MODE_INTERP_LLVMONLY: + return true; + + default: + return false; + } } static void set_running_in_emulator (bool yesno) noexcept From b95077d4dd8aa8af2e2aeb428985c545e59454cd Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Wed, 13 Nov 2024 10:58:18 -0800 Subject: [PATCH 32/54] More move to static, more cleanup --- src/native/monodroid/debug.cc | 2 +- src/native/monodroid/embedded-assemblies.cc | 10 ++++----- src/native/monodroid/embedded-assemblies.hh | 14 ++++++------ src/native/monodroid/globals.cc | 3 --- src/native/monodroid/globals.hh | 1 - src/native/monodroid/internal-pinvokes.cc | 2 +- src/native/monodroid/monodroid-glue.cc | 24 ++++++++++----------- 7 files changed, 26 insertions(+), 30 deletions(-) diff --git a/src/native/monodroid/debug.cc b/src/native/monodroid/debug.cc index add61468747..db787268f41 100644 --- a/src/native/monodroid/debug.cc +++ b/src/native/monodroid/debug.cc @@ -515,7 +515,7 @@ Debug::start_debugging (void) if (sdb_fd == 0) return; - embeddedAssemblies.set_register_debug_symbols (true); + EmbeddedAssemblies::set_register_debug_symbols (true); char *debug_arg = Util::monodroid_strdup_printf ("--debugger-agent=transport=socket-fd,address=%d,embedding=1", sdb_fd); std::array debug_options = { diff --git a/src/native/monodroid/embedded-assemblies.cc b/src/native/monodroid/embedded-assemblies.cc index f5855dfd832..db3704f160f 100644 --- a/src/native/monodroid/embedded-assemblies.cc +++ b/src/native/monodroid/embedded-assemblies.cc @@ -493,7 +493,7 @@ MonoAssembly* EmbeddedAssemblies::open_from_bundles (MonoAssemblyLoadContextGCHandle alc_gchandle, MonoAssemblyName *aname, [[maybe_unused]] char **assemblies_path, [[maybe_unused]] void *user_data, MonoError *error) { constexpr bool ref_only = false; - return embeddedAssemblies.open_from_bundles (aname, alc_gchandle, error, ref_only); + return EmbeddedAssemblies::open_from_bundles (aname, alc_gchandle, error, ref_only); } MonoAssembly* @@ -501,17 +501,17 @@ EmbeddedAssemblies::open_from_bundles_full (MonoAssemblyName *aname, [[maybe_unu { constexpr bool ref_only = false; - return embeddedAssemblies.open_from_bundles (aname, ref_only /* loader_data */, nullptr /* error */, ref_only); + return EmbeddedAssemblies::open_from_bundles (aname, ref_only /* loader_data */, nullptr /* error */, ref_only); } void -EmbeddedAssemblies::install_preload_hooks_for_appdomains () +EmbeddedAssemblies::install_preload_hooks_for_appdomains () noexcept { mono_install_assembly_preload_hook (open_from_bundles_full, nullptr); } void -EmbeddedAssemblies::install_preload_hooks_for_alc () +EmbeddedAssemblies::install_preload_hooks_for_alc () noexcept { mono_install_assembly_preload_hook_v3 ( open_from_bundles, @@ -679,7 +679,7 @@ EmbeddedAssemblies::typemap_java_to_managed (hash_t hash, const MonoString *java } else { MonoAssemblyLoadContextGCHandle alc_gchandle = mono_alc_get_default_gchandle (); MonoError mono_error; - assm = embeddedAssemblies.open_from_bundles (assembly_name, alc_gchandle, &mono_error, false /* ref_only */); + assm = EmbeddedAssemblies::open_from_bundles (assembly_name, alc_gchandle, &mono_error, false /* ref_only */); } if (assm == nullptr) { diff --git a/src/native/monodroid/embedded-assemblies.hh b/src/native/monodroid/embedded-assemblies.hh index 1ac42b9d1de..efaa296a0a7 100644 --- a/src/native/monodroid/embedded-assemblies.hh +++ b/src/native/monodroid/embedded-assemblies.hh @@ -122,11 +122,11 @@ namespace xamarin::android::internal { {} #endif // def RELEASE - STATIC_IN_ANDROID_RELEASE const char* typemap_managed_to_java (MonoReflectionType *type, const uint8_t *mvid) noexcept; + static const char* typemap_managed_to_java (MonoReflectionType *type, const uint8_t *mvid) noexcept; - void install_preload_hooks_for_appdomains (); - void install_preload_hooks_for_alc (); - STATIC_IN_ANDROID_RELEASE MonoReflectionType* typemap_java_to_managed (MonoString *java_type) noexcept; + static void install_preload_hooks_for_appdomains () noexcept; + static void install_preload_hooks_for_alc () noexcept; + static MonoReflectionType* typemap_java_to_managed (MonoString *java_type) noexcept; /* returns current number of *all* assemblies found from all invocations */ template @@ -205,8 +205,8 @@ namespace xamarin::android::internal { } private: - STATIC_IN_ANDROID_RELEASE const char* typemap_managed_to_java (MonoType *type, MonoClass *klass, const uint8_t *mvid) noexcept; - STATIC_IN_ANDROID_RELEASE MonoReflectionType* typemap_java_to_managed (hash_t hash, const MonoString *java_type_name) noexcept; + static const char* typemap_managed_to_java (MonoType *type, MonoClass *klass, const uint8_t *mvid) noexcept; + static MonoReflectionType* typemap_java_to_managed (hash_t hash, const MonoString *java_type_name) noexcept; static size_t register_from_apk (const char *apk_file, monodroid_should_register should_register) noexcept; static size_t register_from_filesystem (monodroid_should_register should_register) noexcept; static size_t register_from_filesystem (const char *dir, bool look_for_mangled_names, monodroid_should_register should_register) noexcept; @@ -247,7 +247,7 @@ namespace xamarin::android::internal { bool typemap_load_file (int dir_fd, const char *dir_path, const char *file_path, TypeMap &module); bool typemap_load_file (BinaryTypeMapHeader &header, const char *dir_path, const char *file_path, int file_fd, TypeMap &module); static ssize_t do_read (int fd, void *buf, size_t count); - const TypeMapEntry *typemap_managed_to_java (const char *managed_type_name) noexcept; + static const TypeMapEntry *typemap_managed_to_java (const char *managed_type_name) noexcept; #endif // DEBUG static md_mmap_info md_mmap_apk_file (int fd, uint32_t offset, size_t size, const char* filename); diff --git a/src/native/monodroid/globals.cc b/src/native/monodroid/globals.cc index eb1a2c87fe4..7822952f8f0 100644 --- a/src/native/monodroid/globals.cc +++ b/src/native/monodroid/globals.cc @@ -3,10 +3,7 @@ using namespace xamarin::android; using namespace xamarin::android::internal; -Util utils; -AndroidSystem androidSystem; OSBridge osBridge; -EmbeddedAssemblies embeddedAssemblies; MonodroidRuntime monodroidRuntime; Timing *timing = nullptr; diff --git a/src/native/monodroid/globals.hh b/src/native/monodroid/globals.hh index 7717ec2ec79..6f1649d9796 100644 --- a/src/native/monodroid/globals.hh +++ b/src/native/monodroid/globals.hh @@ -11,7 +11,6 @@ extern xamarin::android::Debug debug; extern xamarin::android::internal::OSBridge osBridge; -extern xamarin::android::internal::EmbeddedAssemblies embeddedAssemblies; extern xamarin::android::internal::MonodroidRuntime monodroidRuntime; extern xamarin::android::Timing *timing; diff --git a/src/native/monodroid/internal-pinvokes.cc b/src/native/monodroid/internal-pinvokes.cc index 0df3d868715..2324084a3f7 100644 --- a/src/native/monodroid/internal-pinvokes.cc +++ b/src/native/monodroid/internal-pinvokes.cc @@ -21,7 +21,7 @@ monodroid_get_system_property (const char *name, char **value) int monodroid_embedded_assemblies_set_assemblies_prefix (const char *prefix) { - embeddedAssemblies.set_assemblies_prefix (prefix); + EmbeddedAssemblies::set_assemblies_prefix (prefix); return 0; } diff --git a/src/native/monodroid/monodroid-glue.cc b/src/native/monodroid/monodroid-glue.cc index d9eca63b7a4..d40d9b264ae 100644 --- a/src/native/monodroid/monodroid-glue.cc +++ b/src/native/monodroid/monodroid-glue.cc @@ -228,7 +228,7 @@ inline void MonodroidRuntime::gather_bundled_assemblies (jstring_array_wrapper &runtimeApks, size_t *out_user_assemblies_count, bool have_split_apks) { if (!AndroidSystem::is_embedded_dso_mode_enabled ()) { - *out_user_assemblies_count = embeddedAssemblies.register_from_filesystem (); + *out_user_assemblies_count = EmbeddedAssemblies::register_from_filesystem (); return; } @@ -261,12 +261,12 @@ MonodroidRuntime::gather_bundled_assemblies (jstring_array_wrapper &runtimeApks, *out_user_assemblies_count += (cur_num_assemblies - prev_num_assemblies); prev_num_assemblies = cur_num_assemblies; - if (!embeddedAssemblies.keep_scanning ()) { + if (!EmbeddedAssemblies::keep_scanning ()) { break; } } - embeddedAssemblies.ensure_valid_assembly_stores (); + EmbeddedAssemblies::ensure_valid_assembly_stores (); } #if defined (DEBUG) @@ -495,7 +495,7 @@ MonodroidRuntime::set_debug_options (void) if (AndroidSystem::monodroid_get_system_property (SharedConstants::DEBUG_MONO_DEBUG_PROPERTY, nullptr) == 0) return; - embeddedAssemblies.set_register_debug_symbols (true); + EmbeddedAssemblies::set_register_debug_symbols (true); mono_debug_init (MONO_DEBUG_FORMAT_MONO); } @@ -513,7 +513,7 @@ MonodroidRuntime::mono_runtime_init ([[maybe_unused]] JNIEnv *env, [[maybe_unuse } else if (options.debug && cur_time > options.timeout_time) { log_warn (LOG_DEBUGGER, "Not starting the debugger as the timeout value has been reached; current-time: %lli timeout: %lli", cur_time, options.timeout_time); } else if (options.debug && cur_time <= options.timeout_time) { - embeddedAssemblies.set_register_debug_symbols (true); + EmbeddedAssemblies::set_register_debug_symbols (true); int loglevel; if (Logger::have_debugger_log_level ()) @@ -687,7 +687,7 @@ MonodroidRuntime::mono_runtime_init ([[maybe_unused]] JNIEnv *env, [[maybe_unuse * Looking for assemblies from the update dir takes precedence over * everything else, and thus must go LAST. */ - embeddedAssemblies.install_preload_hooks_for_appdomains (); + EmbeddedAssemblies::install_preload_hooks_for_appdomains (); #ifndef RELEASE mono_install_assembly_preload_hook (open_from_update_dir, nullptr); #endif @@ -702,7 +702,7 @@ MonodroidRuntime::mono_runtime_init ([[maybe_unused]] JNIEnv *env, [[maybe_unuse void MonodroidRuntime::cleanup_runtime_config ([[maybe_unused]] MonovmRuntimeConfigArguments *args, [[maybe_unused]] void *user_data) { - embeddedAssemblies.unmap_runtime_config_blob (); + EmbeddedAssemblies::unmap_runtime_config_blob (); } MonoDomain* @@ -712,14 +712,14 @@ MonodroidRuntime::create_domain (JNIEnv *env, jstring_array_wrapper &runtimeApks gather_bundled_assemblies (runtimeApks, &user_assemblies_count, have_split_apks); - if (embeddedAssemblies.have_runtime_config_blob ()) { + if (EmbeddedAssemblies::have_runtime_config_blob ()) { size_t blob_time_index; if (FastTiming::enabled ()) [[unlikely]] { blob_time_index = internal_timing->start_event (TimingEventKind::RuntimeConfigBlob); } runtime_config_args.kind = 1; - embeddedAssemblies.get_runtime_config_blob (runtime_config_args.runtimeconfig.data.data, runtime_config_args.runtimeconfig.data.data_len); + EmbeddedAssemblies::get_runtime_config_blob (runtime_config_args.runtimeconfig.data.data, runtime_config_args.runtimeconfig.data.data_len); monovm_runtimeconfig_initialize (&runtime_config_args, cleanup_runtime_config, nullptr); if (FastTiming::enabled ()) [[unlikely]] { @@ -1267,7 +1267,7 @@ MonodroidRuntime::create_and_initialize_domain (JNIEnv* env, jclass runtimeClass default_alc = mono_alc_get_default_gchandle (); abort_unless (default_alc != nullptr, "Default AssemblyLoadContext not found"); - embeddedAssemblies.install_preload_hooks_for_alc (); + EmbeddedAssemblies::install_preload_hooks_for_alc (); log_debug (LOG_ASSEMBLY, "ALC hooks installed"); bool preload = (AndroidSystem::is_assembly_preload_enabled () || (is_running_on_desktop && force_preload_assemblies)); @@ -1289,13 +1289,13 @@ MonodroidRuntime::monodroid_unhandled_exception (MonoObject *java_exception) MonoReflectionType* MonodroidRuntime::typemap_java_to_managed (MonoString *java_type_name) noexcept { - return embeddedAssemblies.typemap_java_to_managed (java_type_name); + return EmbeddedAssemblies::typemap_java_to_managed (java_type_name); } const char* MonodroidRuntime::typemap_managed_to_java (MonoReflectionType *type, const uint8_t *mvid) noexcept { - return embeddedAssemblies.typemap_managed_to_java (type, mvid); + return EmbeddedAssemblies::typemap_managed_to_java (type, mvid); } #endif // !def RELEASE From 1d4584297eecc26ded78dc0d6357cda68478633c Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Wed, 13 Nov 2024 14:50:37 -0800 Subject: [PATCH 33/54] MonodroidRuntime is static now --- src/native/monodroid/globals.cc | 1 - src/native/monodroid/globals.hh | 1 - src/native/monodroid/internal-pinvokes.cc | 16 +-- .../monodroid/monodroid-glue-internal.hh | 116 ++++++++---------- src/native/monodroid/monodroid-glue.cc | 74 +++++------ 5 files changed, 99 insertions(+), 109 deletions(-) diff --git a/src/native/monodroid/globals.cc b/src/native/monodroid/globals.cc index 7822952f8f0..d5fdf4d08e4 100644 --- a/src/native/monodroid/globals.cc +++ b/src/native/monodroid/globals.cc @@ -4,7 +4,6 @@ using namespace xamarin::android; using namespace xamarin::android::internal; OSBridge osBridge; -MonodroidRuntime monodroidRuntime; Timing *timing = nullptr; Debug debug; diff --git a/src/native/monodroid/globals.hh b/src/native/monodroid/globals.hh index 6f1649d9796..046a0ff770f 100644 --- a/src/native/monodroid/globals.hh +++ b/src/native/monodroid/globals.hh @@ -11,7 +11,6 @@ extern xamarin::android::Debug debug; extern xamarin::android::internal::OSBridge osBridge; -extern xamarin::android::internal::MonodroidRuntime monodroidRuntime; extern xamarin::android::Timing *timing; #endif // !__GLOBALS_H diff --git a/src/native/monodroid/internal-pinvokes.cc b/src/native/monodroid/internal-pinvokes.cc index 2324084a3f7..c61768ea173 100644 --- a/src/native/monodroid/internal-pinvokes.cc +++ b/src/native/monodroid/internal-pinvokes.cc @@ -135,13 +135,13 @@ _monodroid_gc_wait_for_bridge_processing () void monodroid_clear_gdb_wait () { - monodroidRuntime.set_monodroid_gdb_wait (false); + MonodroidRuntime::set_monodroid_gdb_wait (false); } void* _monodroid_get_identity_hash_code (JNIEnv *env, void *v) { - intptr_t rv = env->CallStaticIntMethod (monodroidRuntime.get_java_class_System (), monodroidRuntime.get_java_class_method_System_identityHashCode (), v); + intptr_t rv = env->CallStaticIntMethod (MonodroidRuntime::get_java_class_System (), MonodroidRuntime::get_java_class_method_System_identityHashCode (), v); return (void*) rv; } @@ -149,9 +149,9 @@ void* _monodroid_timezone_get_default_id () { JNIEnv *env = osBridge.ensure_jnienv (); - jmethodID getDefault = env->GetStaticMethodID (monodroidRuntime.get_java_class_TimeZone (), "getDefault", "()Ljava/util/TimeZone;"); - jmethodID getID = env->GetMethodID (monodroidRuntime.get_java_class_TimeZone (), "getID", "()Ljava/lang/String;"); - jobject d = env->CallStaticObjectMethod (monodroidRuntime.get_java_class_TimeZone (), getDefault); + jmethodID getDefault = env->GetStaticMethodID (MonodroidRuntime::get_java_class_TimeZone (), "getDefault", "()Ljava/util/TimeZone;"); + jmethodID getID = env->GetMethodID (MonodroidRuntime::get_java_class_TimeZone (), "getID", "()Ljava/lang/String;"); + jobject d = env->CallStaticObjectMethod (MonodroidRuntime::get_java_class_TimeZone (), getDefault); jstring id = reinterpret_cast (env->CallObjectMethod (d, getID)); const char *mutf8 = env->GetStringUTFChars (id, nullptr); @@ -175,7 +175,7 @@ void _monodroid_counters_dump ([[maybe_unused]] const char *format, [[maybe_unused]] va_list args) { #if !defined (NET) - monodroidRuntime.dump_counters_v (format, args); + MonodroidRuntime::dump_counters_v (format, args); #endif // ndef NET } @@ -234,7 +234,7 @@ monodroid_strdup_printf (const char *format, ...) char* monodroid_TypeManager_get_java_class_name (jclass klass) { - return monodroidRuntime.get_java_class_name_for_TypeManager (klass); + return MonodroidRuntime::get_java_class_name_for_TypeManager (klass); } int @@ -333,5 +333,5 @@ monodroid_log_traces (uint32_t kind, const char *first_line) JNIEnv *env = osBridge.ensure_jnienv (); auto tk = static_cast(kind); - monodroidRuntime.log_traces (env, tk, first_line); + MonodroidRuntime::log_traces (env, tk, first_line); } diff --git a/src/native/monodroid/monodroid-glue-internal.hh b/src/native/monodroid/monodroid-glue-internal.hh index abbd8a8d4c6..59f00ceffd2 100644 --- a/src/native/monodroid/monodroid-glue-internal.hh +++ b/src/native/monodroid/monodroid-glue-internal.hh @@ -115,45 +115,45 @@ namespace xamarin::android::internal static constexpr int XA_LOG_COUNTERS = MONO_COUNTER_JIT | MONO_COUNTER_METADATA | MONO_COUNTER_GC | MONO_COUNTER_GENERICS | MONO_COUNTER_INTERP; public: - void Java_mono_android_Runtime_register (JNIEnv *env, jstring managedType, jclass nativeClass, jstring methods); - void Java_mono_android_Runtime_initInternal (JNIEnv *env, jclass klass, jstring lang, jobjectArray runtimeApksJava, + static void Java_mono_android_Runtime_register (JNIEnv *env, jstring managedType, jclass nativeClass, jstring methods) noexcept; + static void Java_mono_android_Runtime_initInternal (JNIEnv *env, jclass klass, jstring lang, jobjectArray runtimeApksJava, jstring runtimeNativeLibDir, jobjectArray appDirs, jint localDateTimeOffset, jobject loader, jobjectArray assembliesJava, jboolean isEmulator, - jboolean haveSplitApks); + jboolean haveSplitApks) noexcept; - jint Java_JNI_OnLoad (JavaVM *vm, void *reserved); + static jint Java_JNI_OnLoad (JavaVM *vm, void *reserved) noexcept; - jclass get_java_class_System () const + static jclass get_java_class_System () noexcept { return java_System; } - jmethodID get_java_class_method_System_identityHashCode () const + static jmethodID get_java_class_method_System_identityHashCode () noexcept { return java_System_identityHashCode; } - jclass get_java_class_TimeZone () const + static jclass get_java_class_TimeZone () noexcept { return java_TimeZone; } - void set_monodroid_gdb_wait (bool yes_no) + static void set_monodroid_gdb_wait (bool yes_no) noexcept { monodroid_gdb_wait = yes_no; } - void propagate_uncaught_exception (JNIEnv *env, jobject javaThread, jthrowable javaException); - char* get_java_class_name_for_TypeManager (jclass klass); - void log_traces (JNIEnv *env, TraceKind kind, const char *first_line) noexcept; + static void propagate_uncaught_exception (JNIEnv *env, jobject javaThread, jthrowable javaException) noexcept; + static char* get_java_class_name_for_TypeManager (jclass klass) noexcept; + static void log_traces (JNIEnv *env, TraceKind kind, const char *first_line) noexcept; private: static void mono_log_handler (const char *log_domain, const char *log_level, const char *message, mono_bool fatal, void *user_data); static void mono_log_standard_streams_handler (const char *str, mono_bool is_stdout); // A reference to unique_ptr is not the best practice ever, but it's faster this way - void setup_mono_tracing (std::unique_ptr const& mono_log_mask, bool have_log_assembly, bool have_log_gc); - void install_logging_handlers (); + static void setup_mono_tracing (std::unique_ptr const& mono_log_mask, bool have_log_assembly, bool have_log_gc) noexcept; + static void install_logging_handlers () noexcept; unsigned int convert_dl_flags (int flags); @@ -174,45 +174,45 @@ namespace xamarin::android::internal fnptr = reinterpret_cast(symptr); } - void create_xdg_directory (jstring_wrapper& home, size_t home_len, std::string_view const& relative_path, std::string_view const& environment_variable_name) noexcept; - void create_xdg_directories_and_environment (jstring_wrapper &homeDir); - void lookup_bridge_info (MonoClass *klass, const OSBridge::MonoJavaGCBridgeType *type, OSBridge::MonoJavaGCBridgeInfo *info); - void lookup_bridge_info (MonoImage *image, const OSBridge::MonoJavaGCBridgeType *type, OSBridge::MonoJavaGCBridgeInfo *info); - void load_assembly (MonoDomain *domain, jstring_wrapper &assembly); - void load_assembly (MonoAssemblyLoadContextGCHandle alc_handle, jstring_wrapper &assembly); - void load_assemblies (load_assemblies_context_type ctx, bool preload, jstring_array_wrapper &assemblies); - - void set_debug_options (); - void parse_gdb_options (); - void mono_runtime_init (JNIEnv *env, dynamic_local_string& runtime_args); - void init_android_runtime (JNIEnv *env, jclass runtimeClass, jobject loader); - void set_environment_variable_for_directory (const char *name, jstring_wrapper &value, bool createDirectory, mode_t mode); - - void set_environment_variable_for_directory (const char *name, jstring_wrapper &value) + static void create_xdg_directory (jstring_wrapper& home, size_t home_len, std::string_view const& relative_path, std::string_view const& environment_variable_name) noexcept; + static void create_xdg_directories_and_environment (jstring_wrapper &homeDir) noexcept; + static void lookup_bridge_info (MonoClass *klass, const OSBridge::MonoJavaGCBridgeType *type, OSBridge::MonoJavaGCBridgeInfo *info) noexcept; + static void lookup_bridge_info (MonoImage *image, const OSBridge::MonoJavaGCBridgeType *type, OSBridge::MonoJavaGCBridgeInfo *info) noexcept; + static void load_assembly (MonoDomain *domain, jstring_wrapper &assembly) noexcept; + static void load_assembly (MonoAssemblyLoadContextGCHandle alc_handle, jstring_wrapper &assembly) noexcept; + static void load_assemblies (load_assemblies_context_type ctx, bool preload, jstring_array_wrapper &assemblies) noexcept; + + static void set_debug_options () noexcept; + static void parse_gdb_options () noexcept; + static void mono_runtime_init (JNIEnv *env, dynamic_local_string& runtime_args) noexcept; + static void init_android_runtime (JNIEnv *env, jclass runtimeClass, jobject loader) noexcept; + static void set_environment_variable_for_directory (const char *name, jstring_wrapper &value, bool createDirectory, mode_t mode) noexcept; + + static void set_environment_variable_for_directory (const char *name, jstring_wrapper &value) noexcept { set_environment_variable_for_directory (name, value, true, DEFAULT_DIRECTORY_MODE); } - void set_environment_variable (const char *name, jstring_wrapper &value) + static void set_environment_variable (const char *name, jstring_wrapper &value) noexcept { set_environment_variable_for_directory (name, value, false, 0); } static void monodroid_unhandled_exception (MonoObject *java_exception); - MonoClass* get_android_runtime_class (); + static MonoClass* get_android_runtime_class () noexcept; - MonoDomain* create_domain (JNIEnv *env, jstring_array_wrapper &runtimeApks, bool is_root_domain, bool have_split_apks); - MonoDomain* create_and_initialize_domain (JNIEnv* env, jclass runtimeClass, jstring_array_wrapper &runtimeApks, + static MonoDomain* create_domain (JNIEnv *env, jstring_array_wrapper &runtimeApks, bool is_root_domain, bool have_split_apks) noexcept; + static MonoDomain* create_and_initialize_domain (JNIEnv* env, jclass runtimeClass, jstring_array_wrapper &runtimeApks, jstring_array_wrapper &assemblies, jobjectArray assembliesBytes, jstring_array_wrapper &assembliesPaths, jobject loader, bool is_root_domain, bool force_preload_assemblies, - bool have_split_apks); + bool have_split_apks) noexcept; - void gather_bundled_assemblies (jstring_array_wrapper &runtimeApks, size_t *out_user_assemblies_count, bool have_split_apks); + static void gather_bundled_assemblies (jstring_array_wrapper &runtimeApks, size_t *out_user_assemblies_count, bool have_split_apks) noexcept; static bool should_register_file (const char *filename); - void set_trace_options (); - void set_profile_options (); + static void set_trace_options () noexcept; + static void set_profile_options () noexcept; - void log_jit_event (MonoMethod *method, const char *event_name); + static void log_jit_event (MonoMethod *method, const char *event_name) noexcept; static void jit_begin (MonoProfiler *prof, MonoMethod *method); static void jit_failed (MonoProfiler *prof, MonoMethod *method); static void jit_done (MonoProfiler *prof, MonoMethod *method, MonoJitInfo* jinfo); @@ -236,44 +236,36 @@ namespace xamarin::android::internal #endif // def RELEASE #if defined (DEBUG) - void set_debug_env_vars (void); - bool parse_runtime_args (dynamic_local_string &runtime_args, RuntimeOptions *options); - int monodroid_debug_connect (int sock, struct sockaddr_in addr); - int monodroid_debug_accept (int sock, struct sockaddr_in addr); + static inline void set_debug_env_vars (void) noexcept; + static inline bool parse_runtime_args (dynamic_local_string &runtime_args, RuntimeOptions *options) noexcept; + static inline int monodroid_debug_connect (int sock, struct sockaddr_in addr) noexcept; + static inline int monodroid_debug_accept (int sock, struct sockaddr_in addr) noexcept; #endif // DEBUG #if !defined (RELEASE) static MonoAssembly* open_from_update_dir (MonoAssemblyName *aname, char **assemblies_path, void *user_data); #endif private: - MonoMethod *registerType = nullptr; - volatile bool monodroid_gdb_wait = true; - jclass java_System; - jmethodID java_System_identityHashCode; - jmethodID Class_getName; - jclass java_TimeZone; - timing_period jit_time; - FILE *jit_log; - MonoProfilerHandle profiler_handle; + static inline MonoMethod *registerType = nullptr; + static inline bool monodroid_gdb_wait = true; + static inline jclass java_System; + static inline jmethodID java_System_identityHashCode; + static inline jmethodID Class_getName; + static inline jclass java_TimeZone; + static inline timing_period jit_time; + static inline FILE *jit_log = nullptr; + static inline MonoProfilerHandle profiler_handle; /* * If set, monodroid will spin in a loop until the debugger breaks the wait by * clearing monodroid_gdb_wait. */ - bool wait_for_gdb; - - /* The context (mapping to a Mono AppDomain) that is currently selected as the - * active context from the point of view of Java. We cannot rely on the value - * of `mono_domain_get` for this as it's stored per-thread and we want to be - * able to switch our different contexts from different threads. - */ - int current_context_id = -1; - - jnienv_register_jni_natives_fn jnienv_register_jni_natives = nullptr; - MonoAssemblyLoadContextGCHandle default_alc = nullptr; + static inline bool wait_for_gdb = false; + static inline jnienv_register_jni_natives_fn jnienv_register_jni_natives = nullptr; + static inline MonoAssemblyLoadContextGCHandle default_alc = nullptr; static MonoCoreRuntimeProperties monovm_core_properties; - MonovmRuntimeConfigArguments runtime_config_args; + static inline MonovmRuntimeConfigArguments runtime_config_args; }; } #endif diff --git a/src/native/monodroid/monodroid-glue.cc b/src/native/monodroid/monodroid-glue.cc index d40d9b264ae..a90e239e83f 100644 --- a/src/native/monodroid/monodroid-glue.cc +++ b/src/native/monodroid/monodroid-glue.cc @@ -102,7 +102,7 @@ MonodroidRuntime::thread_end ([[maybe_unused]] MonoProfiler *prof, [[maybe_unuse } inline void -MonodroidRuntime::log_jit_event (MonoMethod *method, const char *event_name) +MonodroidRuntime::log_jit_event (MonoMethod *method, const char *event_name) noexcept { jit_time.mark_end (); @@ -120,19 +120,19 @@ MonodroidRuntime::log_jit_event (MonoMethod *method, const char *event_name) void MonodroidRuntime::jit_begin ([[maybe_unused]] MonoProfiler *prof, MonoMethod *method) { - monodroidRuntime.log_jit_event (method, "begin"); + MonodroidRuntime::log_jit_event (method, "begin"); } void MonodroidRuntime::jit_failed ([[maybe_unused]] MonoProfiler *prof, MonoMethod *method) { - monodroidRuntime.log_jit_event (method, "failed"); + MonodroidRuntime::log_jit_event (method, "failed"); } void MonodroidRuntime::jit_done ([[maybe_unused]] MonoProfiler *prof, MonoMethod *method, [[maybe_unused]] MonoJitInfo* jinfo) { - monodroidRuntime.log_jit_event (method, "done"); + MonodroidRuntime::log_jit_event (method, "done"); } #ifndef RELEASE @@ -225,7 +225,7 @@ MonodroidRuntime::should_register_file ([[maybe_unused]] const char *filename) } inline void -MonodroidRuntime::gather_bundled_assemblies (jstring_array_wrapper &runtimeApks, size_t *out_user_assemblies_count, bool have_split_apks) +MonodroidRuntime::gather_bundled_assemblies (jstring_array_wrapper &runtimeApks, size_t *out_user_assemblies_count, bool have_split_apks) noexcept { if (!AndroidSystem::is_embedded_dso_mode_enabled ()) { *out_user_assemblies_count = EmbeddedAssemblies::register_from_filesystem (); @@ -271,7 +271,7 @@ MonodroidRuntime::gather_bundled_assemblies (jstring_array_wrapper &runtimeApks, #if defined (DEBUG) int -MonodroidRuntime::monodroid_debug_connect (int sock, struct sockaddr_in addr) +MonodroidRuntime::monodroid_debug_connect (int sock, struct sockaddr_in addr) noexcept { long flags = fcntl (sock, F_GETFL, nullptr); flags |= O_NONBLOCK; @@ -316,7 +316,7 @@ MonodroidRuntime::monodroid_debug_connect (int sock, struct sockaddr_in addr) } int -MonodroidRuntime::monodroid_debug_accept (int sock, struct sockaddr_in addr) +MonodroidRuntime::monodroid_debug_accept (int sock, struct sockaddr_in addr) noexcept { ssize_t res = bind (sock, (struct sockaddr *) &addr, sizeof (addr)); if (res < 0) @@ -342,7 +342,7 @@ MonodroidRuntime::monodroid_debug_accept (int sock, struct sockaddr_in addr) #endif inline jint -MonodroidRuntime::Java_JNI_OnLoad (JavaVM *vm, [[maybe_unused]] void *reserved) +MonodroidRuntime::Java_JNI_OnLoad (JavaVM *vm, [[maybe_unused]] void *reserved) noexcept { JNIEnv *env; @@ -355,7 +355,7 @@ MonodroidRuntime::Java_JNI_OnLoad (JavaVM *vm, [[maybe_unused]] void *reserved) } void -MonodroidRuntime::parse_gdb_options () +MonodroidRuntime::parse_gdb_options () noexcept { dynamic_local_string val; @@ -389,7 +389,7 @@ MonodroidRuntime::parse_gdb_options () #if defined (DEBUG) bool -MonodroidRuntime::parse_runtime_args (dynamic_local_string &runtime_args, RuntimeOptions *options) +MonodroidRuntime::parse_runtime_args (dynamic_local_string &runtime_args, RuntimeOptions *options) noexcept { if (runtime_args.length () == 0) { log_warn (LOG_DEFAULT, "runtime args empty"); @@ -490,7 +490,7 @@ MonodroidRuntime::parse_runtime_args (dynamic_local_string& runtime_args) +MonodroidRuntime::mono_runtime_init ([[maybe_unused]] JNIEnv *env, [[maybe_unused]] dynamic_local_string& runtime_args) noexcept { #if defined (DEBUG) RuntimeOptions options{}; @@ -706,7 +706,7 @@ MonodroidRuntime::cleanup_runtime_config ([[maybe_unused]] MonovmRuntimeConfigAr } MonoDomain* -MonodroidRuntime::create_domain (JNIEnv *env, jstring_array_wrapper &runtimeApks, bool is_root_domain, bool have_split_apks) +MonodroidRuntime::create_domain (JNIEnv *env, jstring_array_wrapper &runtimeApks, bool is_root_domain, bool have_split_apks) noexcept { size_t user_assemblies_count = 0uz; @@ -773,7 +773,7 @@ MonodroidRuntime::create_domain (JNIEnv *env, jstring_array_wrapper &runtimeApks } force_inline void -MonodroidRuntime::lookup_bridge_info (MonoClass *klass, const OSBridge::MonoJavaGCBridgeType *type, OSBridge::MonoJavaGCBridgeInfo *info) +MonodroidRuntime::lookup_bridge_info (MonoClass *klass, const OSBridge::MonoJavaGCBridgeType *type, OSBridge::MonoJavaGCBridgeInfo *info) noexcept { info->klass = klass; info->handle = mono_class_get_field_from_name (info->klass, const_cast ("handle")); @@ -798,7 +798,7 @@ MonodroidRuntime::lookup_bridge_info (MonoClass *klass, const OSBridge::MonoJava } force_inline void -MonodroidRuntime::lookup_bridge_info (MonoImage *image, const OSBridge::MonoJavaGCBridgeType *type, OSBridge::MonoJavaGCBridgeInfo *info) +MonodroidRuntime::lookup_bridge_info (MonoImage *image, const OSBridge::MonoJavaGCBridgeType *type, OSBridge::MonoJavaGCBridgeInfo *info) noexcept { lookup_bridge_info ( mono_class_from_name (image, type->_namespace, type->_typename), @@ -814,7 +814,7 @@ MonodroidRuntime::monodroid_debugger_unhandled_exception (MonoException *ex) } void -MonodroidRuntime::init_android_runtime (JNIEnv *env, jclass runtimeClass, jobject loader) +MonodroidRuntime::init_android_runtime (JNIEnv *env, jclass runtimeClass, jobject loader) noexcept { constexpr std::string_view icall_typemap_java_to_managed { "Java.Interop.TypeManager::monodroid_typemap_java_to_managed" }; constexpr std::string_view icall_typemap_managed_to_java { "Android.Runtime.JNIEnv::monodroid_typemap_managed_to_java" }; @@ -960,7 +960,7 @@ MonodroidRuntime::init_android_runtime (JNIEnv *env, jclass runtimeClass, jobjec } MonoClass* -MonodroidRuntime::get_android_runtime_class () +MonodroidRuntime::get_android_runtime_class () noexcept { MonoAssembly *assm = Util::monodroid_load_assembly (default_alc, SharedConstants::MONO_ANDROID_ASSEMBLY_NAME.data ()); MonoImage *image = mono_assembly_get_image (assm); @@ -968,7 +968,7 @@ MonodroidRuntime::get_android_runtime_class () } inline void -MonodroidRuntime::propagate_uncaught_exception (JNIEnv *env, jobject javaThread, jthrowable javaException) +MonodroidRuntime::propagate_uncaught_exception (JNIEnv *env, jobject javaThread, jthrowable javaException) noexcept { MonoClass *runtime = get_android_runtime_class (); MonoMethod *method = mono_class_get_method_from_name (runtime, "PropagateUncaughtException", 3); @@ -991,7 +991,7 @@ setup_gc_logging (void) } inline void -MonodroidRuntime::set_environment_variable_for_directory (const char *name, jstring_wrapper &value, bool createDirectory, mode_t mode) +MonodroidRuntime::set_environment_variable_for_directory (const char *name, jstring_wrapper &value, bool createDirectory, mode_t mode) noexcept { if (createDirectory) { int rv = Util::create_directory (value.get_cstr (), mode); @@ -1016,7 +1016,7 @@ MonodroidRuntime::create_xdg_directory (jstring_wrapper& home, size_t home_len, } inline void -MonodroidRuntime::create_xdg_directories_and_environment (jstring_wrapper &homeDir) +MonodroidRuntime::create_xdg_directories_and_environment (jstring_wrapper &homeDir) noexcept { size_t home_len = strlen (homeDir.get_cstr ()); @@ -1031,7 +1031,7 @@ MonodroidRuntime::create_xdg_directories_and_environment (jstring_wrapper &homeD #if DEBUG void -MonodroidRuntime::set_debug_env_vars (void) +MonodroidRuntime::set_debug_env_vars (void) noexcept { dynamic_local_string value; if (AndroidSystem::monodroid_get_system_property (SharedConstants::DEBUG_MONO_ENV_PROPERTY, value) == 0) @@ -1071,7 +1071,7 @@ MonodroidRuntime::set_debug_env_vars (void) #endif /* DEBUG */ inline void -MonodroidRuntime::set_trace_options (void) +MonodroidRuntime::set_trace_options (void) noexcept { dynamic_local_string value; if (AndroidSystem::monodroid_get_system_property (SharedConstants::DEBUG_MONO_TRACE_PROPERTY, value) == 0) @@ -1081,7 +1081,7 @@ MonodroidRuntime::set_trace_options (void) } inline void -MonodroidRuntime::set_profile_options () +MonodroidRuntime::set_profile_options () noexcept { // We want to avoid dynamic allocation, thus let’s create a buffer that can take both the property value and a // path without allocation @@ -1146,7 +1146,7 @@ MonodroidRuntime::set_profile_options () } inline void -MonodroidRuntime::load_assembly (MonoAssemblyLoadContextGCHandle alc_handle, jstring_wrapper &assembly) +MonodroidRuntime::load_assembly (MonoAssemblyLoadContextGCHandle alc_handle, jstring_wrapper &assembly) noexcept { size_t total_time_index; if (FastTiming::enabled ()) [[unlikely]] { @@ -1178,7 +1178,7 @@ MonodroidRuntime::load_assembly (MonoAssemblyLoadContextGCHandle alc_handle, jst } inline void -MonodroidRuntime::load_assembly (MonoDomain *domain, jstring_wrapper &assembly) +MonodroidRuntime::load_assembly (MonoDomain *domain, jstring_wrapper &assembly) noexcept { size_t total_time_index; if (FastTiming::enabled ()) [[unlikely]] { @@ -1216,7 +1216,7 @@ MonodroidRuntime::load_assembly (MonoDomain *domain, jstring_wrapper &assembly) } inline void -MonodroidRuntime::load_assemblies (load_assemblies_context_type ctx, bool preload, jstring_array_wrapper &assemblies) +MonodroidRuntime::load_assemblies (load_assemblies_context_type ctx, bool preload, jstring_array_wrapper &assemblies) noexcept { size_t total_time_index; if (FastTiming::enabled ()) [[unlikely]] { @@ -1251,7 +1251,7 @@ MonoDomain* MonodroidRuntime::create_and_initialize_domain (JNIEnv* env, jclass runtimeClass, jstring_array_wrapper &runtimeApks, jstring_array_wrapper &assemblies, [[maybe_unused]] jobjectArray assembliesBytes, [[maybe_unused]] jstring_array_wrapper &assembliesPaths, jobject loader, bool is_root_domain, - bool force_preload_assemblies, bool have_split_apks) + bool force_preload_assemblies, bool have_split_apks) noexcept { MonoDomain* domain = create_domain (env, runtimeApks, is_root_domain, have_split_apks); // Asserting this on desktop apparently breaks a Designer test @@ -1300,7 +1300,7 @@ MonodroidRuntime::typemap_managed_to_java (MonoReflectionType *type, const uint8 #endif // !def RELEASE force_inline void -MonodroidRuntime::setup_mono_tracing (std::unique_ptr const& mono_log_mask, bool have_log_assembly, bool have_log_gc) +MonodroidRuntime::setup_mono_tracing (std::unique_ptr const& mono_log_mask, bool have_log_assembly, bool have_log_gc) noexcept { constexpr std::string_view MASK_ASM { "asm" }; constexpr std::string_view MASK_DLL { "dll" }; @@ -1373,7 +1373,7 @@ MonodroidRuntime::setup_mono_tracing (std::unique_ptr const& mono_log_ma } force_inline void -MonodroidRuntime::install_logging_handlers () +MonodroidRuntime::install_logging_handlers () noexcept { mono_trace_set_log_handler (mono_log_handler, nullptr); mono_trace_set_print_handler (mono_log_standard_streams_handler); @@ -1384,7 +1384,7 @@ inline void MonodroidRuntime::Java_mono_android_Runtime_initInternal (JNIEnv *env, jclass klass, jstring lang, jobjectArray runtimeApksJava, jstring runtimeNativeLibDir, jobjectArray appDirs, jint localDateTimeOffset, jobject loader, jobjectArray assembliesJava, jboolean isEmulator, - jboolean haveSplitApks) + jboolean haveSplitApks) noexcept { char *mono_log_mask_raw = nullptr; char *mono_log_level_raw = nullptr; @@ -1558,7 +1558,7 @@ JNIEXPORT jint JNICALL JNI_OnLoad (JavaVM *vm, void *reserved) { Util::initialize (); - return monodroidRuntime.Java_JNI_OnLoad (vm, reserved); + return MonodroidRuntime::Java_JNI_OnLoad (vm, reserved); } /* !DO NOT REMOVE! Used by the Android Designer */ @@ -1568,7 +1568,7 @@ Java_mono_android_Runtime_init (JNIEnv *env, jclass klass, jstring lang, jobject [[maybe_unused]] jobjectArray externalStorageDirs, jobjectArray assembliesJava, [[maybe_unused]] jstring packageName, [[maybe_unused]] jint apiLevel, [[maybe_unused]] jobjectArray environmentVariables) { - monodroidRuntime.Java_mono_android_Runtime_initInternal ( + MonodroidRuntime::Java_mono_android_Runtime_initInternal ( env, klass, lang, @@ -1589,7 +1589,7 @@ Java_mono_android_Runtime_initInternal (JNIEnv *env, jclass klass, jstring lang, jobjectArray assembliesJava, jboolean isEmulator, jboolean haveSplitApks) { - monodroidRuntime.Java_mono_android_Runtime_initInternal ( + MonodroidRuntime::Java_mono_android_Runtime_initInternal ( env, klass, lang, @@ -1605,7 +1605,7 @@ Java_mono_android_Runtime_initInternal (JNIEnv *env, jclass klass, jstring lang, } force_inline void -MonodroidRuntime::Java_mono_android_Runtime_register (JNIEnv *env, jstring managedType, jclass nativeClass, jstring methods) +MonodroidRuntime::Java_mono_android_Runtime_register (JNIEnv *env, jstring managedType, jclass nativeClass, jstring methods) noexcept { size_t total_time_index; @@ -1649,11 +1649,11 @@ JNICALL Java_mono_android_Runtime_dumpTimingData ([[maybe_unused]] JNIEnv *env, JNIEXPORT void JNICALL Java_mono_android_Runtime_register (JNIEnv *env, [[maybe_unused]] jclass klass, jstring managedType, jclass nativeClass, jstring methods) { - monodroidRuntime.Java_mono_android_Runtime_register (env, managedType, nativeClass, methods); + MonodroidRuntime::Java_mono_android_Runtime_register (env, managedType, nativeClass, methods); } char* -MonodroidRuntime::get_java_class_name_for_TypeManager (jclass klass) +MonodroidRuntime::get_java_class_name_for_TypeManager (jclass klass) noexcept { if (klass == nullptr || Class_getName == nullptr) return nullptr; @@ -1694,5 +1694,5 @@ get_jnienv (void) JNIEXPORT void JNICALL Java_mono_android_Runtime_propagateUncaughtException (JNIEnv *env, [[maybe_unused]] jclass klass, jobject javaThread, jthrowable javaException) { - monodroidRuntime.propagate_uncaught_exception (env, javaThread, javaException); + MonodroidRuntime::propagate_uncaught_exception (env, javaThread, javaException); } From 7fb04adf734bdab75b379807fd23eb9dcab65265 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Wed, 13 Nov 2024 16:33:44 -0800 Subject: [PATCH 34/54] Buglets fixed --- src/native/monodroid/embedded-assemblies-zip.cc | 4 ++-- src/native/monodroid/embedded-assemblies.hh | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/native/monodroid/embedded-assemblies-zip.cc b/src/native/monodroid/embedded-assemblies-zip.cc index 82a56859d88..f8d4811df7b 100644 --- a/src/native/monodroid/embedded-assemblies-zip.cc +++ b/src/native/monodroid/embedded-assemblies-zip.cc @@ -257,7 +257,7 @@ EmbeddedAssemblies::zip_load_assembly_store_entries (std::vector const& dynamic_local_string entry_name; bool assembly_store_found = false; - log_debug (LOG_ASSEMBLY, "Looking for assembly stores in APK ('%s)", assembly_store_file_path.data ()); + log_debug (LOG_ASSEMBLY, "Looking for assembly stores in APK ('%s')", assembly_store_file_path.data ()); for (size_t i = 0uz; i < num_entries; i++) { if (all_required_zip_entries_found ()) { need_to_scan_more_apks = false; @@ -269,7 +269,7 @@ EmbeddedAssemblies::zip_load_assembly_store_entries (std::vector const& continue; } - if (!assembly_store_found && Util::ends_with (entry_name, assembly_store_file_path)) { + if (!assembly_store_found && Util::ends_with (entry_name, assembly_store_file_path.data ())) { assembly_store_found = true; map_assembly_store (entry_name, state); continue; diff --git a/src/native/monodroid/embedded-assemblies.hh b/src/native/monodroid/embedded-assemblies.hh index efaa296a0a7..88d57c21d47 100644 --- a/src/native/monodroid/embedded-assemblies.hh +++ b/src/native/monodroid/embedded-assemblies.hh @@ -454,8 +454,8 @@ namespace xamarin::android::internal { static inline uint32_t number_of_zip_dso_entries = 0u; static inline bool need_to_scan_more_apks = true; - static inline AssemblyStoreIndexEntry *assembly_store_hashes; - static inline xamarin::android::mutex assembly_decompress_mutex; + static inline AssemblyStoreIndexEntry *assembly_store_hashes = nullptr; + static inline xamarin::android::mutex assembly_decompress_mutex {}; }; } From 430aea3db48111a2e710b4595afa60f5c19af40d Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Thu, 21 Nov 2024 14:06:41 +0100 Subject: [PATCH 35/54] Trying to find out why AppContext.GetData doesn't appear to work --- src/native/monodroid/embedded-assemblies-zip.cc | 9 +++++++++ src/native/monodroid/embedded-assemblies.hh | 4 +++- src/native/monodroid/monodroid-glue.cc | 5 ++++- src/native/runtime-base/shared-constants.hh | 5 +++-- src/native/runtime-base/util.hh | 5 +++++ 5 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/native/monodroid/embedded-assemblies-zip.cc b/src/native/monodroid/embedded-assemblies-zip.cc index f8d4811df7b..0926b72c83c 100644 --- a/src/native/monodroid/embedded-assemblies-zip.cc +++ b/src/native/monodroid/embedded-assemblies-zip.cc @@ -46,6 +46,7 @@ EmbeddedAssemblies::zip_load_entry_common (size_t entry_index, std::vectorstart_event (TimingEventKind::RuntimeConfigBlob); @@ -720,7 +721,9 @@ MonodroidRuntime::create_domain (JNIEnv *env, jstring_array_wrapper &runtimeApks runtime_config_args.kind = 1; EmbeddedAssemblies::get_runtime_config_blob (runtime_config_args.runtimeconfig.data.data, runtime_config_args.runtimeconfig.data.data_len); - monovm_runtimeconfig_initialize (&runtime_config_args, cleanup_runtime_config, nullptr); + log_info (LOG_ASSEMBLY, " rc data == %p; rc size == %zu", runtime_config_args.runtimeconfig.data.data, runtime_config_args.runtimeconfig.data.data_len); + int ret = monovm_runtimeconfig_initialize (&runtime_config_args, cleanup_runtime_config, nullptr); + log_info (LOG_ASSEMBLY, " ret == %d", ret); if (FastTiming::enabled ()) [[unlikely]] { internal_timing->end_event (blob_time_index); diff --git a/src/native/runtime-base/shared-constants.hh b/src/native/runtime-base/shared-constants.hh index a3355963b59..963faacd1f1 100644 --- a/src/native/runtime-base/shared-constants.hh +++ b/src/native/runtime-base/shared-constants.hh @@ -40,13 +40,14 @@ namespace xamarin::android::internal static constexpr std::string_view DLL_EXTENSION { ".dll" }; static constexpr std::string_view PDB_EXTENSION { ".pdb" }; - private: +// private: static constexpr std::string_view RUNTIME_CONFIG_BLOB_BASE_NAME { "libarc.bin" }; static constexpr size_t runtime_config_blob_name_size = calc_size (RUNTIME_CONFIG_BLOB_BASE_NAME, MANGLED_ASSEMBLY_NAME_EXT); static constexpr auto RUNTIME_CONFIG_BLOB_NAME_ARRAY = concat_string_views (RUNTIME_CONFIG_BLOB_BASE_NAME, MANGLED_ASSEMBLY_NAME_EXT); public: - static constexpr std::string_view RUNTIME_CONFIG_BLOB_NAME { RUNTIME_CONFIG_BLOB_NAME_ARRAY }; + // .data() must be used otherwise string_view length will include the trailing \0 in the array + static constexpr std::string_view RUNTIME_CONFIG_BLOB_NAME { RUNTIME_CONFIG_BLOB_NAME_ARRAY.data () }; static constexpr std::string_view MONO_SGEN_SO { "libmonosgen-2.0.so" }; static constexpr std::string_view MONO_SGEN_ARCH_SO { "libmonosgen-" __BITNESS__ "-2.0.so" }; static constexpr std::string_view OVERRIDE_DIRECTORY_NAME { ".__override__" }; diff --git a/src/native/runtime-base/util.hh b/src/native/runtime-base/util.hh index 97db495dbea..554f421c510 100644 --- a/src/native/runtime-base/util.hh +++ b/src/native/runtime-base/util.hh @@ -167,6 +167,11 @@ namespace xamarin::android return false; } + log_debug (LOG_ASSEMBLY, " ends_with: '%s' -> '%s'; sv.length () == %zu", + str.get () + str.length () - sv.length (), + sv.data (), + sv.length () + ); return memcmp (str.get () + str.length () - sv.length (), sv.data (), sv.length ()) == 0; } From 5c728e75d79e673fce49ff020441980a3479929b Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Thu, 21 Nov 2024 18:11:21 +0100 Subject: [PATCH 36/54] Cleanup --- src/native/monodroid/embedded-assemblies-zip.cc | 9 --------- src/native/monodroid/embedded-assemblies.hh | 11 ++++++++--- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/src/native/monodroid/embedded-assemblies-zip.cc b/src/native/monodroid/embedded-assemblies-zip.cc index 0926b72c83c..f8d4811df7b 100644 --- a/src/native/monodroid/embedded-assemblies-zip.cc +++ b/src/native/monodroid/embedded-assemblies-zip.cc @@ -46,7 +46,6 @@ EmbeddedAssemblies::zip_load_entry_common (size_t entry_index, std::vector (apk_lib_dir_name, zip_path_separator, SharedConstants::android_lib_abi, zip_path_separator); - static constexpr std::string_view assemblies_prefix { assemblies_prefix_array }; + + // .data() must be used otherwise string_view length will include the trailing \0 in the array + static constexpr std::string_view assemblies_prefix { assemblies_prefix_array.data () }; // We have two records for each assembly, for names with and without the extension static constexpr uint32_t assembly_store_index_entries_per_assembly = 2; @@ -104,11 +106,14 @@ namespace xamarin::android::internal { static constexpr size_t assembly_store_file_name_size = calc_size (assembly_store_prefix, SharedConstants::android_lib_abi, assembly_store_extension, dso_suffix); static constexpr auto assembly_store_file_name_array = concat_string_views (assembly_store_prefix, SharedConstants::android_lib_abi, assembly_store_extension, dso_suffix); - static constexpr std::string_view assembly_store_file_name { assembly_store_file_name_array }; + + // .data() must be used otherwise string_view length will include the trailing \0 in the array + static constexpr std::string_view assembly_store_file_name { assembly_store_file_name_array.data () }; static constexpr size_t assembly_store_file_path_size = calc_size(apk_lib_dir_name, zip_path_separator, SharedConstants::android_lib_abi, zip_path_separator, assembly_store_prefix, SharedConstants::android_lib_abi, assembly_store_extension, dso_suffix); static constexpr auto assembly_store_file_path_array = concat_string_views (apk_lib_dir_name, zip_path_separator, SharedConstants::android_lib_abi, zip_path_separator, assembly_store_prefix, SharedConstants::android_lib_abi, assembly_store_extension, dso_suffix); - static constexpr std::string_view assembly_store_file_path { assembly_store_file_path_array }; + // .data() must be used otherwise string_view length will include the trailing \0 in the array + static constexpr std::string_view assembly_store_file_path { assembly_store_file_path_array.data () }; static constexpr size_t dso_size_overhead = ArchiveDSOStubConfig::PayloadSectionOffset + (ArchiveDSOStubConfig::SectionHeaderEntryCount * ArchiveDSOStubConfig::SectionHeaderEntrySize); From 6e3b5e31f0c8e271e7e18618aa9bd36472f4687f Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Mon, 25 Nov 2024 13:19:09 +0100 Subject: [PATCH 37/54] Lengths and offsets... --- src/native/monodroid/embedded-assemblies.hh | 4 ++-- src/native/monodroid/internal-pinvokes.cc | 2 +- src/native/monodroid/monodroid-glue.cc | 5 +---- src/native/runtime-base/shared-constants.hh | 2 +- src/native/runtime-base/util.hh | 10 +++++----- 5 files changed, 10 insertions(+), 13 deletions(-) diff --git a/src/native/monodroid/embedded-assemblies.hh b/src/native/monodroid/embedded-assemblies.hh index d84c3f03e19..ff153942724 100644 --- a/src/native/monodroid/embedded-assemblies.hh +++ b/src/native/monodroid/embedded-assemblies.hh @@ -341,10 +341,10 @@ namespace xamarin::android::internal { } if (application_config.have_assembly_store) { - return { apk_lib_prefix.data (), apk_lib_prefix.size () - 1 }; + return { apk_lib_prefix.data (), apk_lib_prefix.size () }; } - return {assemblies_prefix.data (), assemblies_prefix.size () - 1}; + return {assemblies_prefix.data (), assemblies_prefix.size () }; } static bool all_required_zip_entries_found () noexcept diff --git a/src/native/monodroid/internal-pinvokes.cc b/src/native/monodroid/internal-pinvokes.cc index c61768ea173..81367aaea29 100644 --- a/src/native/monodroid/internal-pinvokes.cc +++ b/src/native/monodroid/internal-pinvokes.cc @@ -22,7 +22,7 @@ int monodroid_embedded_assemblies_set_assemblies_prefix (const char *prefix) { EmbeddedAssemblies::set_assemblies_prefix (prefix); - return 0; + return 0; } void diff --git a/src/native/monodroid/monodroid-glue.cc b/src/native/monodroid/monodroid-glue.cc index 47d72442040..a90e239e83f 100644 --- a/src/native/monodroid/monodroid-glue.cc +++ b/src/native/monodroid/monodroid-glue.cc @@ -713,7 +713,6 @@ MonodroidRuntime::create_domain (JNIEnv *env, jstring_array_wrapper &runtimeApks gather_bundled_assemblies (runtimeApks, &user_assemblies_count, have_split_apks); if (EmbeddedAssemblies::have_runtime_config_blob ()) { - log_info (LOG_ASSEMBLY, "Got runtime config blob"); size_t blob_time_index; if (FastTiming::enabled ()) [[unlikely]] { blob_time_index = internal_timing->start_event (TimingEventKind::RuntimeConfigBlob); @@ -721,9 +720,7 @@ MonodroidRuntime::create_domain (JNIEnv *env, jstring_array_wrapper &runtimeApks runtime_config_args.kind = 1; EmbeddedAssemblies::get_runtime_config_blob (runtime_config_args.runtimeconfig.data.data, runtime_config_args.runtimeconfig.data.data_len); - log_info (LOG_ASSEMBLY, " rc data == %p; rc size == %zu", runtime_config_args.runtimeconfig.data.data, runtime_config_args.runtimeconfig.data.data_len); - int ret = monovm_runtimeconfig_initialize (&runtime_config_args, cleanup_runtime_config, nullptr); - log_info (LOG_ASSEMBLY, " ret == %d", ret); + monovm_runtimeconfig_initialize (&runtime_config_args, cleanup_runtime_config, nullptr); if (FastTiming::enabled ()) [[unlikely]] { internal_timing->end_event (blob_time_index); diff --git a/src/native/runtime-base/shared-constants.hh b/src/native/runtime-base/shared-constants.hh index 963faacd1f1..0b7264d5ce4 100644 --- a/src/native/runtime-base/shared-constants.hh +++ b/src/native/runtime-base/shared-constants.hh @@ -40,7 +40,7 @@ namespace xamarin::android::internal static constexpr std::string_view DLL_EXTENSION { ".dll" }; static constexpr std::string_view PDB_EXTENSION { ".pdb" }; -// private: + private: static constexpr std::string_view RUNTIME_CONFIG_BLOB_BASE_NAME { "libarc.bin" }; static constexpr size_t runtime_config_blob_name_size = calc_size (RUNTIME_CONFIG_BLOB_BASE_NAME, MANGLED_ASSEMBLY_NAME_EXT); static constexpr auto RUNTIME_CONFIG_BLOB_NAME_ARRAY = concat_string_views (RUNTIME_CONFIG_BLOB_BASE_NAME, MANGLED_ASSEMBLY_NAME_EXT); diff --git a/src/native/runtime-base/util.hh b/src/native/runtime-base/util.hh index 554f421c510..d3a8d950dbb 100644 --- a/src/native/runtime-base/util.hh +++ b/src/native/runtime-base/util.hh @@ -167,11 +167,11 @@ namespace xamarin::android return false; } - log_debug (LOG_ASSEMBLY, " ends_with: '%s' -> '%s'; sv.length () == %zu", - str.get () + str.length () - sv.length (), - sv.data (), - sv.length () - ); + // log_debug (LOG_ASSEMBLY, " ends_with: '%s' -> '%s'; sv.length () == %zu", + // str.get () + str.length () - sv.length (), + // sv.data (), + // sv.length () + // ); return memcmp (str.get () + str.length () - sv.length (), sv.data (), sv.length ()) == 0; } From 6d88346cc6ff46df1d55782d740438c217ad1438 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Tue, 26 Nov 2024 09:51:09 +0100 Subject: [PATCH 38/54] Cleanup --- src/native/monodroid/embedded-assemblies-zip.cc | 2 +- src/native/runtime-base/util.hh | 5 ----- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/src/native/monodroid/embedded-assemblies-zip.cc b/src/native/monodroid/embedded-assemblies-zip.cc index f8d4811df7b..d807c633a23 100644 --- a/src/native/monodroid/embedded-assemblies-zip.cc +++ b/src/native/monodroid/embedded-assemblies-zip.cc @@ -269,7 +269,7 @@ EmbeddedAssemblies::zip_load_assembly_store_entries (std::vector const& continue; } - if (!assembly_store_found && Util::ends_with (entry_name, assembly_store_file_path.data ())) { + if (!assembly_store_found && Util::ends_with (entry_name, assembly_store_file_path)) { assembly_store_found = true; map_assembly_store (entry_name, state); continue; diff --git a/src/native/runtime-base/util.hh b/src/native/runtime-base/util.hh index d3a8d950dbb..97db495dbea 100644 --- a/src/native/runtime-base/util.hh +++ b/src/native/runtime-base/util.hh @@ -167,11 +167,6 @@ namespace xamarin::android return false; } - // log_debug (LOG_ASSEMBLY, " ends_with: '%s' -> '%s'; sv.length () == %zu", - // str.get () + str.length () - sv.length (), - // sv.data (), - // sv.length () - // ); return memcmp (str.get () + str.length () - sv.length (), sv.data (), sv.length ()) == 0; } From ad67d5497810ef04205f5c69961b93227c9b2d17 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Tue, 26 Nov 2024 19:02:12 +0100 Subject: [PATCH 39/54] Start using std::format and std::string_view string literals --- .../monodroid/embedded-assemblies-zip.cc | 130 ++++++---- src/native/monodroid/embedded-assemblies.cc | 243 ++++++++++-------- src/native/monodroid/embedded-assemblies.hh | 7 +- src/native/shared/CMakeLists.txt | 1 - src/native/shared/helpers.hh | 25 ++ src/native/shared/log_types.hh | 127 +++++++++ src/native/shared/new_delete.cc | 87 ------- 7 files changed, 370 insertions(+), 250 deletions(-) delete mode 100644 src/native/shared/new_delete.cc diff --git a/src/native/monodroid/embedded-assemblies-zip.cc b/src/native/monodroid/embedded-assemblies-zip.cc index d807c633a23..6d47ba7c042 100644 --- a/src/native/monodroid/embedded-assemblies-zip.cc +++ b/src/native/monodroid/embedded-assemblies-zip.cc @@ -1,6 +1,7 @@ #include #include #include +#include #include #include @@ -21,12 +22,12 @@ EmbeddedAssemblies::zip_load_entry_common (size_t entry_index, std::vector= application_config.number_of_assemblies_in_apk || state.bundled_assemblies_slow_path) [[unlikely]] { if (!state.bundled_assemblies_slow_path && bundled_assembly_index == application_config.number_of_assemblies_in_apk) { - log_warn (LOG_ASSEMBLY, "Number of assemblies stored at build time (%u) was incorrect, switching to slow bundling path.", application_config.number_of_assemblies_in_apk); + log_warn ( + LOG_ASSEMBLY, + std::format ( + "Number of assemblies stored at build time ({}) was incorrect, switching to slow bundling path.", + application_config.number_of_assemblies_in_apk + ) + ); } if (extra_bundled_assemblies == nullptr) { @@ -132,9 +139,9 @@ EmbeddedAssemblies::store_individual_assembly_data (dynamic_local_string if (number_of_mapped_assembly_stores > number_of_assembly_store_files) { Helpers::abort_application ( LOG_ASSEMBLY, - Util::monodroid_strdup_printf ( - "Too many assembly stores. Expected at most %u", + std::format ( + "Too many assembly stores. Expected at most {}", number_of_assembly_store_files ) ); @@ -189,7 +196,7 @@ EmbeddedAssemblies::map_assembly_store (dynamic_local_string int fd; bool close_fd; if (!AndroidSystem::is_embedded_dso_mode_enabled ()) { - log_debug (LOG_ASSEMBLY, "Mapping assembly blob file from filesystem"); + log_debug (LOG_ASSEMBLY, "Mapping assembly blob file from filesystem"sv); close_fd = true; // state.file_fd refers to the directory where our files live @@ -209,14 +216,14 @@ EmbeddedAssemblies::map_assembly_store (dynamic_local_string } auto [payload_start, payload_size] = get_wrapper_dso_payload_pointer_and_size (assembly_store_map, entry_name.get ()); - log_debug (LOG_ASSEMBLY, "Adjusted assembly store pointer: %p; size: %zu", payload_start, payload_size); + log_debug (LOG_ASSEMBLY, std::format ("Adjusted assembly store pointer: {:p}; size: {}", payload_start, payload_size)); auto header = static_cast(payload_start); if (header->magic != ASSEMBLY_STORE_MAGIC) { Helpers::abort_application ( LOG_ASSEMBLY, - Util::monodroid_strdup_printf ( - "Assembly store '%s' is not a valid .NET for Android assembly store file", + std::format ( + "Assembly store '{}' is not a valid .NET for Android assembly store file", entry_name.get () ) ); @@ -225,8 +232,8 @@ EmbeddedAssemblies::map_assembly_store (dynamic_local_string if (header->version != ASSEMBLY_STORE_FORMAT_VERSION) { Helpers::abort_application ( LOG_ASSEMBLY, - Util::monodroid_strdup_printf ( - "Assembly store '%s' uses format version 0x%x, instead of the expected 0x%x", + std::format ( + "Assembly store '{}' uses format version {:x}, instead of the expected {:x}", entry_name.get (), header->version, ASSEMBLY_STORE_FORMAT_VERSION @@ -257,7 +264,7 @@ EmbeddedAssemblies::zip_load_assembly_store_entries (std::vector const& dynamic_local_string entry_name; bool assembly_store_found = false; - log_debug (LOG_ASSEMBLY, "Looking for assembly stores in APK ('%s')", assembly_store_file_path.data ()); + log_debug (LOG_ASSEMBLY, std::format ("Looking for assembly stores in APK ('{}')", assembly_store_file_path.data ())); for (size_t i = 0uz; i < num_entries; i++) { if (all_required_zip_entries_found ()) { need_to_scan_more_apks = false; @@ -291,7 +298,17 @@ EmbeddedAssemblies::zip_load_assembly_store_entries (std::vector const& apk_entry->offset = state.data_offset; apk_entry->fd = state.file_fd; - log_debug (LOG_ASSEMBLY, "Found a shared library entry %s (index: %u; name: %s; hash: 0x%llx; apk offset: %u)", entry_name.get (), number_of_zip_dso_entries, name, apk_entry->name_hash, apk_entry->offset); + log_debug ( + LOG_ASSEMBLY, + std::format ( + "Found a shared library entry {} (index: {}; name: {}; hash: {:x}; apk offset: {})", + entry_name.get (), + number_of_zip_dso_entries, + name, + apk_entry->name_hash, + apk_entry->offset + ) + ); number_of_zip_dso_entries++; } } @@ -307,7 +324,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)) { Helpers::abort_application ( LOG_ASSEMBLY, - Util::monodroid_strdup_printf ( + std::format ( "Failed to read the EOCD record from APK file %s", apk_name ) @@ -322,8 +339,8 @@ EmbeddedAssemblies::zip_load_entries (int fd, const char *apk_name, [[maybe_unus if (retval < 0) { Helpers::abort_application ( LOG_ASSEMBLY, - Util::monodroid_strdup_printf ( - "Failed to seek to central directory position in APK: %s. retval=%d errno=%d, File=%s", + std::format ( + "Failed to seek to central directory position in APK: {}. retval={} errno={}, File={}", std::strerror (errno), retval, errno, @@ -353,8 +370,8 @@ EmbeddedAssemblies::zip_load_entries (int fd, const char *apk_name, [[maybe_unus if (static_cast(nread) != cd_size) { Helpers::abort_application ( LOG_ASSEMBLY, - Util::monodroid_strdup_printf ( - "Failed to read Central Directory from APK: %s. nread=%d errno=%d File=%s", + std::format ( + "Failed to read Central Directory from APK: {}. nread={} errno={} File={}", std::strerror (errno), nread, errno, @@ -394,8 +411,9 @@ EmbeddedAssemblies::set_entry_data (XamarinAndroidBundledAssembly &entry, ZipEnt log_debug ( LOG_ASSEMBLY, - "Set bundled assembly entry data. file name: '%s'; entry name: '%s'; data size: %u", - entry.file_name, entry.name, entry.data_size + std::format ("Set bundled assembly entry data. file name: '{}'; entry name: '{}'; data size: {}", + entry.file_name, entry.name, entry.data_size + ) ); } @@ -417,14 +435,14 @@ EmbeddedAssemblies::zip_read_cd_info (int fd, uint32_t& cd_offset, uint32_t& cd_ // The simplest case - no file comment off_t ret = ::lseek (fd, -ZIP_EOCD_LEN, SEEK_END); if (ret < 0) { - log_error (LOG_ASSEMBLY, "Unable to seek into the APK to find ECOD: %s (ret: %d; errno: %d)", std::strerror (errno), ret, errno); + log_error (LOG_ASSEMBLY, std::format ("Unable to seek into the APK to find ECOD: {} (ret: {}; errno: {})", std::strerror (errno), ret, errno)); return false; } std::array eocd; ssize_t nread = ::read (fd, eocd.data (), eocd.size ()); if (nread < 0 || nread != eocd.size ()) { - log_error (LOG_ASSEMBLY, "Failed to read EOCD from the APK: %s (nread: %d; errno: %d)", std::strerror (errno), nread, errno); + log_error (LOG_ASSEMBLY, std::format ("Failed to read EOCD from the APK: {} (nread: {}; errno: {})", std::strerror (errno), nread, errno)); return false; } @@ -432,7 +450,7 @@ EmbeddedAssemblies::zip_read_cd_info (int fd, uint32_t& cd_offset, uint32_t& cd_ std::array signature; if (!zip_read_field (eocd, index, signature)) { - log_error (LOG_ASSEMBLY, "Failed to read EOCD signature"); + log_error (LOG_ASSEMBLY, "Failed to read EOCD signature"sv); return false; } @@ -444,7 +462,7 @@ EmbeddedAssemblies::zip_read_cd_info (int fd, uint32_t& cd_offset, uint32_t& cd_ constexpr size_t alloc_size = 65535uz + ZIP_EOCD_LEN; // 64k is the biggest comment size allowed ret = ::lseek (fd, static_cast(-alloc_size), SEEK_END); if (ret < 0) { - log_error (LOG_ASSEMBLY, "Unable to seek into the file to find ECOD before APK comment: %s (ret: %d; errno: %d)", std::strerror (errno), ret, errno); + log_error (LOG_ASSEMBLY, std::format ("Unable to seek into the file to find ECOD before APK comment: {} (ret: {}; errno: {})", std::strerror (errno), ret, errno)); return false; } @@ -453,7 +471,7 @@ EmbeddedAssemblies::zip_read_cd_info (int fd, uint32_t& cd_offset, uint32_t& cd_ nread = ::read (fd, buf.data (), buf.size ()); if (nread < 0 || static_cast(nread) != alloc_size) { - log_error (LOG_ASSEMBLY, "Failed to read EOCD and comment from the APK: %s (nread: %d; errno: %d)", std::strerror (errno), nread, errno); + log_error (LOG_ASSEMBLY, std::format ("Failed to read EOCD and comment from the APK: {} (nread: {}; errno: {})", std::strerror (errno), nread, errno)); return false; } @@ -470,7 +488,7 @@ EmbeddedAssemblies::zip_read_cd_info (int fd, uint32_t& cd_offset, uint32_t& cd_ } if (!found) { - log_error (LOG_ASSEMBLY, "Unable to find EOCD in the APK (with comment)"); + log_error (LOG_ASSEMBLY, "Unable to find EOCD in the APK (with comment)"sv); return false; } @@ -485,7 +503,13 @@ EmbeddedAssemblies::zip_adjust_data_offset (int fd, ZipEntryLoadState &state) no off_t result = ::lseek (fd, static_cast(state.local_header_offset), SEEK_SET); if (result < 0) { - log_error (LOG_ASSEMBLY, "Failed to seek to archive entry local header at offset %u. %s (result: %d; errno: %d)", state.local_header_offset, result, errno); + log_error ( + LOG_ASSEMBLY, + std::format ( + "Failed to seek to archive entry local header at offset {}. {} (result: {}; errno: {})", + state.local_header_offset, std::strerror (errno), result, errno + ) + ); return false; } @@ -494,32 +518,32 @@ EmbeddedAssemblies::zip_adjust_data_offset (int fd, ZipEntryLoadState &state) no ssize_t nread = ::read (fd, local_header.data (), local_header.size ()); if (nread < 0 || nread != ZIP_LOCAL_LEN) { - log_error (LOG_ASSEMBLY, "Failed to read local header at offset %u: %s (nread: %d; errno: %d)", state.local_header_offset, std::strerror (errno), nread, errno); + log_error (LOG_ASSEMBLY, std::format ("Failed to read local header at offset {}: {} (nread: {}; errno: {})", state.local_header_offset, std::strerror (errno), nread, errno)); return false; } size_t index = 0; if (!zip_read_field (local_header, index, signature)) { - log_error (LOG_ASSEMBLY, "Failed to read Local Header entry signature at offset %u", state.local_header_offset); + log_error (LOG_ASSEMBLY, std::format ("Failed to read Local Header entry signature at offset {}", state.local_header_offset)); return false; } if (memcmp (signature.data (), ZIP_LOCAL_MAGIC.data (), signature.size ()) != 0) { - log_error (LOG_ASSEMBLY, "Invalid Local Header entry signature at offset %u", state.local_header_offset); + log_error (LOG_ASSEMBLY, std::format ("Invalid Local Header entry signature at offset {}", state.local_header_offset)); return false; } uint16_t file_name_length; index = LH_FILE_NAME_LENGTH_OFFSET; if (!zip_read_field (local_header, index, file_name_length)) { - log_error (LOG_ASSEMBLY, "Failed to read Local Header 'file name length' field at offset %u", (state.local_header_offset + index)); + log_error (LOG_ASSEMBLY, std::format ("Failed to read Local Header 'file name length' field at offset {}", (state.local_header_offset + index))); return false; } uint16_t extra_field_length; index = LH_EXTRA_LENGTH_OFFSET; if (!zip_read_field (local_header, index, extra_field_length)) { - log_error (LOG_ASSEMBLY, "Failed to read Local Header 'extra field length' field at offset %u", (state.local_header_offset + index)); + log_error (LOG_ASSEMBLY, std::format ("Failed to read Local Header 'extra field length' field at offset {}", (state.local_header_offset + index))); return false; } @@ -539,17 +563,17 @@ EmbeddedAssemblies::zip_extract_cd_info (std::array const& buf static_assert (BufSize >= ZIP_EOCD_LEN, "Buffer too short for EOCD"); if (!zip_read_field (buf, EOCD_TOTAL_ENTRIES_OFFSET, cd_entries)) { - log_error (LOG_ASSEMBLY, "Failed to read EOCD 'total number of entries' field"); + log_error (LOG_ASSEMBLY, "Failed to read EOCD 'total number of entries' field"sv); return false; } if (!zip_read_field (buf, EOCD_CD_START_OFFSET, cd_offset)) { - log_error (LOG_ASSEMBLY, "Failed to read EOCD 'central directory size' field"); + log_error (LOG_ASSEMBLY, "Failed to read EOCD 'central directory size' field"sv); return false; } if (!zip_read_field (buf, EOCD_CD_SIZE_OFFSET, cd_size)) { - log_error (LOG_ASSEMBLY, "Failed to read EOCD 'central directory offset' field"); + log_error (LOG_ASSEMBLY, "Failed to read EOCD 'central directory offset' field"sv); return false; } @@ -561,7 +585,7 @@ force_inline bool EmbeddedAssemblies::zip_ensure_valid_params (T const& buf, size_t index, size_t to_read) noexcept { if (index + to_read > buf.size ()) { - log_error (LOG_ASSEMBLY, "Buffer too short to read %u bytes of data", to_read); + log_error (LOG_ASSEMBLY, std::format ("Buffer too short to read {} bytes of data", to_read)); return false; } @@ -637,51 +661,51 @@ EmbeddedAssemblies::zip_read_entry_info (std::vector const& buf, dynami std::array signature; if (!zip_read_field (buf, index, signature)) { - log_error (LOG_ASSEMBLY, "Failed to read Central Directory entry signature"); + log_error (LOG_ASSEMBLY, "Failed to read Central Directory entry signature"sv); return false; } if (memcmp (signature.data (), ZIP_CENTRAL_MAGIC.data (), signature.size ()) != 0) { - log_error (LOG_ASSEMBLY, "Invalid Central Directory entry signature"); + log_error (LOG_ASSEMBLY, "Invalid Central Directory entry signature"sv); return false; } index = state.buf_offset + CD_COMPRESSION_METHOD_OFFSET; if (!zip_read_field (buf, index, state.compression_method)) { - log_error (LOG_ASSEMBLY, "Failed to read Central Directory entry 'compression method' field"); + log_error (LOG_ASSEMBLY, "Failed to read Central Directory entry 'compression method' field"sv); return false; } index = state.buf_offset + CD_UNCOMPRESSED_SIZE_OFFSET;; if (!zip_read_field (buf, index, state.file_size)) { - log_error (LOG_ASSEMBLY, "Failed to read Central Directory entry 'uncompressed size' field"); + log_error (LOG_ASSEMBLY, "Failed to read Central Directory entry 'uncompressed size' field"sv); return false; } uint16_t file_name_length; index = state.buf_offset + CD_FILENAME_LENGTH_OFFSET; if (!zip_read_field (buf, index, file_name_length)) { - log_error (LOG_ASSEMBLY, "Failed to read Central Directory entry 'file name length' field"); + log_error (LOG_ASSEMBLY, "Failed to read Central Directory entry 'file name length' field"sv); return false; } uint16_t extra_field_length; index = state.buf_offset + CD_EXTRA_LENGTH_OFFSET; if (!zip_read_field (buf, index, extra_field_length)) { - log_error (LOG_ASSEMBLY, "Failed to read Central Directory entry 'extra field length' field"); + log_error (LOG_ASSEMBLY, "Failed to read Central Directory entry 'extra field length' field"sv); return false; } uint16_t comment_length; index = state.buf_offset + CD_COMMENT_LENGTH_OFFSET; if (!zip_read_field (buf, index, comment_length)) { - log_error (LOG_ASSEMBLY, "Failed to read Central Directory entry 'file comment length' field"); + log_error (LOG_ASSEMBLY, "Failed to read Central Directory entry 'file comment length' field"sv); return false; } index = state.buf_offset + CD_LOCAL_HEADER_POS_OFFSET; if (!zip_read_field (buf, index, state.local_header_offset)) { - log_error (LOG_ASSEMBLY, "Failed to read Central Directory entry 'relative offset of local header' field"); + log_error (LOG_ASSEMBLY, "Failed to read Central Directory entry 'relative offset of local header' field"sv); return false; } index += sizeof(state.local_header_offset); @@ -689,7 +713,7 @@ EmbeddedAssemblies::zip_read_entry_info (std::vector const& buf, dynami if (file_name_length == 0) { file_name.clear (); } else if (!zip_read_field (buf, index, file_name_length, file_name)) { - log_error (LOG_ASSEMBLY, "Failed to read Central Directory entry 'file name' field"); + log_error (LOG_ASSEMBLY, "Failed to read Central Directory entry 'file name' field"sv); return false; } diff --git a/src/native/monodroid/embedded-assemblies.cc b/src/native/monodroid/embedded-assemblies.cc index db3704f160f..cf056bbb7b3 100644 --- a/src/native/monodroid/embedded-assemblies.cc +++ b/src/native/monodroid/embedded-assemblies.cc @@ -86,13 +86,13 @@ EmbeddedAssemblies::get_assembly_data (uint8_t *data, uint32_t data_size, [[mayb auto header = reinterpret_cast(data); if (header->magic == COMPRESSED_DATA_MAGIC) { if (compressed_assemblies.descriptors == nullptr) [[unlikely]] { - Helpers::abort_application (LOG_ASSEMBLY, "Compressed assembly found but no descriptor defined"); + Helpers::abort_application (LOG_ASSEMBLY, "Compressed assembly found but no descriptor defined"sv); } if (header->descriptor_index >= compressed_assemblies.count) [[unlikely]] { Helpers::abort_application ( LOG_ASSEMBLY, - Util::monodroid_strdup_printf ( - "Invalid compressed assembly descriptor index %u", + std::format ( + "Invalid compressed assembly descriptor index {}", header->descriptor_index ) ); @@ -111,8 +111,8 @@ EmbeddedAssemblies::get_assembly_data (uint8_t *data, uint32_t data_size, [[mayb if (cad.data == nullptr) [[unlikely]] { Helpers::abort_application ( LOG_ASSEMBLY, - Util::monodroid_strdup_printf ( - "Invalid compressed assembly descriptor at %u: no data", + std::format ( + "Invalid compressed assembly descriptor at {}: no data", header->descriptor_index ) ); @@ -122,15 +122,15 @@ EmbeddedAssemblies::get_assembly_data (uint8_t *data, uint32_t data_size, [[mayb if (header->uncompressed_length > cad.uncompressed_file_size) { Helpers::abort_application ( LOG_ASSEMBLY, - Util::monodroid_strdup_printf ( - "Compressed assembly '%s' is larger than when the application was built (expected at most %u, got %u). Assemblies don't grow just like that!", + std::format ( + "Compressed assembly '{}' is larger than when the application was built (expected at most {}, got {}). Assemblies don't grow just like that!", name, cad.uncompressed_file_size, header->uncompressed_length ) ); } else { - log_debug (LOG_ASSEMBLY, "Compressed assembly '%s' is smaller than when the application was built. Adjusting accordingly.", name); + log_debug (LOG_ASSEMBLY, std::format ("Compressed assembly '{}' is smaller than when the application was built. Adjusting accordingly.", name)); } cad.uncompressed_file_size = header->uncompressed_length; } @@ -141,8 +141,8 @@ EmbeddedAssemblies::get_assembly_data (uint8_t *data, uint32_t data_size, [[mayb if (ret < 0) { Helpers::abort_application ( LOG_ASSEMBLY, - Util::monodroid_strdup_printf ( - "Decompression of assembly %s failed with code %d", + std::format ( + "Decompression of assembly {} failed with code {}", name, ret ) @@ -152,8 +152,8 @@ EmbeddedAssemblies::get_assembly_data (uint8_t *data, uint32_t data_size, [[mayb if (static_cast(ret) != cad.uncompressed_file_size) { Helpers::abort_application ( LOG_ASSEMBLY, - Util::monodroid_strdup_printf ( - "Decompression of assembly %s yielded a different size (expected %lu, got %u)", + std::format ( + "Decompression of assembly {} yielded a different size (expected {}, got {})", name, cad.uncompressed_file_size, static_cast(ret) @@ -190,7 +190,7 @@ EmbeddedAssemblies::map_runtime_file (XamarinAndroidBundledAssembly& file) noexc int fd; bool close_fd; if (!AndroidSystem::is_embedded_dso_mode_enabled ()) { - log_debug (LOG_ASSEMBLY, "Mapping a runtime file from filesystem"); + log_debug (LOG_ASSEMBLY, "Mapping a runtime file from filesystem"sv); close_fd = true; // file.file_fd refers to the directory where our files live @@ -228,7 +228,7 @@ EmbeddedAssemblies::map_runtime_file (XamarinAndroidBundledAssembly& file) noexc ); if (already_mapped) { - log_debug (LOG_ASSEMBLY, "Assembly %s already mmapped by another thread, unmapping our copy", file.name); + log_debug (LOG_ASSEMBLY, std::format ("Assembly {} already mmapped by another thread, unmapping our copy", file.name)); munmap (map_info.area, file.data_size); map_info.area = nullptr; } @@ -243,8 +243,19 @@ EmbeddedAssemblies::map_runtime_file (XamarinAndroidBundledAssembly& file) noexc header[j] = isprint (p [j]) ? p [j] : '.'; header [header.size () - 1] = '\0'; - log_info_nocheck (LOG_ASSEMBLY, "file-offset: % 8x start: %08p end: %08p len: % 12i zip-entry: %s name: %s [%s]", - (int) file.data_offset, file.data, file.data + file.data_size, (int) file.data_size, file.name, file.name, header.data ()); + log_info_nocheck ( + LOG_ASSEMBLY, + std::format ( + "file-offset: {:<8x} start: {:<8p} end: {:<8p} len: {:<12} zip-entry: {} name: {} [{}]", + file.data_offset, + static_cast(file.data), + reinterpret_cast(file.data + file.data_size), + file.data_size, + file.name, + file.name, + header.data () + ) + ); } } } @@ -278,7 +289,7 @@ EmbeddedAssemblies::load_bundled_assembly ( if (strcmp (assembly.name, abi_name.get ()) != 0) { return nullptr; } else { - log_debug (LOG_ASSEMBLY, "open_from_bundles: found architecture-specific: '%s'", abi_name.get ()); + log_debug (LOG_ASSEMBLY, std::format ("open_from_bundles: found architecture-specific: '{}'", abi_name.get ())); } } @@ -312,7 +323,7 @@ EmbeddedAssemblies::load_bundled_assembly ( if (debug_file.data != nullptr) { if (debug_file.data_size > std::numeric_limits::max ()) { - log_warn (LOG_ASSEMBLY, "Debug info file '%s' is too big for Mono to consume", debug_file.name); + log_warn (LOG_ASSEMBLY, std::format ("Debug info file '{}' is too big for Mono to consume", debug_file.name)); } else { mono_debug_open_image_from_memory (image, reinterpret_cast(debug_file.data), static_cast(debug_file.data_size)); } @@ -324,7 +335,7 @@ EmbeddedAssemblies::load_bundled_assembly ( MonoImageOpenStatus status; MonoAssembly *a = mono_assembly_load_from_full (image, name.get (), &status, ref_only); if (a == nullptr || status != MonoImageOpenStatus::MONO_IMAGE_OK) { - log_warn (LOG_ASSEMBLY, "Failed to load managed assembly '%s'. %s", name.get (), mono_image_strerror (status)); + log_warn (LOG_ASSEMBLY, std::format ("Failed to load managed assembly '{}'. {}", name.get (), mono_image_strerror (status))); return nullptr; } @@ -339,7 +350,7 @@ EmbeddedAssemblies::individual_assemblies_open_from_bundles (dynamic_local_strin name.append (SharedConstants::DLL_EXTENSION); } - log_debug (LOG_ASSEMBLY, "individual_assemblies_open_from_bundles: looking for bundled name: '%s'", name.get ()); + log_debug (LOG_ASSEMBLY, std::format ("individual_assemblies_open_from_bundles: looking for bundled name: '{}'", name.get ())); dynamic_local_string abi_name; abi_name @@ -386,19 +397,19 @@ force_inline MonoAssembly* EmbeddedAssemblies::assembly_store_open_from_bundles (dynamic_local_string& name, TLoaderData loader_data, bool ref_only) noexcept { hash_t name_hash = xxhash::hash (name.get (), name.length ()); - log_debug (LOG_ASSEMBLY, "assembly_store_open_from_bundles: looking for bundled name: '%s' (hash 0x%zx)", name.get (), name_hash); + log_debug (LOG_ASSEMBLY, std::format ("assembly_store_open_from_bundles: looking for bundled name: '{}' (hash {:x})", name.get (), name_hash)); const AssemblyStoreIndexEntry *hash_entry = find_assembly_store_entry (name_hash, assembly_store_hashes, assembly_store.index_entry_count); if (hash_entry == nullptr) { - log_warn (LOG_ASSEMBLY, "Assembly '%s' (hash 0x%zx) not found", name.get (), name_hash); + log_warn (LOG_ASSEMBLY, std::format ("Assembly '{}' (hash {:x}) not found", name.get (), name_hash)); return nullptr; } if (hash_entry->descriptor_index >= assembly_store.assembly_count) { Helpers::abort_application ( LOG_ASSEMBLY, - Util::monodroid_strdup_printf ( - "Invalid assembly descriptor index %u, exceeds the maximum value of %u", + std::format ( + "Invalid assembly descriptor index {}, exceeds the maximum value of {}", hash_entry->descriptor_index, assembly_store.assembly_count - 1 ) @@ -419,15 +430,16 @@ EmbeddedAssemblies::assembly_store_open_from_bundles (dynamic_local_stringdata_size, - assembly_runtime_info.descriptor->debug_data_size, - assembly_runtime_info.descriptor->config_data_size, - name.get () + std::format ("Mapped: image_data == {:p}; debug_info_data == {:p}; config_data == {:p}; descriptor == {:p}; data size == {}; debug data size == {}; config data size == {}; name == '{}'", + static_cast(assembly_runtime_info.image_data), + static_cast(assembly_runtime_info.debug_info_data), + static_cast(assembly_runtime_info.config_data), + static_cast(assembly_runtime_info.descriptor), + assembly_runtime_info.descriptor->data_size, + assembly_runtime_info.descriptor->debug_data_size, + assembly_runtime_info.descriptor->config_data_size, + name.get () + ) ); } @@ -437,7 +449,7 @@ EmbeddedAssemblies::assembly_store_open_from_bundles (dynamic_local_string 0) { @@ -611,26 +623,26 @@ EmbeddedAssemblies::typemap_java_to_managed ([[maybe_unused]] hash_t hash, const entry = binary_search (java_type_name.get (), type_map.java_to_managed, type_map.entry_count); if (entry == nullptr) [[unlikely]] { - log_info (LOG_ASSEMBLY, "typemap: unable to find mapping to a managed type from Java type '%s'", java_type_name.get ()); + log_info (LOG_ASSEMBLY, std::format ("typemap: unable to find mapping to a managed type from Java type '{}'", java_type_name.get ())); return nullptr; } const char *managed_type_name = entry->to; if (managed_type_name == nullptr) { - log_debug (LOG_ASSEMBLY, "typemap: Java type '%s' maps either to an open generic type or an interface type.", java_type_name.get ()); + log_debug (LOG_ASSEMBLY, std::format ("typemap: Java type '{}' maps either to an open generic type or an interface type.", java_type_name.get ())); return nullptr; } - log_debug (LOG_DEFAULT, "typemap: Java type '%s' corresponds to managed type '%s'", java_type_name.get (), managed_type_name); + log_debug (LOG_DEFAULT, std::format ("typemap: Java type '{}' corresponds to managed type '{}'", java_type_name.get (), managed_type_name)); MonoType *type = mono_reflection_type_from_name (const_cast(managed_type_name), nullptr); if (type == nullptr) [[unlikely]] { - log_info (LOG_ASSEMBLY, "typemap: managed type '%s' (mapped from Java type '%s') could not be loaded", managed_type_name, java_type_name.get ()); + log_info (LOG_ASSEMBLY, std::format ("typemap: managed type '{}' (mapped from Java type '{}') could not be loaded", managed_type_name, java_type_name.get ())); return nullptr; } MonoReflectionType *ret = mono_type_get_object (Util::get_current_domain (), type); if (ret == nullptr) [[unlikely]] { - log_warn (LOG_ASSEMBLY, "typemap: unable to instantiate managed type '%s'", managed_type_name); + log_warn (LOG_ASSEMBLY, std::format ("typemap: unable to instantiate managed type '{}'", managed_type_name)); return nullptr; } @@ -650,16 +662,16 @@ EmbeddedAssemblies::typemap_java_to_managed (hash_t hash, const MonoString *java TypeMapModule *module = java_entry != nullptr && java_entry->module_index < map_module_count ? &map_modules[java_entry->module_index] : nullptr; if (module == nullptr) { if (java_entry == nullptr) { - log_info (LOG_ASSEMBLY, "typemap: unable to find mapping to a managed type from Java type '%s' (hash 0x%zx)", to_utf8 (java_type_name).get (), hash); + log_info (LOG_ASSEMBLY, std::format ("typemap: unable to find mapping to a managed type from Java type '{}' (hash {:x})", to_utf8 (java_type_name).get (), hash)); } else { - log_warn (LOG_ASSEMBLY, "typemap: mapping from Java type '%s' to managed type has invalid module index %u", to_utf8 (java_type_name).get (), java_entry->module_index); + log_warn (LOG_ASSEMBLY, std::format ("typemap: mapping from Java type '{}' to managed type has invalid module index {}", to_utf8 (java_type_name).get (), java_entry->module_index)); } return nullptr; } const TypeMapModuleEntry *entry = binary_search (java_entry->type_token_id, module->map, module->entry_count); if (entry == nullptr) { - log_info (LOG_ASSEMBLY, "typemap: unable to find mapping from Java type '%s' to managed type with token ID %u in module [%s]", to_utf8 (java_type_name).get (), java_entry->type_token_id, MonoGuidString (module->module_uuid).get ()); + log_info (LOG_ASSEMBLY, std::format ("typemap: unable to find mapping from Java type '{}' to managed type with token ID {} in module [{}]", to_utf8 (java_type_name).get (), java_entry->type_token_id, MonoGuidString (module->module_uuid).get ())); return nullptr; } @@ -667,14 +679,14 @@ EmbeddedAssemblies::typemap_java_to_managed (hash_t hash, const MonoString *java module->image = mono_image_loaded (module->assembly_name); if (module->image == nullptr) { - log_debug (LOG_ASSEMBLY, "typemap: assembly '%s' hasn't been loaded yet, attempting a full load", module->assembly_name); + log_debug (LOG_ASSEMBLY, std::format ("typemap: assembly '{}' hasn't been loaded yet, attempting a full load", module->assembly_name)); // Fake a request from MonoVM to load the assembly. MonoAssemblyName *assembly_name = mono_assembly_name_new (module->assembly_name); MonoAssembly *assm; if (assembly_name == nullptr) { - log_error (LOG_ASSEMBLY, "typemap: failed to create Mono assembly name for '%s'", module->assembly_name); + log_error (LOG_ASSEMBLY, std::format ("typemap: failed to create Mono assembly name for '{}'", module->assembly_name)); assm = nullptr; } else { MonoAssemblyLoadContextGCHandle alc_gchandle = mono_alc_get_default_gchandle (); @@ -683,22 +695,22 @@ EmbeddedAssemblies::typemap_java_to_managed (hash_t hash, const MonoString *java } if (assm == nullptr) { - log_warn (LOG_ASSEMBLY, "typemap: failed to load managed assembly '%s'", module->assembly_name); + log_warn (LOG_ASSEMBLY, std::format ("typemap: failed to load managed assembly '{}'", module->assembly_name)); } else { module->image = mono_assembly_get_image (assm); } } if (module->image == nullptr) { - log_error (LOG_ASSEMBLY, "typemap: unable to load assembly '%s' when looking up managed type corresponding to Java type '%s'", module->assembly_name, to_utf8 (java_type_name).get ()); + log_error (LOG_ASSEMBLY, std::format ("typemap: unable to load assembly '{}' when looking up managed type corresponding to Java type '{}'", module->assembly_name, to_utf8 (java_type_name).get ())); return nullptr; } } - log_debug (LOG_ASSEMBLY, "typemap: java type '%s' corresponds to managed token id %u (0x%x)", to_utf8 (java_type_name).get (), java_entry->type_token_id, java_entry->type_token_id); + log_debug (LOG_ASSEMBLY, std::format ("typemap: java type '{}' corresponds to managed token id {} ({:x})", to_utf8 (java_type_name).get (), java_entry->type_token_id, java_entry->type_token_id)); MonoClass *klass = mono_class_get (module->image, java_entry->type_token_id); if (klass == nullptr) [[unlikely]] { - log_error (LOG_ASSEMBLY, "typemap: unable to find managed type with token ID %u in assembly '%s', corresponding to Java type '%s'", java_entry->type_token_id, module->assembly_name, to_utf8 (java_type_name).get ()); + log_error (LOG_ASSEMBLY, std::format ("typemap: unable to find managed type with token ID {} in assembly '{}', corresponding to Java type '{}'", java_entry->type_token_id, module->assembly_name, to_utf8 (java_type_name).get ())); return nullptr; } @@ -709,7 +721,7 @@ EmbeddedAssemblies::typemap_java_to_managed (hash_t hash, const MonoString *java MonoReflectionType *ret = mono_type_get_object (domain, mono_class_get_type (klass)); if (ret == nullptr) { - log_warn (LOG_ASSEMBLY, "typemap: unable to instantiate managed type with token ID %u in assembly '%s', corresponding to Java type '%s'", java_entry->type_token_id, module->assembly_name, to_utf8 (java_type_name).get ()); + log_warn (LOG_ASSEMBLY, std::format ("typemap: unable to instantiate managed type with token ID {} in assembly '{}', corresponding to Java type '{}'", java_entry->type_token_id, module->assembly_name, to_utf8 (java_type_name).get ())); return nullptr; } @@ -727,7 +739,7 @@ EmbeddedAssemblies::typemap_java_to_managed (MonoString *java_type) noexcept } if (java_type == nullptr) [[unlikely]]{ - log_warn (LOG_ASSEMBLY, "typemap: null 'java_type' passed to 'typemap_java_to_managed'"); + log_warn (LOG_ASSEMBLY, "typemap: null 'java_type' passed to 'typemap_java_to_managed'"sv); return nullptr; } @@ -735,7 +747,7 @@ EmbeddedAssemblies::typemap_java_to_managed (MonoString *java_type) noexcept // number of bytes. int name_len = mono_string_length (java_type) << 1; if (name_len <= 0) [[unlikely]] { - log_warn (LOG_ASSEMBLY, "typemap: empty 'java_type' passed to 'typemap_java_to_managed'"); + log_warn (LOG_ASSEMBLY, "typemap: empty 'java_type' passed to 'typemap_java_to_managed'"sv); return nullptr; } @@ -774,7 +786,7 @@ EmbeddedAssemblies::typemap_managed_to_java ([[maybe_unused]] MonoType *type, Mo const TypeMapEntry *entry = typemap_managed_to_java (full_name.get ()); if (entry == nullptr) [[unlikely]] { - log_info (LOG_ASSEMBLY, "typemap: unable to find mapping to a Java type from managed type '%s'", full_name.get ()); + log_info (LOG_ASSEMBLY, std::format ("typemap: unable to find mapping to a Java type from managed type '{}'", full_name.get ())); return nullptr; } @@ -793,58 +805,59 @@ EmbeddedAssemblies::typemap_managed_to_java ([[maybe_unused]] MonoType *type, Mo const TypeMapModule *match = mvid != nullptr ? binary_search (mvid, map_modules, map_module_count) : nullptr; if (match == nullptr) { if (mvid == nullptr) { - log_warn (LOG_ASSEMBLY, "typemap: no mvid specified in call to typemap_managed_to_java"); + log_warn (LOG_ASSEMBLY, "typemap: no mvid specified in call to typemap_managed_to_java"sv); } else { - log_info (LOG_ASSEMBLY, "typemap: module matching MVID [%s] not found.", MonoGuidString (mvid).get ()); + log_info (LOG_ASSEMBLY, std::format ("typemap: module matching MVID [{}] not found.", MonoGuidString (mvid).get ())); } return nullptr; } uint32_t token = mono_class_get_type_token (klass); - log_debug (LOG_ASSEMBLY, "typemap: MVID [%s] maps to assembly %s, looking for token %d (0x%x), table index %d", MonoGuidString (mvid).get (), match->assembly_name, token, token, token & 0x00FFFFFF); + log_debug (LOG_ASSEMBLY, std::format ("typemap: MVID [{}] maps to assembly {}, looking for token {} ({:x}), table index {}", MonoGuidString (mvid).get (), match->assembly_name, token, token, token & 0x00FFFFFF)); // Each map entry is a pair of 32-bit integers: [TypeTokenID][JavaMapArrayIndex] const TypeMapModuleEntry *entry = match->map != nullptr ? binary_search (token, match->map, match->entry_count) : nullptr; if (entry == nullptr) { if (match->map == nullptr) { - log_warn (LOG_ASSEMBLY, "typemap: module with mvid [%s] has no associated type map.", MonoGuidString (mvid).get ()); + log_warn (LOG_ASSEMBLY, std::format ("typemap: module with MVID [{}] has no associated type map.", MonoGuidString (mvid).get ())); return nullptr; } if (match->duplicate_count > 0 && match->duplicate_map != nullptr) { - log_debug (LOG_ASSEMBLY, "typemap: searching module [%s] duplicate map for token %u (0x%x)", MonoGuidString (mvid).get (), token, token); + log_debug (LOG_ASSEMBLY, std::format ("typemap: searching module [{}] duplicate map for token {} ({:x})", MonoGuidString (mvid).get (), token, token)); entry = binary_search (token, match->duplicate_map, match->duplicate_count); } if (entry == nullptr) { - log_info (LOG_ASSEMBLY, "typemap: type with token %d (0x%x) in module {%s} (%s) not found.", token, token, MonoGuidString (mvid).get (), match->assembly_name); + log_info (LOG_ASSEMBLY, std::format ("typemap: type with token {} ({:x}) in module [{}] ({}) not found.", token, token, MonoGuidString (mvid).get (), match->assembly_name)); return nullptr; } } if (entry->java_map_index >= java_type_count) [[unlikely]] { - log_warn (LOG_ASSEMBLY, "typemap: type with token %d (0x%x) in module {%s} (%s) has invalid Java type index %u", token, token, MonoGuidString (mvid).get (), match->assembly_name, entry->java_map_index); + log_warn (LOG_ASSEMBLY, std::format ("typemap: type with token {} ({:x}) in module [{}] ({}) has invalid Java type index {}", token, token, MonoGuidString (mvid).get (), match->assembly_name, entry->java_map_index)); return nullptr; } TypeMapJava const& java_entry = map_java[entry->java_map_index]; if (java_entry.java_name_index >= java_type_count) [[unlikely]] { - log_warn (LOG_ASSEMBLY, "typemap: type with token %d (0x%x) in module {%s} (%s) points to invalid Java type at index %u (invalid type name index %u)", token, token, MonoGuidString (mvid).get (), match->assembly_name, entry->java_map_index, java_entry.java_name_index); + log_warn (LOG_ASSEMBLY, std::format ("typemap: type with token {} ({:x}) in module [{}] ({}) points to invalid Java type at index {} (invalid type name index {})", token, token, MonoGuidString (mvid).get (), match->assembly_name, entry->java_map_index, java_entry.java_name_index)); return nullptr; } const char *ret = java_type_names[java_entry.java_name_index]; if (ret == nullptr) [[unlikely]] { - log_warn (LOG_ASSEMBLY, "typemap: empty Java type name returned for entry at index %u", entry->java_map_index); + log_warn (LOG_ASSEMBLY, std::format ("typemap: empty Java type name returned for entry at index {}", entry->java_map_index)); } log_debug ( LOG_ASSEMBLY, - "typemap: type with token %d (0x%x) in module {%s} (%s) corresponds to Java type '%s'", - token, - token, - MonoGuidString (mvid).get (), - match->assembly_name, - ret + std::format ("typemap: type with token {} ({:x}) in module [{}] ({}) corresponds to Java type '{}'", + token, + token, + MonoGuidString (mvid).get (), + match->assembly_name, + ret + ) ); return ret; @@ -862,7 +875,7 @@ EmbeddedAssemblies::typemap_managed_to_java (MonoReflectionType *reflection_type MonoType *type = mono_reflection_type_get_type (reflection_type); if (type == nullptr) { - log_warn (LOG_ASSEMBLY, "Failed to map reflection type to MonoType"); + log_warn (LOG_ASSEMBLY, "Failed to map reflection type to MonoType"sv); return nullptr; } @@ -891,8 +904,8 @@ EmbeddedAssemblies::md_mmap_apk_file (int fd, uint32_t offset, size_t size, cons if (mmap_info.area == MAP_FAILED) { Helpers::abort_application ( LOG_ASSEMBLY, - Util::monodroid_strdup_printf ( - "Could not mmap APK fd %d: %s; File=%s", + std::format ( + "Could not mmap APK fd {}: {}; File={}", fd, strerror (errno), filename @@ -904,9 +917,19 @@ EmbeddedAssemblies::md_mmap_apk_file (int fd, uint32_t offset, size_t size, cons file_info.area = (void*)((const char*)mmap_info.area + offsetFromPage); file_info.size = size; - log_info (LOG_ASSEMBLY, " mmap_start: %08p mmap_end: %08p mmap_len: % 12u file_start: %08p file_end: %08p file_len: % 12u apk descriptor: %d file: %s", - mmap_info.area, reinterpret_cast (mmap_info.area) + mmap_info.size, mmap_info.size, - file_info.area, reinterpret_cast (file_info.area) + file_info.size, file_info.size, fd, filename); + log_info ( + LOG_ASSEMBLY, + std::format (" mmap_start: {:<8p}; mmap_end: {:<8p} mmap_len: {:<12} file_start: {:<8p} file_end: {:<8p} file_len: {:<12} apk descriptor: {} file: {}", + mmap_info.area, + reinterpret_cast(reinterpret_cast (mmap_info.area) + mmap_info.size), + mmap_info.size, + file_info.area, + reinterpret_cast(reinterpret_cast (file_info.area) + file_info.size), + file_info.size, + fd, + filename + ) + ); return file_info; } @@ -919,13 +942,13 @@ EmbeddedAssemblies::gather_bundled_assemblies_from_apk (const char* apk, monodro if ((fd = open (apk, O_RDONLY)) < 0) { Helpers::abort_application ( LOG_ASSEMBLY, - Util::monodroid_strdup_printf ( - "ERROR: Unable to load application package %s.", + std::format ( + "ERROR: Unable to load application package {}.", apk ) ); } - log_debug (LOG_ASSEMBLY, "APK %s FD: %d", apk, fd); + log_debug (LOG_ASSEMBLY, std::format ("APK {} FD: {}", apk, fd)); zip_load_entries (fd, apk, should_register); } @@ -952,40 +975,40 @@ EmbeddedAssemblies::typemap_read_header ([[maybe_unused]] int dir_fd, const char struct stat sbuf; int res = fstatat (dir_fd, file_path, &sbuf, 0); if (res < 0) { - log_error (LOG_ASSEMBLY, "typemap: failed to stat %s file '%s/%s': %s", file_type, dir_path, file_path, strerror (errno)); + log_error (LOG_ASSEMBLY, std::format ("typemap: failed to stat {} file '{}/{}': {}", file_type, dir_path, file_path, strerror (errno))); return false; } file_size = static_cast(sbuf.st_size); if (file_size < sizeof (header)) { - log_error (LOG_ASSEMBLY, "typemap: %s file '%s/%s' is too small (must be at least %u bytes)", file_type, dir_path, file_path, sizeof (header)); + log_error (LOG_ASSEMBLY, std::format ("typemap: {} file '{}/{}' is too small (must be at least {} bytes)", file_type, dir_path, file_path, sizeof (header))); return false; } fd = openat (dir_fd, file_path, O_RDONLY); if (fd < 0) { - log_error (LOG_ASSEMBLY, "typemap: failed to open %s file %s/%s for reading: %s", file_type, dir_path, file_path, strerror (errno)); + log_error (LOG_ASSEMBLY, std::format ("typemap: failed to open {} file {}/{} for reading: {}", file_type, dir_path, file_path, strerror (errno))); return false; } ssize_t nread = do_read (fd, &header, sizeof (header)); if (nread <= 0) { if (nread < 0) { - log_error (LOG_ASSEMBLY, "typemap: failed to read %s file header from '%s/%s': %s", file_type, dir_path, file_path, strerror (errno)); + log_error (LOG_ASSEMBLY, std::format ("typemap: failed to read {} file header from '{}/{}': {}", file_type, dir_path, file_path, strerror (errno))); } else { - log_error (LOG_ASSEMBLY, "typemap: end of file while reading %s file header from '%s/%s'", file_type, dir_path, file_path); + log_error (LOG_ASSEMBLY, std::format ("typemap: end of file while reading {} file header from '{}/{}'", file_type, dir_path, file_path)); } return false; } if (header.magic != expected_magic) { - log_error (LOG_ASSEMBLY, "typemap: invalid magic value in the %s file header from '%s/%s': expected 0x%X, got 0x%X", file_type, dir_path, file_path, expected_magic, header.magic); + log_error (LOG_ASSEMBLY, std::format ("typemap: invalid magic value in the {} file header from '{}/{}': expected {:x}, got {:x}", file_type, dir_path, file_path, expected_magic, header.magic)); return false; } if (header.version != MODULE_FORMAT_VERSION) { - log_error (LOG_ASSEMBLY, "typemap: incompatible %s format version. This build supports only version %u, file '%s/%s' uses version %u", file_type, MODULE_FORMAT_VERSION, dir_path, file_path, header.version); + log_error (LOG_ASSEMBLY, std::format ("typemap: incompatible {} format version. This build supports only version {}, file '{}/{}' uses version {}", file_type, MODULE_FORMAT_VERSION, dir_path, file_path, header.version)); return false; } @@ -998,14 +1021,14 @@ EmbeddedAssemblies::typemap_load_index (TypeMapIndexHeader &header, size_t file_ size_t entry_size = header.module_file_name_width; size_t data_size = entry_size * type_map_count; if (sizeof(header) + data_size > file_size) { - log_error (LOG_ASSEMBLY, "typemap: index file is too small, expected %u, found %u bytes", data_size + sizeof(header), file_size); + log_error (LOG_ASSEMBLY, std::format ("typemap: index file is too small, expected {}, found {} bytes", data_size + sizeof(header), file_size)); return nullptr; } auto data = std::make_unique (data_size); ssize_t nread = do_read (index_fd, data.get (), data_size); if (nread != static_cast(data_size)) { - log_error (LOG_ASSEMBLY, "typemap: failed to read %u bytes from index file. %s", data_size, strerror (errno)); + log_error (LOG_ASSEMBLY, std::format ("typemap: failed to read {} bytes from index file. {}", data_size, strerror (errno))); return nullptr; } @@ -1021,7 +1044,7 @@ EmbeddedAssemblies::typemap_load_index (TypeMapIndexHeader &header, size_t file_ std::unique_ptr EmbeddedAssemblies::typemap_load_index (int dir_fd, const char *dir_path, const char *index_path) { - log_debug (LOG_ASSEMBLY, "typemap: loading TypeMap index file '%s/%s'", dir_path, index_path); + log_debug (LOG_ASSEMBLY, std::format ("typemap: loading TypeMap index file '{}/{}'", dir_path, index_path)); TypeMapIndexHeader header; size_t file_size; @@ -1048,7 +1071,7 @@ EmbeddedAssemblies::typemap_load_file (BinaryTypeMapHeader &header, const char * ssize_t nread = do_read (file_fd, module.assembly_name, header.assembly_name_length); if (nread != static_cast(header.assembly_name_length)) { - log_error (LOG_ASSEMBLY, "tyemap: failed to read map assembly name from '%s/%s': %s", dir_path, file_path, strerror (errno)); + log_error (LOG_ASSEMBLY, std::format ("typemap: failed to read map assembly name from '{}/{}': {}", dir_path, file_path, strerror (errno))); return false; } @@ -1057,8 +1080,16 @@ EmbeddedAssemblies::typemap_load_file (BinaryTypeMapHeader &header, const char * log_debug ( LOG_ASSEMBLY, - "typemap: '%s/%s':: entry count == %u; Java name field width == %u; Managed name width == %u; assembly name length == %u; assembly name == %s", - dir_path, file_path, header.entry_count, header.java_name_width, header.managed_name_width, header.assembly_name_length, module.assembly_name + std::format ( + "typemap: '{}/{}':: entry count == {}; Java name field width == {}; Managed name width == {}; assembly name length == {}; assembly name == {}", + dir_path, + file_path, + header.entry_count, + header.java_name_width, + header.managed_name_width, + header.assembly_name_length, + module.assembly_name + ) ); // [name][index] @@ -1072,7 +1103,7 @@ EmbeddedAssemblies::typemap_load_file (BinaryTypeMapHeader &header, const char * module.data = new uint8_t [data_size]; nread = do_read (file_fd, module.data, data_size); if (nread != static_cast(data_size)) { - log_error (LOG_ASSEMBLY, "tyemap: failed to read map data from '%s/%s': %s", dir_path, file_path, strerror (errno)); + log_error (LOG_ASSEMBLY, std::format ("typemap: failed to read map data from '{}/{}': {}", dir_path, file_path, strerror (errno))); return false; } @@ -1116,7 +1147,7 @@ EmbeddedAssemblies::typemap_load_file (BinaryTypeMapHeader &header, const char * bool EmbeddedAssemblies::typemap_load_file (int dir_fd, const char *dir_path, const char *file_path, TypeMap &module) { - log_debug (LOG_ASSEMBLY, "typemap: loading TypeMap file '%s/%s'", dir_path, file_path); + log_debug (LOG_ASSEMBLY, std::format ("typemap: loading TypeMap file '{}/{}'", dir_path, file_path)); bool ret = true; BinaryTypeMapHeader header; @@ -1155,7 +1186,7 @@ EmbeddedAssemblies::register_from_apk (const char *apk_file, monodroid_should_re gather_bundled_assemblies_from_apk (apk_file, should_register); - log_info (LOG_ASSEMBLY, "Package '%s' contains %i assemblies", apk_file, number_of_found_assemblies - prev); + log_info (LOG_ASSEMBLY, std::format ("Package '{}' contains {} assemblies", apk_file, number_of_found_assemblies - prev)); return number_of_found_assemblies; } @@ -1259,10 +1290,10 @@ EmbeddedAssemblies::maybe_register_blob_from_filesystem ( force_inline size_t EmbeddedAssemblies::register_from_filesystem (const char *lib_dir_path,bool look_for_mangled_names, monodroid_should_register should_register) noexcept { - log_debug (LOG_ASSEMBLY, "Looking for assemblies in '%s'", lib_dir_path); + log_debug (LOG_ASSEMBLY, std::format ("Looking for assemblies in '{}'", lib_dir_path)); DIR *lib_dir = opendir (lib_dir_path); // TODO: put it in a scope guard at some point if (lib_dir == nullptr) { - log_warn (LOG_ASSEMBLY, "Unable to open app library directory '%s': %s", lib_dir_path, std::strerror (errno)); + log_warn (LOG_ASSEMBLY, std::format ("Unable to open app library directory '{}': {}", lib_dir_path, std::strerror (errno))); return 0; } @@ -1271,14 +1302,14 @@ EmbeddedAssemblies::register_from_filesystem (const char *lib_dir_path,bool look int dir_fd = dirfd (lib_dir); if (dir_fd < 0) [[unlikely]] { - log_warn (LOG_ASSEMBLY, "Unable to obtain file descriptor for directory '%s': %s", lib_dir_path, std::strerror (errno)); + log_warn (LOG_ASSEMBLY, std::format ("Unable to obtain file descriptor for directory '{}': {}", lib_dir_path, std::strerror (errno))); closedir (lib_dir); return 0; } state.file_fd = dup (dir_fd); if (state.file_fd < 0) [[unlikely]] { - log_warn (LOG_ASSEMBLY, "Unable to duplicate file descriptor %d for directory '%s': %s", dir_fd, lib_dir_path, std::strerror (errno)); + log_warn (LOG_ASSEMBLY, std::format ("Unable to duplicate file descriptor {} for directory '{}': {}", dir_fd, lib_dir_path, std::strerror (errno))); closedir (lib_dir); return 0; } @@ -1295,7 +1326,7 @@ EmbeddedAssemblies::register_from_filesystem (const char *lib_dir_path,bool look dirent *cur = readdir (lib_dir); if (cur == nullptr) { if (errno != 0) { - log_warn (LOG_ASSEMBLY, "Failed to open a directory entry from '%s': %s", lib_dir_path, std::strerror (errno)); + log_warn (LOG_ASSEMBLY, std::format ("Failed to open a directory entry from '{}': {}", lib_dir_path, std::strerror (errno))); continue; // keep going, no harm } break; // No more entries, we're done @@ -1315,7 +1346,7 @@ EmbeddedAssemblies::register_from_filesystem (const char *lib_dir_path,bool look // ...and we can handle the runtime config entry if (!runtime_config_blob_found && std::strncmp (cur->d_name, SharedConstants::RUNTIME_CONFIG_BLOB_NAME.data (), SharedConstants::RUNTIME_CONFIG_BLOB_NAME.size ()) == 0) { - log_debug (LOG_ASSEMBLY, "Mapping runtime config blob from '%s'", cur->d_name); + log_debug (LOG_ASSEMBLY, std::format ("Mapping runtime config blob from '{}'", cur->d_name)); auto file_size = Util::get_file_size_at (state.file_fd, cur->d_name); if (!file_size) { continue; @@ -1344,7 +1375,7 @@ EmbeddedAssemblies::register_from_filesystem (const char *lib_dir_path,bool look size_t EmbeddedAssemblies::register_from_filesystem (monodroid_should_register should_register) noexcept { - log_debug (LOG_ASSEMBLY, "Registering assemblies from the filesystem"); + log_debug (LOG_ASSEMBLY, "Registering assemblies from the filesystem"sv); constexpr bool LookForMangledNames = true; size_t assembly_count = register_from_filesystem ( AndroidSystem::app_lib_directories[0], @@ -1362,6 +1393,6 @@ EmbeddedAssemblies::register_from_filesystem (monodroid_should_register should_r ); #endif - log_debug (LOG_ASSEMBLY, "Found %zu assemblies on the filesystem", assembly_count); + log_debug (LOG_ASSEMBLY, std::format ("Found {} assemblies on the filesystem", assembly_count)); return assembly_count; } diff --git a/src/native/monodroid/embedded-assemblies.hh b/src/native/monodroid/embedded-assemblies.hh index ff153942724..21fc0de80b8 100644 --- a/src/native/monodroid/embedded-assemblies.hh +++ b/src/native/monodroid/embedded-assemblies.hh @@ -20,6 +20,7 @@ #include #include "archive-dso-stub-config.hh" +#include "log_types.hh" #include "strings.hh" #include "xamarin-app.hh" #include "cpp-util.hh" @@ -309,7 +310,7 @@ namespace xamarin::android::internal { elf_header->e_ident[EI_MAG1] != ELFMAG1 || elf_header->e_ident[EI_MAG2] != ELFMAG2 || elf_header->e_ident[EI_MAG3] != ELFMAG3) { - log_debug (LOG_ASSEMBLY, "Not an ELF image: %s", file_name); + log_debug (LOG_ASSEMBLY, std::format ("Not an ELF image: {}", file_name)); // Not an ELF image, just return what we mmapped before return { map_info.area, map_info.size }; } @@ -328,7 +329,7 @@ namespace xamarin::android::internal { static void store_mapped_runtime_config_data (md_mmap_info const& map_info, const char *file_name) noexcept { auto [payload_start, payload_size] = get_wrapper_dso_payload_pointer_and_size (map_info, file_name); - log_debug (LOG_ASSEMBLY, "Runtime config: payload pointer %p ; size %zu", payload_start, payload_size); + log_debug (LOG_ASSEMBLY, std::format ("Runtime config: payload pointer {:p} ; size {}", payload_start, payload_size)); runtime_config_data = payload_start; runtime_config_data_size = payload_size; runtime_config_blob_found = true; @@ -430,7 +431,7 @@ namespace xamarin::android::internal { } } } - log_debug (LOG_ASSEMBLY, "Unmangled name to '%s'", name.get ()); + log_debug (LOG_ASSEMBLY, std::format ("Unmangled name to '{}'", name.get ())); }; private: diff --git a/src/native/shared/CMakeLists.txt b/src/native/shared/CMakeLists.txt index 4a3bb7ece18..75f4b0c4616 100644 --- a/src/native/shared/CMakeLists.txt +++ b/src/native/shared/CMakeLists.txt @@ -4,7 +4,6 @@ set(LIB_ALIAS xa::shared) set(XA_SHARED_SOURCES helpers.cc log_functions.cc - new_delete.cc ) add_clang_check_sources("${XA_SHARED_SOURCES};") diff --git a/src/native/shared/helpers.hh b/src/native/shared/helpers.hh index 3c6c16ca6a3..3a2bc67dfb5 100644 --- a/src/native/shared/helpers.hh +++ b/src/native/shared/helpers.hh @@ -3,9 +3,14 @@ #include #include +#include +#include #include #include "platform-compat.hh" +#include "log_types.hh" + +using namespace std::string_view_literals; namespace xamarin::android { @@ -46,10 +51,30 @@ namespace xamarin::android [[noreturn]] static void abort_application (LogCategories category, const char *message, bool log_location = true, std::source_location sloc = std::source_location::current ()) noexcept; + [[noreturn]] static void abort_application (LogCategories category, std::string const& message, bool log_location = true, std::source_location sloc = std::source_location::current ()) noexcept + { + abort_application (category, message.c_str (), log_location, sloc); + } + + [[noreturn]] static void abort_application (LogCategories category, std::string_view const& message, bool log_location = true, std::source_location sloc = std::source_location::current ()) noexcept + { + abort_application (category, message.data (), log_location, sloc); + } + [[noreturn]] static void abort_application (const char *message, bool log_location = true, std::source_location sloc = std::source_location::current ()) noexcept { abort_application (LOG_DEFAULT, message, log_location, sloc); } + + [[noreturn]] static void abort_application (std::string const& message, bool log_location = true, std::source_location sloc = std::source_location::current ()) noexcept + { + abort_application (LOG_DEFAULT, message.c_str (), log_location, sloc); + } + + [[noreturn]] static void abort_application (std::string_view const& message, bool log_location = true, std::source_location sloc = std::source_location::current ()) noexcept + { + abort_application (LOG_DEFAULT, message.data (), log_location, sloc); + } }; } #endif // __HELPERS_HH diff --git a/src/native/shared/log_types.hh b/src/native/shared/log_types.hh index b0ed20018d9..f6fb1142597 100644 --- a/src/native/shared/log_types.hh +++ b/src/native/shared/log_types.hh @@ -2,10 +2,34 @@ #define LOG_LEVEL_HH #include +#include +#include +#include #include "java-interop-logger.h" +// We redeclare macros as real functions here +#if defined(DO_LOG) +#undef DO_LOG +#endif + +#if defined(log_debug) +#undef log_debug +#endif + +#if defined(log_info) +#undef log_info +#endif + namespace xamarin::android { + namespace detail { + [[gnu::always_inline]] + static inline bool _category_is_enabled (LogCategories category) noexcept + { + return (log_categories & category) == category; + } + } + enum class LogTimingCategories : uint32_t { Default = 0, @@ -30,6 +54,109 @@ namespace xamarin::android { // A slightly faster alternative to other log functions as it doesn't parse the message // for format placeholders nor it uses variable arguments void log_write (LogCategories category, LogLevel level, const char *message) noexcept; + + template [[gnu::always_inline]] + static inline constexpr void log_debug (LogCategories category, const char *format, Args&& ...args) noexcept + { + if (detail::_category_is_enabled (category)) { + ::log_debug_nocheck (category, format, std::forward(args)...); + } + } + + template [[gnu::always_inline]] + static inline constexpr void log_debug (LogCategories category, std::string_view const& format, Args&& ...args) noexcept + { + if (detail::_category_is_enabled (category)) { + ::log_debug_nocheck (category, format.data (), std::forward(args)...); + } + } + + static inline constexpr void log_debug (LogCategories category, std::string const& message) noexcept + { + if (detail::_category_is_enabled (category)) { + ::log_debug_nocheck (category, message.c_str ()); + } + } + + // + // This will be enabled once all log_* calls are converted to std::format format + // + // template [[gnu::always_inline]] + // static inline constexpr void log_debug (LogCategories category, std::format_string fmt, Args&& ...args) + // { + // if (detail::_category_is_enabled (category)) { + + // log_debug_nocheck (category, std::format (fmt, std::forward(args)...).c_str ()); + // } + // } + + template [[gnu::always_inline]] + static inline constexpr void log_info (LogCategories category, const char *format, Args&& ...args) noexcept + { + if (detail::_category_is_enabled (category)) { + ::log_info_nocheck (category, format, std::forward(args)...); + } + } + + template [[gnu::always_inline]] + static inline constexpr void log_info (LogCategories category, std::string_view const& format, Args&& ...args) noexcept + { + if (detail::_category_is_enabled (category)) { + ::log_info_nocheck (category, format.data (), std::forward(args)...); + } + } + + [[gnu::always_inline]] + static inline constexpr void log_info (LogCategories category, std::string const& message) noexcept + { + if (detail::_category_is_enabled (category)) { + ::log_info_nocheck (category, message.c_str ()); + } + } + + [[gnu::always_inline]] + static inline constexpr void log_info_nocheck (LogCategories category, std::string const& message) noexcept + { + if (detail::_category_is_enabled (category)) { + ::log_info_nocheck (category, message.c_str ()); + } + } + + [[gnu::always_inline]] + static inline constexpr void log_warn (LogCategories category, std::string const& message) noexcept + { + ::log_warn (category, message.c_str ()); + } + + [[gnu::always_inline]] + static inline constexpr void log_warn (LogCategories category, std::string_view const& message) noexcept + { + ::log_warn (category, message.data ()); + } + + [[gnu::always_inline]] + static inline constexpr void log_error (LogCategories category, std::string const& message) noexcept + { + ::log_error (category, message.c_str ()); + } + + [[gnu::always_inline]] + static inline constexpr void log_error (LogCategories category, std::string_view const& message) noexcept + { + ::log_error (category, message.data ()); + } + + [[gnu::always_inline]] + static inline constexpr void log_fatal (LogCategories category, std::string const& message) noexcept + { + ::log_fatal (category, message.c_str ()); + } + + [[gnu::always_inline]] + static inline constexpr void log_fatal (LogCategories category, std::string_view const& message) noexcept + { + ::log_fatal (category, message.data ()); + } } extern unsigned int log_categories; #endif // ndef LOG_LEVEL_HH diff --git a/src/native/shared/new_delete.cc b/src/native/shared/new_delete.cc deleted file mode 100644 index 2293dddca10..00000000000 --- a/src/native/shared/new_delete.cc +++ /dev/null @@ -1,87 +0,0 @@ -#include - -#include "helpers.hh" - -namespace std -{ - struct nothrow_t {}; - extern const nothrow_t nothrow; -} - -#include "java-interop-util.h" - -static void* -do_alloc (size_t size) -{ - return ::malloc (size == 0 ? 1 : size); -} - -__attribute__((__weak__)) -void* -operator new (size_t size) -{ - void* p = do_alloc (size); - if (p == nullptr) { - xamarin::android::Helpers::abort_application ("Out of memory in the `new` operator"); - } - - return p; -} - -void* -operator new (size_t size, const std::nothrow_t&) noexcept -{ - return do_alloc (size); -} - -__attribute__((__weak__)) -void* -operator new[] (size_t size) -{ - return ::operator new (size); -} - -void* -operator new[] (size_t size, const std::nothrow_t&) noexcept -{ - return do_alloc (size); -} - -__attribute__((__weak__)) -void -operator delete (void* ptr) noexcept -{ - if (ptr) - ::free (ptr); -} - -void -operator delete (void* ptr, const std::nothrow_t&) -{ - ::operator delete (ptr); -} - -void -operator delete (void* ptr, size_t) noexcept -{ - ::operator delete (ptr); -} - -__attribute__((__weak__)) -void -operator delete[] (void* ptr) noexcept -{ - ::operator delete (ptr); -} - -void -operator delete[] (void* ptr, const std::nothrow_t&) noexcept -{ - ::operator delete[] (ptr); -} - -void -operator delete[] (void* ptr, size_t) noexcept -{ - ::operator delete[] (ptr); -} From 3bc283ab9ebf6aa6ad653df1a13c35221d8c8c08 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Tue, 26 Nov 2024 22:55:24 +0100 Subject: [PATCH 40/54] A bit less of reinterpret_cast<> --- src/native/monodroid/embedded-assemblies.cc | 18 +++++++++--------- src/native/shared/helpers.hh | 12 ++++++++++++ 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/src/native/monodroid/embedded-assemblies.cc b/src/native/monodroid/embedded-assemblies.cc index cf056bbb7b3..d03e99cc44e 100644 --- a/src/native/monodroid/embedded-assemblies.cc +++ b/src/native/monodroid/embedded-assemblies.cc @@ -135,7 +135,7 @@ EmbeddedAssemblies::get_assembly_data (uint8_t *data, uint32_t data_size, [[mayb cad.uncompressed_file_size = header->uncompressed_length; } - const char *data_start = reinterpret_cast(data + sizeof(CompressedAssemblyHeader)); + const char *data_start = pointer_add(data, sizeof(CompressedAssemblyHeader)); int ret = LZ4_decompress_safe (data_start, reinterpret_cast(cad.data), static_cast(assembly_data_size), static_cast(cad.uncompressed_file_size)); if (ret < 0) { @@ -249,7 +249,7 @@ EmbeddedAssemblies::map_runtime_file (XamarinAndroidBundledAssembly& file) noexc "file-offset: {:<8x} start: {:<8p} end: {:<8p} len: {:<12} zip-entry: {} name: {} [{}]", file.data_offset, static_cast(file.data), - reinterpret_cast(file.data + file.data_size), + pointer_add (file.data, file.data_size), file.data_size, file.name, file.name, @@ -560,7 +560,7 @@ EmbeddedAssemblies::binary_search (const Key *key, const Entry *base, size_t nme while (nmemb > 0) { const Entry *ret; if constexpr (use_precalculated_size) { - ret = reinterpret_cast(reinterpret_cast(base) + (precalculated_size * (nmemb / 2))); + ret = pointer_add(reinterpret_cast(base), precalculated_size * (nmemb / 2)); } else { ret = base + (nmemb / 2); } @@ -570,7 +570,7 @@ EmbeddedAssemblies::binary_search (const Key *key, const Entry *base, size_t nme nmemb /= 2; } else if (result > 0) { if constexpr (use_precalculated_size) { - base = reinterpret_cast(reinterpret_cast(ret) + precalculated_size); + base = pointer_add(reinterpret_cast(ret), precalculated_size); } else { base = ret + 1; } @@ -914,17 +914,17 @@ EmbeddedAssemblies::md_mmap_apk_file (int fd, uint32_t offset, size_t size, cons } mmap_info.size = offsetSize; - file_info.area = (void*)((const char*)mmap_info.area + offsetFromPage); + file_info.area = pointer_add (mmap_info.area, offsetFromPage); file_info.size = size; log_info ( LOG_ASSEMBLY, std::format (" mmap_start: {:<8p}; mmap_end: {:<8p} mmap_len: {:<12} file_start: {:<8p} file_end: {:<8p} file_len: {:<12} apk descriptor: {} file: {}", mmap_info.area, - reinterpret_cast(reinterpret_cast (mmap_info.area) + mmap_info.size), + pointer_add (mmap_info.area, mmap_info.size), mmap_info.size, file_info.area, - reinterpret_cast(reinterpret_cast (file_info.area) + file_info.size), + pointer_add (file_info.area, file_info.size), file_info.size, fd, filename @@ -1126,7 +1126,7 @@ EmbeddedAssemblies::typemap_load_file (BinaryTypeMapHeader &header, const char * // integer from unaligned memory memcpy (&idx, java_pos + header.java_name_width, sizeof (idx)); if (idx < INVALID_TYPE_INDEX) { - cur->to = reinterpret_cast(managed_start + (managed_entry_size * idx)); + cur->to = pointer_add(managed_start, managed_entry_size * idx); } else { // Ignore the type mapping cur->to = nullptr; @@ -1137,7 +1137,7 @@ EmbeddedAssemblies::typemap_load_file (BinaryTypeMapHeader &header, const char * cur->from = reinterpret_cast(managed_pos); memcpy (&idx, managed_pos + header.managed_name_width, sizeof (idx)); - cur->to = reinterpret_cast(java_start + (java_entry_size * idx)); + cur->to = pointer_add(java_start, java_entry_size * idx); managed_pos += managed_entry_size; } diff --git a/src/native/shared/helpers.hh b/src/native/shared/helpers.hh index 3a2bc67dfb5..078da3afac0 100644 --- a/src/native/shared/helpers.hh +++ b/src/native/shared/helpers.hh @@ -2,6 +2,7 @@ #define __HELPERS_HH #include +#include #include #include #include @@ -14,6 +15,11 @@ using namespace std::string_view_literals; namespace xamarin::android { + namespace detail { + template + concept TPointer = requires { std::is_pointer_v; }; + } + class [[gnu::visibility("hidden")]] Helpers { public: @@ -76,5 +82,11 @@ namespace xamarin::android abort_application (LOG_DEFAULT, message.data (), log_location, sloc); } }; + + template [[gnu::always_inline]] + static inline constexpr auto pointer_add (TPtr ptr, size_t offset) noexcept -> TRet + { + return reinterpret_cast(reinterpret_cast(ptr) + offset); + } } #endif // __HELPERS_HH From bbbbb79f6c0b00717c77ff91ff6f26ef52fc37c1 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Wed, 27 Nov 2024 13:13:47 +0100 Subject: [PATCH 41/54] Conversion to std::format continues Build is broken atm --- src/native/monodroid/debug.cc | 76 ++++---- .../monodroid/embedded-assemblies-zip.cc | 6 +- src/native/monodroid/monodroid-glue.cc | 137 ++++++------- src/native/monodroid/osbridge.cc | 172 ++++++++++------- src/native/monodroid/xamarin_getifaddrs.cc | 109 ++++++----- .../pinvoke-override-api-impl.hh | 22 +-- src/native/pinvoke-override/precompiled.cc | 12 +- src/native/runtime-base/android-system.cc | 72 +++---- src/native/runtime-base/monodroid-dl.hh | 14 +- src/native/shared/log_types.hh | 180 +++++++----------- 10 files changed, 404 insertions(+), 396 deletions(-) diff --git a/src/native/monodroid/debug.cc b/src/native/monodroid/debug.cc index db787268f41..7aa2ec6abb2 100644 --- a/src/native/monodroid/debug.cc +++ b/src/native/monodroid/debug.cc @@ -95,9 +95,11 @@ Debug::monodroid_profiler_load (const char *libmono_path, const char *desc, cons if (!found) log_warn (LOG_DEFAULT, - "The '%s' profiler wasn't found in the main executable nor could it be loaded from '%s'.", - mname.get (), - libname.get ()); + std::format ("The '{}' profiler wasn't found in the main executable nor could it be loaded from '{}'.", + mname.get (), + libname.get () + ) + ); } /* Profiler support cribbed from mono/metadata/profiler.c */ @@ -108,7 +110,7 @@ bool Debug::load_profiler (void *handle, const char *desc, const char *symbol) { ProfilerInitializer func = reinterpret_cast (java_interop_lib_symbol (handle, symbol, nullptr)); - log_warn (LOG_DEFAULT, "Looking for profiler init symbol '%s'? %p", symbol, func); + log_warn (LOG_DEFAULT, std::format ("Looking for profiler init symbol '{}'? {:p}", symbol, reinterpret_cast(func))); if (func != nullptr) { func (desc); @@ -138,7 +140,7 @@ Debug::parse_options (char *options, ConnOptions *opts) { char **args, **ptr; - log_info (LOG_DEFAULT, "Connection options: '%s'", options); + log_info (LOG_DEFAULT, std::format ("Connection options: '{}'", options)); args = Util::monodroid_strsplit (options, ",", 0); @@ -148,21 +150,21 @@ Debug::parse_options (char *options, ConnOptions *opts) if (strstr (arg, "port=") == arg) { int port = atoi (arg + strlen ("port=")); if (port < 0 || port > std::numeric_limits::max ()) { - log_error (LOG_DEFAULT, "Invalid debug port value %d", port); + log_error (LOG_DEFAULT, std::format ("Invalid debug port value {}", port)); continue; } conn_port = static_cast(port); - log_info (LOG_DEFAULT, "XS port = %d", conn_port); + log_info (LOG_DEFAULT, std::format ("XS port = {}", conn_port)); } else if (strstr (arg, "timeout=") == arg) { char *endp; arg += strlen ("timeout="); opts->timeout_time = strtoll (arg, &endp, 10); if ((endp == arg) || (*endp != '\0')) - log_error (LOG_DEFAULT, "Invalid --timeout argument."); + log_error (LOG_DEFAULT, "Invalid --timeout argument."sv); } else { - log_info (LOG_DEFAULT, "Unknown connection option: '%s'", arg); + log_info (LOG_DEFAULT, std::format ("Unknown connection option: '{}'", arg)); } } } @@ -186,7 +188,7 @@ Debug::start_connection (char *options) cur_time = time (nullptr); if (opts.timeout_time && cur_time > opts.timeout_time) { - log_warn (LOG_DEBUGGER, "Not connecting to IDE as the timeout value has been reached; current-time: %lli timeout: %lli", cur_time, opts.timeout_time); + log_warn (LOG_DEBUGGER, std::format ("Not connecting to IDE as the timeout value has been reached; current-time: {} timeout: {}", cur_time, opts.timeout_time)); return DebuggerConnectionStatus::Unconnected; } @@ -197,7 +199,7 @@ Debug::start_connection (char *options) res = pthread_create (&conn_thread_id, nullptr, xamarin::android::conn_thread, this); if (res) { - log_error (LOG_DEFAULT, "Failed to create connection thread: %s", strerror (errno)); + log_error (LOG_DEFAULT, std::format ("Failed to create connection thread: {}", strerror (errno))); return DebuggerConnectionStatus::Error; } @@ -218,8 +220,8 @@ Debug::start_debugging_and_profiling () if (res == DebuggerConnectionStatus::Error) { Helpers::abort_application ( LOG_DEBUGGER, - Util::monodroid_strdup_printf ( - "Connection to debugger failed. Args: %s", + std::format ( + "Connection to debugger failed. Args: {}", connect_args ) ); @@ -257,24 +259,24 @@ Debug::process_connection (int fd) ssize_t rv = Util::recv_uninterrupted (fd, &cmd_len, sizeof(cmd_len)); if (rv == 0) { - log_info (LOG_DEFAULT, "EOF on socket.\n"); + log_info (LOG_DEFAULT, "EOF on socket."sv); return false; } if (rv <= 0) { - log_info (LOG_DEFAULT, "Error while receiving command from XS (%s)\n", strerror (errno)); + log_info (LOG_DEFAULT, std::format ("Error while receiving command from XS ({})", strerror (errno))); return false; } rv = Util::recv_uninterrupted (fd, command, cmd_len); if (rv <= 0) { - log_info (LOG_DEFAULT, "Error while receiving command from XS (%s)\n", strerror (errno)); + log_info (LOG_DEFAULT, std::format ("Error while receiving command from XS ({})", strerror (errno))); return false; } // null-terminate command [cmd_len] = 0; - log_info (LOG_DEFAULT, "Received cmd: '%s'.", command); + log_info (LOG_DEFAULT, std::format ("Received cmd: '{}'.", command)); if (process_cmd (fd, command)) return true; @@ -286,14 +288,14 @@ Debug::handle_server_connection (void) { int listen_socket = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP); if (listen_socket == -1) { - log_info (LOG_DEFAULT, "Could not create socket for XS to connect to: %s", strerror (errno)); + log_info (LOG_DEFAULT, std::format ("Could not create socket for XS to connect to: {}", strerror (errno))); return 1; } int flags = 1; int rv = setsockopt (listen_socket, SOL_SOCKET, SO_REUSEADDR, &flags, sizeof (flags)); if (rv == -1 && Util::should_log (LOG_DEFAULT)) { - log_info_nocheck (LOG_DEFAULT, "Could not set SO_REUSEADDR on the listening socket (%s)", strerror (errno)); + log_info_nocheck (LOG_DEFAULT, std::format ("Could not set SO_REUSEADDR on the listening socket ({})", strerror (errno))); // not a fatal failure } @@ -307,7 +309,7 @@ Debug::handle_server_connection (void) listen_addr.sin_addr.s_addr = INADDR_ANY; rv = bind (listen_socket, (struct sockaddr *) &listen_addr, sizeof (listen_addr)); if (rv == -1) { - log_info (LOG_DEFAULT, "Could not bind to address: %s", strerror (errno)); + log_info (LOG_DEFAULT, std::format ("Could not bind to address: {}", strerror (errno))); rv = 2; goto cleanup; } @@ -319,7 +321,7 @@ Debug::handle_server_connection (void) rv = listen (listen_socket, 1); if (rv == -1) { - log_info (LOG_DEFAULT, "Could not listen for XS: %s", strerror (errno)); + log_info (LOG_DEFAULT, std::format ("Could not listen for XS: {}", strerror (errno))); rv = 2; goto cleanup; } @@ -362,14 +364,14 @@ Debug::handle_server_connection (void) if ((rv = select (listen_socket + 1, &rset, nullptr, nullptr, &tv)) == 0) { // timeout hit, no connections available. - log_info (LOG_DEFAULT, "Listened2 for connections from XS for 2 seconds, nobody connected.\n"); + log_info (LOG_DEFAULT, "Listened2 for connections from XS for 2 seconds, nobody connected."sv); rv = 3; goto cleanup; } } while (rv == -1 && errno == EINTR); if (rv == -1) { - log_info (LOG_DEFAULT, "Failed while waiting for XS to connect: %s", strerror (errno)); + log_info (LOG_DEFAULT, std::format ("Failed while waiting for XS to connect: {}", strerror (errno))); rv = 2; goto cleanup; } @@ -377,23 +379,23 @@ Debug::handle_server_connection (void) socklen_t len = sizeof (struct sockaddr_in); int fd = accept (listen_socket, (struct sockaddr *) &listen_addr, &len); if (fd == -1) { - log_info (LOG_DEFAULT, "Failed to accept connection from XS: %s", strerror (errno)); + log_info (LOG_DEFAULT, std::format ("Failed to accept connection from XS: {}", strerror (errno))); rv = 3; goto cleanup; } flags = 1; if (setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, (char *) &flags, sizeof (flags)) < 0) { - log_info (LOG_DEFAULT, "Could not set TCP_NODELAY on socket (%s)", strerror (errno)); + log_info (LOG_DEFAULT, std::format ("Could not set TCP_NODELAY on socket ({})", strerror (errno))); // not a fatal failure } - log_info (LOG_DEFAULT, "Successfully received connection from XS on port %i, fd: %i\n", listen_port, fd); + log_info (LOG_DEFAULT, std::format ("Successfully received connection from XS on port {}, fd: {}", listen_port, fd)); need_new_conn = process_connection (fd); } - log_info (LOG_DEFAULT, "Successfully talked to XS. Will continue startup now.\n"); + log_info (LOG_DEFAULT, "Successfully talked to XS. Will continue startup now."sv); rv = 0; @@ -440,13 +442,13 @@ Debug::process_cmd (int fd, char *cmd) constexpr std::string_view PONG_REPLY { "pong" }; if (strcmp (cmd, PING_CMD.data ()) == 0) { if (!Util::send_uninterrupted (fd, const_cast (reinterpret_cast (PONG_REPLY.data ())), 5)) - log_error (LOG_DEFAULT, "Got keepalive request from XS, but could not send response back (%s)\n", strerror (errno)); + log_error (LOG_DEFAULT, std::format ("Got keepalive request from XS, but could not send response back ({})", strerror (errno))); return false; } constexpr std::string_view EXIT_PROCESS_CMD { "exit process" }; if (strcmp (cmd, EXIT_PROCESS_CMD.data ()) == 0) { - log_info (LOG_DEFAULT, "Debugger requested an exit, will exit immediately.\n"); + log_info (LOG_DEFAULT, "Debugger requested an exit, will exit immediately."sv); fflush (stdout); fflush (stderr); exit (0); @@ -486,7 +488,7 @@ Debug::process_cmd (int fd, char *cmd) profiler_fd = fd; profiler_description = Util::monodroid_strdup_printf ("%s,output=#%i", prof, profiler_fd); } else { - log_error (LOG_DEFAULT, "Unknown profiler: '%s'", prof); + log_error (LOG_DEFAULT, std::format ("Unknown profiler: '{}'", prof)); } /* Notify the main thread (start_profiling ()) */ profiler_configured = true; @@ -495,7 +497,7 @@ Debug::process_cmd (int fd, char *cmd) pthread_mutex_unlock (&process_cmd_mutex); return use_fd; } else { - log_error (LOG_DEFAULT, "Unsupported command: '%s'", cmd); + log_error (LOG_DEFAULT, std::format ("Unsupported command: '{}'", cmd)); } return false; @@ -525,7 +527,7 @@ Debug::start_debugging (void) // this text is used in unit tests to check the debugger started // do not change it without updating the test. - log_warn (LOG_DEBUGGER, "Trying to initialize the debugger with options: %s", debug_arg); + log_warn (LOG_DEBUGGER, std::format ("Trying to initialize the debugger with options: {}", debug_arg)); if (enable_soft_breakpoints ()) { constexpr std::string_view soft_breakpoints { "--soft-breakpoints" }; @@ -552,7 +554,7 @@ Debug::start_profiling () if (!profiler_description) return; - log_info (LOG_DEFAULT, "Loading profiler: '%s'", profiler_description); + log_info (LOG_DEFAULT, std::format ("Loading profiler: '{}'", profiler_description)); monodroid_profiler_load (AndroidSystem::get_runtime_libdir (), profiler_description, nullptr); } @@ -572,7 +574,7 @@ Debug::enable_soft_breakpoints (void) uname (&name); for (const char** ptr = soft_breakpoint_kernel_list; *ptr; ptr++) { if (strcmp (name.release, *ptr) == 0) { - log_info (LOG_DEBUGGER, "soft breakpoints enabled due to kernel version match (%s)", name.release); + log_info (LOG_DEBUGGER, std::format ("soft breakpoints enabled due to kernel version match ({})", name.release)); return 1; } } @@ -580,17 +582,17 @@ Debug::enable_soft_breakpoints (void) char *value; /* Soft breakpoints are enabled by default */ if (AndroidSystem::monodroid_get_system_property (SharedConstants::DEBUG_MONO_SOFT_BREAKPOINTS, &value) <= 0) { - log_info (LOG_DEBUGGER, "soft breakpoints enabled by default (%s property not defined)", SharedConstants::DEBUG_MONO_SOFT_BREAKPOINTS.data ()); + log_info (LOG_DEBUGGER, std::format ("soft breakpoints enabled by default ({} property not defined)", SharedConstants::DEBUG_MONO_SOFT_BREAKPOINTS.data ())); return 1; } bool ret; if (strcmp ("0", value) == 0) { ret = false; - log_info (LOG_DEBUGGER, "soft breakpoints disabled (%s property set to %s)", SharedConstants::DEBUG_MONO_SOFT_BREAKPOINTS.data (), value); + log_info (LOG_DEBUGGER, std::format ("soft breakpoints disabled ({} property set to {})", SharedConstants::DEBUG_MONO_SOFT_BREAKPOINTS.data (), value)); } else { ret = true; - log_info (LOG_DEBUGGER, "soft breakpoints enabled (%s property set to %s)", SharedConstants::DEBUG_MONO_SOFT_BREAKPOINTS.data (), value); + log_info (LOG_DEBUGGER, std::format ("soft breakpoints enabled ({} property set to {})", SharedConstants::DEBUG_MONO_SOFT_BREAKPOINTS.data (), value)); } delete[] value; return ret; diff --git a/src/native/monodroid/embedded-assemblies-zip.cc b/src/native/monodroid/embedded-assemblies-zip.cc index 6d47ba7c042..16b2c817b64 100644 --- a/src/native/monodroid/embedded-assemblies-zip.cc +++ b/src/native/monodroid/embedded-assemblies-zip.cc @@ -331,9 +331,9 @@ EmbeddedAssemblies::zip_load_entries (int fd, const char *apk_name, [[maybe_unus ); } #ifdef DEBUG - log_info (LOG_ASSEMBLY, "Central directory offset: %u", cd_offset); - log_info (LOG_ASSEMBLY, "Central directory size: %u", cd_size); - log_info (LOG_ASSEMBLY, "Central directory entries: %u", cd_entries); + log_info (LOG_ASSEMBLY, std::format ("Central directory offset: {}", cd_offset)); + log_info (LOG_ASSEMBLY, std::format ("Central directory size: {}", cd_size)); + log_info (LOG_ASSEMBLY, std::format ("Central directory entries: {}", cd_entries)); #endif off_t retval = ::lseek (fd, static_cast(cd_offset), SEEK_SET); if (retval < 0) { diff --git a/src/native/monodroid/monodroid-glue.cc b/src/native/monodroid/monodroid-glue.cc index a90e239e83f..25c10b07660 100644 --- a/src/native/monodroid/monodroid-glue.cc +++ b/src/native/monodroid/monodroid-glue.cc @@ -95,7 +95,7 @@ MonodroidRuntime::thread_end ([[maybe_unused]] MonoProfiler *prof, [[maybe_unuse if (r != JNI_OK) { #if DEBUG /* - log_fatal (LOG_DEFAULT, "ERROR: Unable to detach current thread from the Java VM!"); + log_fatal (LOG_DEFAULT, "ERROR: Unable to detach current thread from the Java VM!"sv); */ #endif } @@ -174,15 +174,15 @@ MonodroidRuntime::open_from_update_dir (MonoAssemblyName *aname, [[maybe_unused] fullpath.append (SharedConstants::DLL_EXTENSION); } - log_debug (LOG_ASSEMBLY, "open_from_update_dir: trying to open assembly: %s\n", fullpath.get ()); + log_debug (LOG_ASSEMBLY, std::format ("open_from_update_dir: trying to open assembly: {}", fullpath.get ())); if (Util::file_exists (fullpath.get ())) { MonoImageOpenStatus status{}; result = mono_assembly_open_full (fullpath.get (), &status, 0); if (result == nullptr || status != MonoImageOpenStatus::MONO_IMAGE_OK) { - log_warn (LOG_ASSEMBLY, "Failed to load managed assembly '%s'. %s", fullpath.get (), mono_image_strerror (status)); + log_warn (LOG_ASSEMBLY, std::format ("Failed to load managed assembly '{}'. {}", fullpath.get (), mono_image_strerror (status))); } } else { - log_warn (LOG_ASSEMBLY, "open_from_update_dir: assembly file DOES NOT EXIST"); + log_warn (LOG_ASSEMBLY, "open_from_update_dir: assembly file DOES NOT EXIST"sv); } if (result != nullptr) { // TODO: register .mdb, .pdb file @@ -191,7 +191,7 @@ MonodroidRuntime::open_from_update_dir (MonoAssemblyName *aname, [[maybe_unused] } if (result != nullptr && Util::should_log (LOG_ASSEMBLY)) { - log_info_nocheck (LOG_ASSEMBLY, "open_from_update_dir: loaded assembly: %p\n", result); + log_info_nocheck (LOG_ASSEMBLY, std::format ("open_from_update_dir: loaded assembly: {:p}", reinterpret_cast(result))); } return result; } @@ -378,7 +378,7 @@ MonodroidRuntime::parse_gdb_options () noexcept time_t secs = time (nullptr); if (v + 10 < secs) { - log_warn (LOG_DEFAULT, "Found stale %s property with value '%s', not waiting.", SharedConstants::DEBUG_MONO_GDB_PROPERTY.data (), val.get ()); + log_warn (LOG_DEFAULT, std::format ("Found stale {} property with value '{}', not waiting.", SharedConstants::DEBUG_MONO_GDB_PROPERTY.data (), val.get ())); do_wait = false; } } @@ -392,7 +392,7 @@ bool MonodroidRuntime::parse_runtime_args (dynamic_local_string &runtime_args, RuntimeOptions *options) noexcept { if (runtime_args.length () == 0) { - log_warn (LOG_DEFAULT, "runtime args empty"); + log_warn (LOG_DEFAULT, "runtime args empty"sv); return true; } @@ -422,7 +422,7 @@ MonodroidRuntime::parse_runtime_args (dynamic_local_string std::numeric_limits::max ()) { - log_error (LOG_DEFAULT, "Invalid SDB port value %d", sdb_port); + log_error (LOG_DEFAULT, std::format ("Invalid SDB port value {}", sdb_port)); ret = false; continue; } if (out_port > std::numeric_limits::max ()) { - log_error (LOG_DEFAULT, "Invalid output port value %d", out_port); + log_error (LOG_DEFAULT, std::format ("Invalid output port value {}", out_port)); ret = false; continue; } @@ -468,19 +468,19 @@ MonodroidRuntime::parse_runtime_args (dynamic_local_stringout_port = out_port == -1 ? 0 : static_cast(out_port); } else if (token.starts_with (ARG_TIMEOUT)) { if (!token.to_integer (options->timeout_time, ARG_TIMEOUT.length ())) { - log_error (LOG_DEFAULT, "Invalid --timeout argument."); + log_error (LOG_DEFAULT, "Invalid --timeout argument."sv); ret = false; } } else if (token.starts_with (ARG_SERVER)) { options->server = token.has_at ('y', ARG_SERVER.length ()) || token.has_at ('Y', ARG_SERVER.length ()); } else if (token.starts_with (ARG_LOGLEVEL)) { if (!token.to_integer (options->loglevel, ARG_LOGLEVEL.length ())) { - log_error (LOG_DEFAULT, "Invalid --loglevel argument."); + log_error (LOG_DEFAULT, "Invalid --loglevel argument."sv); ret = false; } } else { static_local_string arg (token); - log_error (LOG_DEFAULT, "Unknown runtime argument: '%s'", arg.get ()); + log_error (LOG_DEFAULT, std::format ("Unknown runtime argument: '{}'", arg.get ())); ret = false; } } @@ -509,9 +509,9 @@ MonodroidRuntime::mono_runtime_init ([[maybe_unused]] JNIEnv *env, [[maybe_unuse cur_time = time (nullptr); if (!parse_runtime_args (runtime_args, &options)) { - log_error (LOG_DEFAULT, "Failed to parse runtime args: '%s'", runtime_args.get ()); + log_error (LOG_DEFAULT, std::format ("Failed to parse runtime args: '{}'", runtime_args.get ())); } else if (options.debug && cur_time > options.timeout_time) { - log_warn (LOG_DEBUGGER, "Not starting the debugger as the timeout value has been reached; current-time: %lli timeout: %lli", cur_time, options.timeout_time); + log_warn (LOG_DEBUGGER, std::format ("Not starting the debugger as the timeout value has been reached; current-time: {}; timeout: {}", cur_time, options.timeout_time)); } else if (options.debug && cur_time <= options.timeout_time) { EmbeddedAssemblies::set_register_debug_symbols (true); @@ -537,15 +537,15 @@ MonodroidRuntime::mono_runtime_init ([[maybe_unused]] JNIEnv *env, [[maybe_unuse // this text is used in unit tests to check the debugger started // do not change it without updating the test. - log_warn (LOG_DEBUGGER, "Trying to initialize the debugger with options: %s", debug_arg); + log_warn (LOG_DEBUGGER, std::format ("Trying to initialize the debugger with options: {}", debug_arg)); if (options.out_port > 0) { int sock = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP); if (sock < 0) { Helpers::abort_application ( LOG_DEBUGGER, - Util::monodroid_strdup_printf ( - "Could not construct a socket for stdout and stderr; does your app have the android.permission.INTERNET permission? %s", + std::format ( + "Could not construct a socket for stdout and stderr; does your app have the android.permission.INTERNET permission? {}", strerror (errno) ) ); @@ -561,21 +561,21 @@ MonodroidRuntime::mono_runtime_init ([[maybe_unused]] JNIEnv *env, [[maybe_unuse if ((r = inet_pton (AF_INET, options.host, &addr.sin_addr)) != 1) { Helpers::abort_application ( LOG_DEBUGGER, - Util::monodroid_strdup_printf ( - "Could not setup a socket for stdout and stderr: %s", - r == -1 ? strerror (errno) : "address not parseable in the specified address family" + std::format ( + "Could not setup a socket for stdout and stderr: {}", + r == -1 ? strerror (errno) : "address not parseable in the specified address family"sv ) ); } if (options.server) { int accepted = monodroid_debug_accept (sock, addr); - log_warn (LOG_DEBUGGER, "Accepted stdout connection: %d", accepted); + log_warn (LOG_DEBUGGER, std::format ("Accepted stdout connection: {}", accepted)); if (accepted < 0) { Helpers::abort_application ( LOG_DEBUGGER, - Util::monodroid_strdup_printf ( - "Error accepting stdout and stderr (%s:%d): %s", + std::format ( + "Error accepting stdout and stderr ({}:{}): {}", options.host, options.out_port, strerror (errno) @@ -589,8 +589,8 @@ MonodroidRuntime::mono_runtime_init ([[maybe_unused]] JNIEnv *env, [[maybe_unuse if (monodroid_debug_connect (sock, addr) != 1) { Helpers::abort_application ( LOG_DEBUGGER, - Util::monodroid_strdup_printf ( - "Error connecting stdout and stderr (%s:%d): %s", + std::format ( + "Error connecting stdout and stderr ({}:{}): {}", options.host, options.out_port, strerror (errno) @@ -651,7 +651,7 @@ MonodroidRuntime::mono_runtime_init ([[maybe_unused]] JNIEnv *env, [[maybe_unuse parse_gdb_options (); if (wait_for_gdb) { - log_warn (LOG_DEFAULT, "Waiting for gdb to attach..."); + log_warn (LOG_DEFAULT, "Waiting for gdb to attach..."sv); while (monodroid_gdb_wait) { sleep (1); } @@ -662,7 +662,7 @@ MonodroidRuntime::mono_runtime_init ([[maybe_unused]] JNIEnv *env, [[maybe_unuse if (AndroidSystem::monodroid_get_system_property (SharedConstants::DEBUG_MONO_RUNTIME_ARGS_PROPERTY, prop_val) > 0) { char **ptr; - log_warn (LOG_DEBUGGER, "passing '%s' as extra arguments to the runtime.\n", prop_val.get ()); + log_warn (LOG_DEBUGGER, std::format ("passing '{}' as extra arguments to the runtime.", prop_val.get ())); char **args = Util::monodroid_strsplit (prop_val.get (), " ", 0); int argc = 0; @@ -729,16 +729,20 @@ MonodroidRuntime::create_domain (JNIEnv *env, jstring_array_wrapper &runtimeApks if (user_assemblies_count == 0 && AndroidSystem::count_override_assemblies () == 0 && !is_running_on_desktop) { #if defined (DEBUG) - log_fatal (LOG_DEFAULT, "No assemblies found in '%s' or '%s'. Assuming this is part of Fast Deployment. Exiting...", - AndroidSystem::override_dirs [0], - (AndroidSystem::override_dirs.size () > 1 && AndroidSystem::override_dirs [1] != nullptr) ? AndroidSystem::override_dirs [1] : ""); + log_fatal (LOG_DEFAULT, + std::format ( + "No assemblies found in '{}' or '{}'. Assuming this is part of Fast Deployment. Exiting...", + AndroidSystem::override_dirs [0], + (AndroidSystem::override_dirs.size () > 1 && AndroidSystem::override_dirs [1] != nullptr) ? AndroidSystem::override_dirs [1] : ""sv + ) + ); #else - log_fatal (LOG_DEFAULT, "No assemblies (or assembly blobs) were found in the application APK file(s) or on the filesystem"); + log_fatal (LOG_DEFAULT, "No assemblies (or assembly blobs) were found in the application APK file(s) or on the filesystem"sv); #endif constexpr const char *assemblies_prefix = EmbeddedAssemblies::get_assemblies_prefix ().data (); Helpers::abort_application ( - Util::monodroid_strdup_printf ( - "ALL entries in APK named `%s` MUST be STORED. Gradle's minification may COMPRESS such entries.", + std::format ( + "ALL entries in APK named `{}` MUST be STORED. Gradle's minification may COMPRESS such entries.", assemblies_prefix ) ); @@ -854,7 +858,7 @@ MonodroidRuntime::init_android_runtime (JNIEnv *env, jclass runtimeClass, jobjec // GC threshold is 90% of the max GREF count init.grefGcThreshold = static_cast(AndroidSystem::get_gref_gc_threshold ()); - log_info (LOG_GC, "GREF GC Threshold: %i", init.grefGcThreshold); + log_info (LOG_GC, std::format ("GREF GC Threshold: {}", init.grefGcThreshold)); init.grefClass = RuntimeUtil::get_class_from_runtime_field (env, runtimeClass, "java_lang_Class", true); Class_getName = env->GetMethodID (init.grefClass, "getName", "()Ljava/lang/String;"); @@ -931,7 +935,7 @@ MonodroidRuntime::init_android_runtime (JNIEnv *env, jclass runtimeClass, jobjec osBridge.initialize_on_runtime_init (env, runtimeClass); - log_debug (LOG_DEFAULT, "Calling into managed runtime init"); + log_debug (LOG_DEFAULT, "Calling into managed runtime init"sv); size_t native_to_managed_index; if (FastTiming::enabled ()) [[unlikely]] { @@ -940,7 +944,7 @@ MonodroidRuntime::init_android_runtime (JNIEnv *env, jclass runtimeClass, jobjec auto initialize = reinterpret_cast (mono_method_get_unmanaged_callers_only_ftnptr (method, &error)); if (initialize == nullptr) { - log_fatal (LOG_DEFAULT, "Failed to get pointer to Initialize. Mono error: %s", mono_error_get_message (&error)); + log_fatal (LOG_DEFAULT, std::format ("Failed to get pointer to Initialize. Mono error: {}", mono_error_get_message (&error))); } abort_unless ( @@ -996,7 +1000,7 @@ MonodroidRuntime::set_environment_variable_for_directory (const char *name, jstr if (createDirectory) { int rv = Util::create_directory (value.get_cstr (), mode); if (rv < 0 && errno != EEXIST) - log_warn (LOG_DEFAULT, "Failed to create directory for environment variable %s. %s", name, strerror (errno)); + log_warn (LOG_DEFAULT, std::format ("Failed to create directory for environment variable {}. {}", name, strerror (errno))); } setenv (name, value.get_cstr (), 1); } @@ -1006,10 +1010,10 @@ MonodroidRuntime::create_xdg_directory (jstring_wrapper& home, size_t home_len, { static_local_string dir (home_len + relative_path.length ()); Util::path_combine (dir, home.get_cstr (), home_len, relative_path.data (), relative_path.length ()); - log_debug (LOG_DEFAULT, "Creating XDG directory: %s", dir.get ()); + log_debug (LOG_DEFAULT, std::format ("Creating XDG directory: {}", dir.get ())); int rv = Util::create_directory (dir.get (), DEFAULT_DIRECTORY_MODE); if (rv < 0 && errno != EEXIST) - log_warn (LOG_DEFAULT, "Failed to create XDG directory %s. %s", dir.get (), strerror (errno)); + log_warn (LOG_DEFAULT, std::format ("Failed to create XDG directory {}. {}", dir.get (), strerror (errno))); if (!environment_variable_name.empty ()) { setenv (environment_variable_name.data (), dir.get (), 1); } @@ -1038,7 +1042,7 @@ MonodroidRuntime::set_debug_env_vars (void) noexcept return; auto log_envvar = [](const char *name, const char *v) { - log_debug (LOG_DEFAULT, "Env variable '%s' set to '%s'.", name, v); + log_debug (LOG_DEFAULT, std::format ("Env variable '{}' set to '{}'.", name, v)); }; string_segment arg_token; @@ -1058,7 +1062,7 @@ MonodroidRuntime::set_debug_env_vars (void) noexcept log_envvar (arg.get (), one.data ()); } else if (index == 0) { // ’=value’ - log_warn (LOG_DEFAULT, "Attempt to set environment variable without specifying name: '%s'", arg.get ()); + log_warn (LOG_DEFAULT, std::format ("Attempt to set environment variable without specifying name: '{}'", arg.get ())); } else { // ’name=value’ arg[index] = '\0'; @@ -1138,10 +1142,10 @@ MonodroidRuntime::set_profile_options () noexcept .append (output_path.get (), output_path.length ()); } if (Util::create_directory (AndroidSystem::override_dirs[0], 0) < 0) { - log_warn (LOG_DEFAULT, "Failed to create directory '%s'. %s", AndroidSystem::override_dirs[0], std::strerror (errno)); + log_warn (LOG_DEFAULT, std::format ("Failed to create directory '{}'. {}", AndroidSystem::override_dirs[0], std::strerror (errno))); } - log_warn (LOG_DEFAULT, "Initializing profiler with options: %s", value.get ()); + log_warn (LOG_DEFAULT, std::format ("Initializing profiler with options: {}", value.get ())); debug.monodroid_profiler_load (AndroidSystem::get_runtime_libdir (), value.get (), output_path.get ()); } @@ -1155,7 +1159,7 @@ MonodroidRuntime::load_assembly (MonoAssemblyLoadContextGCHandle alc_handle, jst const char *assm_name = assembly.get_cstr (); if (assm_name == nullptr) [[unlikely]] { - log_warn (LOG_ASSEMBLY, "Unable to load assembly into ALC, name is null"); + log_warn (LOG_ASSEMBLY, "Unable to load assembly into ALC, name is null"sv); return; } @@ -1187,7 +1191,7 @@ MonodroidRuntime::load_assembly (MonoDomain *domain, jstring_wrapper &assembly) const char *assm_name = assembly.get_cstr (); if (assm_name == nullptr) [[unlikely]] { - log_warn (LOG_ASSEMBLY, "Unable to load assembly into AppDomain, name is null"); + log_warn (LOG_ASSEMBLY, "Unable to load assembly into AppDomain, name is null"sv); return; } @@ -1268,7 +1272,7 @@ MonodroidRuntime::create_and_initialize_domain (JNIEnv* env, jclass runtimeClass abort_unless (default_alc != nullptr, "Default AssemblyLoadContext not found"); EmbeddedAssemblies::install_preload_hooks_for_alc (); - log_debug (LOG_ASSEMBLY, "ALC hooks installed"); + log_debug (LOG_ASSEMBLY, "ALC hooks installed"sv); bool preload = (AndroidSystem::is_assembly_preload_enabled () || (is_running_on_desktop && force_preload_assemblies)); @@ -1466,7 +1470,7 @@ MonodroidRuntime::Java_mono_android_Runtime_initInternal (JNIEnv *env, jclass kl if (runtimeNativeLibDir != nullptr) { jstr = runtimeNativeLibDir; AndroidSystem::set_runtime_libdir (strdup (jstr.get_cstr ())); - log_debug (LOG_DEFAULT, "Using runtime path: %s", AndroidSystem::get_runtime_libdir ()); + log_debug (LOG_DEFAULT, std::format ("Using runtime path: {}", AndroidSystem::get_runtime_libdir ())); } AndroidSystem::setup_process_args (runtimeApks); @@ -1480,25 +1484,25 @@ MonodroidRuntime::Java_mono_android_Runtime_initInternal (JNIEnv *env, jclass kl debug.start_debugging_and_profiling (); #endif - log_debug (LOG_DEFAULT, "Probing for Mono AOT mode\n"); + log_debug (LOG_DEFAULT, "Probing for Mono AOT mode"sv); MonoAotMode mode = MonoAotMode::MONO_AOT_MODE_NONE; if (AndroidSystem::is_mono_aot_enabled ()) { mode = AndroidSystem::get_mono_aot_mode (); if (mode != MonoAotMode::MONO_AOT_MODE_INTERP_ONLY) { - log_debug (LOG_DEFAULT, "Enabling AOT mode in Mono"); + log_debug (LOG_DEFAULT, "Enabling AOT mode in Mono"sv); } else { - log_debug (LOG_DEFAULT, "Enabling Mono Interpreter"); + log_debug (LOG_DEFAULT, "Enabling Mono Interpreter"sv); } } mono_jit_set_aot_mode (mode); - log_debug (LOG_DEFAULT, "Probing if we should use LLVM\n"); + log_debug (LOG_DEFAULT, "Probing if we should use LLVM"sv); if (AndroidSystem::is_mono_llvm_enabled ()) { char *args [1]; args[0] = const_cast ("--llvm"); - log_debug (LOG_DEFAULT, "Enabling LLVM mode in Mono\n"); + log_debug (LOG_DEFAULT, "Enabling LLVM mode in Mono"sv); mono_jit_parse_options (1, args); mono_set_use_llvm (true); } @@ -1531,14 +1535,15 @@ MonodroidRuntime::Java_mono_android_Runtime_initInternal (JNIEnv *env, jclass kl if (Util::should_log (LOG_DEFAULT)) [[unlikely]] { log_info_nocheck ( LOG_DEFAULT, - ".NET for Android version: %s (%s; %s); built on %s; NDK version: %s; API level: %s; MonoVM version: %s", - BuildInfo::xa_version.data (), - BuildInfo::architecture.data (), - BuildInfo::kind.data (), - BuildInfo::date.data (), - BuildInfo::ndk_version.data (), - BuildInfo::ndk_api_level.data (), - mono_get_runtime_build_info () + std::format (".NET for Android version: {} ({}; {}); built on {}; NDK version: {}; API level: {}; MonoVM version: {}", + BuildInfo::xa_version.data (), + BuildInfo::architecture.data (), + BuildInfo::kind.data (), + BuildInfo::date.data (), + BuildInfo::ndk_version.data (), + BuildInfo::ndk_api_level.data (), + mono_get_runtime_build_info () + ) ); } @@ -1661,13 +1666,13 @@ MonodroidRuntime::get_java_class_name_for_TypeManager (jclass klass) noexcept JNIEnv *env = osBridge.ensure_jnienv (); jstring name = reinterpret_cast (env->CallObjectMethod (klass, Class_getName)); if (name == nullptr) { - log_error (LOG_DEFAULT, "Failed to obtain Java class name for object at %p", klass); + log_error (LOG_DEFAULT, std::format ("Failed to obtain Java class name for object at {:p}", reinterpret_cast(klass))); return nullptr; } const char *mutf8 = env->GetStringUTFChars (name, nullptr); if (mutf8 == nullptr) { - log_error (LOG_DEFAULT, "Failed to convert Java class name to UTF8 (out of memory?)"); + log_error (LOG_DEFAULT, "Failed to convert Java class name to UTF8 (out of memory?)"sv); env->DeleteLocalRef (name); return nullptr; } diff --git a/src/native/monodroid/osbridge.cc b/src/native/monodroid/osbridge.cc index d2725d278e2..94e0317d3e9 100644 --- a/src/native/monodroid/osbridge.cc +++ b/src/native/monodroid/osbridge.cc @@ -188,7 +188,7 @@ OSBridge::_write_stack_trace (FILE *to, char *from, LogCategories category) *end = '\0'; if ((category == LOG_GREF && gref_to_logcat) || (category == LOG_LREF && lref_to_logcat)) { - log_debug (category, "%s", m); + log_debug (category, std::format ("{}", m)); } if (to != nullptr) { fprintf (to, "%s\n", m); @@ -202,7 +202,7 @@ void OSBridge::_monodroid_gref_log (const char *message) { if (gref_to_logcat) { - log_debug (LOG_GREF, "%s", message); + log_debug (LOG_GREF, std::format ("{}", message)); } if (!gref_log) return; @@ -216,20 +216,23 @@ OSBridge::_monodroid_gref_log_new (jobject curHandle, char curType, jobject newH int c = _monodroid_gref_inc (); if ((log_categories & LOG_GREF) == 0) return c; - log_info (LOG_GREF, "+g+ grefc %i gwrefc %i obj-handle %p/%c -> new-handle %p/%c from thread '%s'(%i)", - c, - gc_weak_gref_count, - curHandle, - curType, - newHandle, - newType, - threadName, - threadId); + log_info (LOG_GREF, + std::format ("+g+ grefc {} gwrefc {} obj-handle {:p}/{} -> new-handle {:p}/{} from thread '{}'({})", + c, + gc_weak_gref_count, + reinterpret_cast(curHandle), + curType, + reinterpret_cast(newHandle), + newType, + threadName, + threadId + ) + ); if (gref_to_logcat) { if (from_writable) { _write_stack_trace (nullptr, const_cast(from), LOG_GREF); } else { - log_info (LOG_GREF, "%s", from); + log_info (LOG_GREF, std::format ("{}", from)); } } if (!gref_log) @@ -259,18 +262,21 @@ OSBridge::_monodroid_gref_log_delete (jobject handle, char type, const char *thr int c = _monodroid_gref_dec (); if ((log_categories & LOG_GREF) == 0) return; - log_info (LOG_GREF, "-g- grefc %i gwrefc %i handle %p/%c from thread '%s'(%i)", - c, - gc_weak_gref_count, - handle, - type, - threadName, - threadId); + log_info (LOG_GREF, + std::format ("-g- grefc {} gwrefc {} handle {:p}/{} from thread '{}'({})", + c, + gc_weak_gref_count, + reinterpret_cast(handle), + type, + threadName, + threadId + ) + ); if (gref_to_logcat) { if (from_writable) { _write_stack_trace (nullptr, const_cast(from), LOG_GREF); } else { - log_info (LOG_GREF, "%s", from); + log_info (LOG_GREF, std::format ("{}", from)); } } if (!gref_log) @@ -296,20 +302,23 @@ OSBridge::_monodroid_weak_gref_new (jobject curHandle, char curType, jobject new ++gc_weak_gref_count; if ((log_categories & LOG_GREF) == 0) return; - log_info (LOG_GREF, "+w+ grefc %i gwrefc %i obj-handle %p/%c -> new-handle %p/%c from thread '%s'(%i)", - gc_gref_count, - gc_weak_gref_count, - curHandle, - curType, - newHandle, - newType, - threadName, - threadId); + log_info (LOG_GREF, + std::format ("+w+ grefc {} gwrefc {} obj-handle {:p}/{} -> new-handle {:p}/{} from thread '{}'({})", + gc_gref_count, + gc_weak_gref_count, + reinterpret_cast(curHandle), + curType, + reinterpret_cast(newHandle), + newType, + threadName, + threadId + ) + ); if (gref_to_logcat) { if (from_writable) { _write_stack_trace (nullptr, const_cast(from), LOG_GREF); } else { - log_info (LOG_GREF, "%s", from); + log_info (LOG_GREF, std::format ("{}", from)); } } if (!gref_log) @@ -337,18 +346,21 @@ OSBridge::_monodroid_weak_gref_delete (jobject handle, char type, const char *th --gc_weak_gref_count; if ((log_categories & LOG_GREF) == 0) return; - log_info (LOG_GREF, "-w- grefc %i gwrefc %i handle %p/%c from thread '%s'(%i)", - gc_gref_count, - gc_weak_gref_count, - handle, - type, - threadName, - threadId); + log_info (LOG_GREF, + std::format ("-w- grefc {} gwrefc {} handle {:p}/{} from thread '{}'({})", + gc_gref_count, + gc_weak_gref_count, + reinterpret_cast(handle), + type, + threadName, + threadId + ) + ); if (gref_to_logcat) { if (from_writable) { _write_stack_trace (nullptr, const_cast(from), LOG_GREF); } else { - log_info (LOG_GREF, "%s", from); + log_info (LOG_GREF, std::format ("{}", from)); } } if (!gref_log) @@ -373,17 +385,20 @@ OSBridge::_monodroid_lref_log_new (int lrefc, jobject handle, char type, const c { if ((log_categories & LOG_LREF) == 0) return; - log_info (LOG_LREF, "+l+ lrefc %i handle %p/%c from thread '%s'(%i)", - lrefc, - handle, - type, - threadName, - threadId); + log_info (LOG_LREF, + std::format ("+l+ lrefc {} handle {:p}/{} from thread '{}'({})", + lrefc, + reinterpret_cast(handle), + type, + threadName, + threadId + ) + ); if (lref_to_logcat) { if (from_writable) { _write_stack_trace (nullptr, const_cast(from), LOG_GREF); } else { - log_info (LOG_GREF, "%s", from); + log_info (LOG_GREF, std::format ("{}", from)); } } if (!lref_log) @@ -407,17 +422,20 @@ OSBridge::_monodroid_lref_log_delete (int lrefc, jobject handle, char type, cons { if ((log_categories & LOG_LREF) == 0) return; - log_info (LOG_LREF, "-l- lrefc %i handle %p/%c from thread '%s'(%i)", - lrefc, - handle, - type, - threadName, - threadId); + log_info (LOG_LREF, + std::format ("-l- lrefc {} handle {:p}/{} from thread '{}'({})", + lrefc, + reinterpret_cast(handle), + type, + threadName, + threadId + ) + ); if (lref_to_logcat) { if (from_writable) { _write_stack_trace (nullptr, const_cast(from), LOG_GREF); } else { - log_info (LOG_GREF, "%s", from); + log_info (LOG_GREF, std::format ("{}", from)); } } if (!lref_log) @@ -529,9 +547,13 @@ OSBridge::gc_bridge_class_kind (MonoClass *klass) i = get_gc_bridge_index (klass); if (i == static_cast (-NUM_GC_BRIDGE_TYPES)) { - log_info (LOG_GC, "asked if a class %s.%s is a bridge before we inited java.lang.Object", - mono_class_get_namespace (klass), - mono_class_get_name (klass)); + log_info (LOG_GC, + std::format ( + "asked if a class {}.{} is a bridge before we inited java.lang.Object", + mono_class_get_namespace (klass), + mono_class_get_name (klass) + ) + ); return MonoGCBridgeObjectKind::GC_BRIDGE_TRANSPARENT_CLASS; } @@ -555,9 +577,13 @@ OSBridge::gc_is_bridge_object (MonoObject *object) if (handle == nullptr) { #if DEBUG MonoClass *mclass = mono_object_get_class (object); - log_info (LOG_GC, "object of class %s.%s with null handle", + log_info (LOG_GC, + std::format ( + "object of class {}.{} with null handle", mono_class_get_namespace (mclass), - mono_class_get_name (mclass)); + mono_class_get_name (mclass) + ) + ); #endif return 0; } @@ -643,9 +669,9 @@ OSBridge::add_reference (JNIEnv *env, OSBridge::AddReferenceTarget target, OSBri *reffed_description = describe_target (reffed_target); if (success) - log_warn (LOG_GC, "Added reference for %s to %s", description, reffed_description); + log_warn (LOG_GC, std::format ("Added reference for {} to {}", description, reffed_description)); else - log_error (LOG_GC, "Missing monodroidAddReference method for %s", description); + log_error (LOG_GC, std::format ("Missing monodroidAddReference method for {}", description)); free (description); free (reffed_description); @@ -881,9 +907,13 @@ OSBridge::gc_cleanup_after_java_collection (JNIEnv *env, int num_sccs, MonoGCBri #if DEBUG if (Logger::gc_spew_enabled ()) { klass = mono_object_get_class (obj); - log_error (LOG_GC, "Missing monodroidClearReferences method for object of class %s.%s", + log_error (LOG_GC, + std::format ( + "Missing monodroidClearReferences method for object of class {}.{}", mono_class_get_namespace (klass), - mono_class_get_name (klass)); + mono_class_get_name (klass) + ) + ); } #endif } @@ -897,7 +927,7 @@ OSBridge::gc_cleanup_after_java_collection (JNIEnv *env, int num_sccs, MonoGCBri } } #if DEBUG - log_info (LOG_GC, "GC cleanup summary: %d objects tested - resurrecting %d.", total, alive); + log_info (LOG_GC, std::format ("GC cleanup summary: {} objects tested - resurrecting {}.", total, alive)); #endif } @@ -927,10 +957,10 @@ OSBridge::gc_cross_references (int num_sccs, MonoGCBridgeSCC **sccs, int num_xre if (Logger::gc_spew_enabled ()) { int i, j; - log_info (LOG_GC, "cross references callback invoked with %d sccs and %d xrefs.", num_sccs, num_xrefs); + log_info (LOG_GC, std::format ("cross references callback invoked with {} sccs and {} xrefs.", num_sccs, num_xrefs)); for (i = 0; i < num_sccs; ++i) { - log_info (LOG_GC, "group %d with %d objects", i, sccs [i]->num_objs); + log_info (LOG_GC, std::format ("group {} with {} objects", i, sccs [i]->num_objs)); for (j = 0; j < sccs [i]->num_objs; ++j) { MonoObject *obj = sccs [i]->objs [j]; @@ -944,18 +974,22 @@ OSBridge::gc_cross_references (int num_sccs, MonoGCBridgeSCC **sccs, int num_xre } } MonoClass *klass = mono_object_get_class (obj); - log_info (LOG_GC, "\tobj %p [%s::%s] handle %p key_handle %p", - obj, + log_info (LOG_GC, + std::format ( + "\tobj {:p} [{}::{}] handle {:p} key_handle {:p}", + reinterpret_cast(obj), mono_class_get_namespace (klass), mono_class_get_name (klass), - handle, - key_handle); + reinterpret_cast(handle), + key_handle + ) + ); } } if (Util::should_log (LOG_GC)) { for (i = 0; i < num_xrefs; ++i) - log_info_nocheck (LOG_GC, "xref [%d] %d -> %d", i, xrefs [i].src_scc_index, xrefs [i].dst_scc_index); + log_info_nocheck (LOG_GC, std::format ("xref [{}] {} -> {}", i, xrefs [i].src_scc_index, xrefs [i].dst_scc_index)); } } diff --git a/src/native/monodroid/xamarin_getifaddrs.cc b/src/native/monodroid/xamarin_getifaddrs.cc index 9f071132976..99ba01039e6 100644 --- a/src/native/monodroid/xamarin_getifaddrs.cc +++ b/src/native/monodroid/xamarin_getifaddrs.cc @@ -381,9 +381,9 @@ get_ifaddrs_impl (int (**getifaddrs_implementation) (struct _monodroid_ifaddrs * } if (!*getifaddrs_implementation) { - log_info (LOG_NET, "This libc does not have getifaddrs/freeifaddrs, using Xamarin's\n"); + log_info (LOG_NET, "This libc does not have getifaddrs/freeifaddrs, using Xamarin's"sv); } else { - log_info (LOG_NET, "This libc has getifaddrs/freeifaddrs\n"); + log_info (LOG_NET, "This libc has getifaddrs/freeifaddrs"sv); } } @@ -421,7 +421,7 @@ open_netlink_session (netlink_session *session) memset (session, 0, sizeof (*session)); session->sock_fd = socket (AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); if (session->sock_fd == -1) { - log_warn (LOG_NETLINK, "Failed to create a netlink socket. %s\n", strerror (errno)); + log_warn (LOG_NETLINK, std::format ("Failed to create a netlink socket. {}", strerror (errno))); return -1; } @@ -440,7 +440,7 @@ open_netlink_session (netlink_session *session) session->them.nl_family = AF_NETLINK; if (bind (session->sock_fd, (struct sockaddr *)&session->us, sizeof (session->us)) < 0) { - log_warn (LOG_NETLINK, "Failed to bind to the netlink socket. %s\n", strerror (errno)); + log_warn (LOG_NETLINK, std::format ("Failed to bind to the netlink socket. {}", strerror (errno))); return -1; } @@ -478,7 +478,7 @@ send_netlink_dump_request (netlink_session *session, int type) session->message_header.msg_iov = &session->payload_vector; if (sendmsg (session->sock_fd, (const struct msghdr*)&session->message_header, 0) < 0) { - log_warn (LOG_NETLINK, "Failed to send netlink message. %s\n", strerror (errno)); + log_warn (LOG_NETLINK, std::format ("Failed to send netlink message. {}", strerror (errno))); return -1; } @@ -529,7 +529,7 @@ parse_netlink_reply (netlink_session *session, struct _monodroid_ifaddrs **ifadd abort_if_invalid_pointer_argument (last_ifaddr, "last_ifaddr"); size_t buf_size = static_cast(getpagesize ()); - log_debug (LOG_NETLINK, "receive buffer size == %d", buf_size); + log_debug (LOG_NETLINK, std::format ("receive buffer size == {}", buf_size)); size_t alloc_size = Helpers::multiply_with_overflow_check (sizeof(*response), buf_size); response = (unsigned char*)malloc (alloc_size); @@ -551,29 +551,29 @@ parse_netlink_reply (netlink_session *session, struct _monodroid_ifaddrs **ifadd netlink_reply.msg_iov = &reply_vector; length = recvmsg (session->sock_fd, &netlink_reply, 0); - log_debug (LOG_NETLINK, " length == %d\n", (int)length); + log_debug (LOG_NETLINK, std::format (" length == {}", (int)length)); if (length < 0) { - log_debug (LOG_NETLINK, "Failed to receive reply from netlink. %s\n", strerror (errno)); + log_debug (LOG_NETLINK, std::format ("Failed to receive reply from netlink. {}", strerror (errno))); goto cleanup; } #if DEBUG if (Util::should_log (LOG_NETLINK)) { - log_debug_nocheck (LOG_NETLINK, "response flags:"); + log_debug_nocheck (LOG_NETLINK, "response flags:"sv); if (netlink_reply.msg_flags == 0) - log_debug_nocheck (LOG_NETLINK, " [NONE]"); + log_debug_nocheck (LOG_NETLINK, " [NONE]"sv); else { if (netlink_reply.msg_flags & MSG_EOR) - log_debug_nocheck (LOG_NETLINK, " MSG_EOR"); + log_debug_nocheck (LOG_NETLINK, " MSG_EOR"sv); if (netlink_reply.msg_flags & MSG_TRUNC) - log_debug_nocheck (LOG_NETLINK, " MSG_TRUNC"); + log_debug_nocheck (LOG_NETLINK, " MSG_TRUNC"sv); if (netlink_reply.msg_flags & MSG_CTRUNC) - log_debug_nocheck (LOG_NETLINK, " MSG_CTRUNC"); + log_debug_nocheck (LOG_NETLINK, " MSG_CTRUNC"sv); if (netlink_reply.msg_flags & MSG_OOB) - log_debug_nocheck (LOG_NETLINK, " MSG_OOB"); + log_debug_nocheck (LOG_NETLINK, " MSG_OOB"sv); if (netlink_reply.msg_flags & MSG_ERRQUEUE) - log_debug_nocheck (LOG_NETLINK, " MSG_ERRQUEUE"); + log_debug_nocheck (LOG_NETLINK, " MSG_ERRQUEUE"sv); } } #endif @@ -582,21 +582,21 @@ parse_netlink_reply (netlink_session *session, struct _monodroid_ifaddrs **ifadd break; for (current_message = (struct nlmsghdr*)response; current_message && NLMSG_OK (current_message, static_cast(length)); current_message = NLMSG_NEXT (current_message, length)) { - log_debug (LOG_NETLINK, "next message... (type: %u)\n", current_message->nlmsg_type); + log_debug (LOG_NETLINK, std::format ("next message... (type: {})", current_message->nlmsg_type)); switch (current_message->nlmsg_type) { /* See rtnetlink.h */ case RTM_NEWLINK: - log_debug (LOG_NETLINK, " dumping link...\n"); + log_debug (LOG_NETLINK, " dumping link..."sv); addr = get_link_info (current_message); if (!addr || append_ifaddr (addr, ifaddrs_head, last_ifaddr) < 0) { ret = -1; goto cleanup; } - log_debug (LOG_NETLINK, " done\n"); + log_debug (LOG_NETLINK, " done"sv); break; case RTM_NEWADDR: - log_debug (LOG_NETLINK, " got an address\n"); + log_debug (LOG_NETLINK, " got an address"sv); addr = get_link_address (current_message, ifaddrs_head); if (!addr || append_ifaddr (addr, ifaddrs_head, last_ifaddr) < 0) { ret = -1; @@ -605,13 +605,13 @@ parse_netlink_reply (netlink_session *session, struct _monodroid_ifaddrs **ifadd break; case NLMSG_DONE: - log_debug (LOG_NETLINK, " message done\n"); + log_debug (LOG_NETLINK, " message done"sv); ret = 0; goto cleanup; break; default: - log_debug (LOG_NETLINK, " message type: %u", current_message->nlmsg_type); + log_debug (LOG_NETLINK, std::format (" message type: {}", current_message->nlmsg_type)); break; } } @@ -634,7 +634,7 @@ fill_sa_address (struct sockaddr **sa, struct ifaddrmsg *net_address, void *rta_ case AF_INET: { struct sockaddr_in *sa4; if (rta_payload_length != 4) /* IPv4 address length */ { - log_warn (LOG_NETLINK, "Unexpected IPv4 address payload length %u", rta_payload_length); + log_warn (LOG_NETLINK, std::format ("Unexpected IPv4 address payload length {}", rta_payload_length)); return -1; } sa4 = (struct sockaddr_in*)calloc (1, sizeof (*sa4)); @@ -650,7 +650,7 @@ fill_sa_address (struct sockaddr **sa, struct ifaddrmsg *net_address, void *rta_ case AF_INET6: { struct sockaddr_in6 *sa6; if (rta_payload_length != 16) /* IPv6 address length */ { - log_warn (LOG_NETLINK, "Unexpected IPv6 address payload length %u", rta_payload_length); + log_warn (LOG_NETLINK, std::format ("Unexpected IPv6 address payload length {}", rta_payload_length)); return -1; } sa6 = (struct sockaddr_in6*)calloc (1, sizeof (*sa6)); @@ -668,7 +668,7 @@ fill_sa_address (struct sockaddr **sa, struct ifaddrmsg *net_address, void *rta_ default: { struct sockaddr *sagen; if (rta_payload_length > sizeof (sagen->sa_data)) { - log_warn (LOG_NETLINK, "Unexpected RTA payload length %u (wanted at most %u)", rta_payload_length, sizeof (sagen->sa_data)); + log_warn (LOG_NETLINK, std::format ("Unexpected RTA payload length {} (wanted at most {})", rta_payload_length, sizeof (sagen->sa_data))); return -1; } @@ -701,16 +701,16 @@ fill_ll_address (struct sockaddr_ll_extended **sa, struct ifinfomsg *net_interfa /* The assert can only fail for Iniband links, which are quite unlikely to be found * in any mobile devices */ - log_debug (LOG_NETLINK, "rta_payload_length == %d; sizeof sll_addr == %d; hw type == 0x%X\n", rta_payload_length, sizeof ((*sa)->sll_addr), net_interface->ifi_type); + log_debug (LOG_NETLINK, std::format ("rta_payload_length == {}; sizeof sll_addr == {}; hw type == {:x}", rta_payload_length, sizeof ((*sa)->sll_addr), net_interface->ifi_type)); if (static_cast(rta_payload_length) > sizeof ((*sa)->sll_addr)) { - log_info (LOG_NETLINK, "Address is too long to place in sockaddr_ll (%d > %d)", rta_payload_length, sizeof ((*sa)->sll_addr)); + log_info (LOG_NETLINK, std::format ("Address is too long to place in sockaddr_ll ({} > {})", rta_payload_length, sizeof ((*sa)->sll_addr))); free (*sa); *sa = NULL; return -1; } if (rta_payload_length > std::numeric_limits::max ()) { - log_info (LOG_NETLINK, "Payload length too big to fit in the address structure"); + log_info (LOG_NETLINK, "Payload length too big to fit in the address structure"sv); free (*sa); *sa = NULL; return -1; @@ -817,16 +817,15 @@ calculate_address_netmask (struct _monodroid_ifaddrs *ifa, struct ifaddrmsg *net memset (netmask_data, 0xFF, prefix_bytes); if (postfix_bytes > 0) memset (netmask_data + prefix_bytes + 1, 0x00, postfix_bytes); - log_debug (LOG_NETLINK, " calculating netmask, prefix length is %u bits (%u bytes), data length is %u bytes\n", prefix_length, prefix_bytes, data_length); + log_debug (LOG_NETLINK, std::format (" calculating netmask, prefix length is {} bits ({} bytes), data length is {} bytes\n", prefix_length, prefix_bytes, data_length)); if (prefix_bytes + 2 < data_length) /* Set the rest of the mask bits in the byte following the last 0xFF value */ netmask_data [prefix_bytes + 1] = static_cast(0xff << (8 - (prefix_length % 8))); if (Util::should_log (LOG_NETLINK)) { - log_debug_nocheck (LOG_NETLINK, " netmask is: "); + log_debug_nocheck (LOG_NETLINK, " netmask is: "sv); for (uint32_t i = 0; i < data_length; i++) { - log_debug_nocheck (LOG_NETLINK, "%s%u", i == 0 ? " " : ".", (unsigned char)ifa->ifa_netmask->sa_data [i]); + log_debug_nocheck (LOG_NETLINK, std::format ("{}{}", i == 0 ? " "sv : "."sv, (unsigned char)ifa->ifa_netmask->sa_data [i])); } - log_debug_nocheck (LOG_NETLINK, "\n"); } } } @@ -848,7 +847,7 @@ get_link_address (const struct nlmsghdr *message, struct _monodroid_ifaddrs **if abort_if_invalid_pointer_argument (message, "message"); net_address = reinterpret_cast (NLMSG_DATA (message)); length = static_cast(IFA_PAYLOAD (message)); - log_debug (LOG_NETLINK, " address data length: %u", length); + log_debug (LOG_NETLINK, std::format (" address data length: {}", length)); if (length <= 0) { goto error; } @@ -862,17 +861,17 @@ get_link_address (const struct nlmsghdr *message, struct _monodroid_ifaddrs **if ifa->ifa_flags = static_cast(get_interface_flags_by_index (static_cast(net_address->ifa_index), ifaddrs_head)); attribute = IFA_RTA (net_address); - log_debug (LOG_NETLINK, " reading attributes"); + log_debug (LOG_NETLINK, " reading attributes"sv); while (RTA_OK (attribute, length)) { payload_size = RTA_PAYLOAD (attribute); - log_debug (LOG_NETLINK, " attribute payload_size == %u\n", payload_size); + log_debug (LOG_NETLINK, std::format (" attribute payload_size == {}", payload_size)); sa = NULL; switch (attribute->rta_type) { case IFA_LABEL: { size_t room_for_trailing_null = 0uz; - log_debug (LOG_NETLINK, " attribute type: LABEL"); + log_debug (LOG_NETLINK, " attribute type: LABEL"sv); if (payload_size > MAX_IFA_LABEL_SIZE) { payload_size = MAX_IFA_LABEL_SIZE; room_for_trailing_null = 1; @@ -893,7 +892,7 @@ get_link_address (const struct nlmsghdr *message, struct _monodroid_ifaddrs **if } case IFA_LOCAL: - log_debug (LOG_NETLINK, " attribute type: LOCAL"); + log_debug (LOG_NETLINK, " attribute type: LOCAL"sv); if (ifa->ifa_addr) { /* P2P protocol, set the dst/broadcast address union from the original address. * Since ifa_addr is set it means IFA_ADDRESS occured earlier and that address @@ -906,7 +905,7 @@ get_link_address (const struct nlmsghdr *message, struct _monodroid_ifaddrs **if break; case IFA_BROADCAST: - log_debug (LOG_NETLINK, " attribute type: BROADCAST"); + log_debug (LOG_NETLINK, " attribute type: BROADCAST"sv); if (ifa->_monodroid_ifa_dstaddr) { /* IFA_LOCAL happened earlier, undo its effect here */ free (ifa->_monodroid_ifa_dstaddr); @@ -916,7 +915,7 @@ get_link_address (const struct nlmsghdr *message, struct _monodroid_ifaddrs **if break; case IFA_ADDRESS: - log_debug (LOG_NETLINK, " attribute type: ADDRESS"); + log_debug (LOG_NETLINK, " attribute type: ADDRESS"sv); if (ifa->ifa_addr) { /* Apparently IFA_LOCAL occured earlier and we have a P2P connection * here. IFA_LOCAL carries the destination address, move it there @@ -928,23 +927,23 @@ get_link_address (const struct nlmsghdr *message, struct _monodroid_ifaddrs **if break; case IFA_UNSPEC: - log_debug (LOG_NETLINK, " attribute type: UNSPEC"); + log_debug (LOG_NETLINK, " attribute type: UNSPEC"sv); break; case IFA_ANYCAST: - log_debug (LOG_NETLINK, " attribute type: ANYCAST"); + log_debug (LOG_NETLINK, " attribute type: ANYCAST"sv); break; case IFA_CACHEINFO: - log_debug (LOG_NETLINK, " attribute type: CACHEINFO"); + log_debug (LOG_NETLINK, " attribute type: CACHEINFO"sv); break; case IFA_MULTICAST: - log_debug (LOG_NETLINK, " attribute type: MULTICAST"); + log_debug (LOG_NETLINK, " attribute type: MULTICAST"sv); break; default: - log_debug (LOG_NETLINK, " attribute type: %u", attribute->rta_type); + log_debug (LOG_NETLINK, std::format (" attribute type: {}", attribute->rta_type)); break; } @@ -960,10 +959,10 @@ get_link_address (const struct nlmsghdr *message, struct _monodroid_ifaddrs **if /* glibc stores the associated interface name in the address if IFA_LABEL never occured */ if (!ifa->ifa_name) { char *name = get_interface_name_by_index (static_cast(net_address->ifa_index), ifaddrs_head); - log_debug (LOG_NETLINK, " address has no name/label, getting one from interface\n"); + log_debug (LOG_NETLINK, " address has no name/label, getting one from interface"sv); ifa->ifa_name = name ? strdup (name) : NULL; } - log_debug (LOG_NETLINK, " address label: %s\n", ifa->ifa_name); + log_debug (LOG_NETLINK, std::format (" address label: {}", ifa->ifa_name)); if (calculate_address_netmask (ifa, net_address) < 0) { goto error; @@ -1017,13 +1016,13 @@ get_link_info (const struct nlmsghdr *message) goto error; } if (Util::should_log (LOG_NETLINK)) { - log_debug_nocheck (LOG_NETLINK, " interface name (payload length: %d; string length: %d)\n", RTA_PAYLOAD (attribute), strlen (ifa->ifa_name)); - log_debug_nocheck (LOG_NETLINK, " %s\n", ifa->ifa_name); + log_debug_nocheck (LOG_NETLINK, std::format (" interface name (payload length: {}; string length: {})", RTA_PAYLOAD (attribute), strlen (ifa->ifa_name))); + log_debug_nocheck (LOG_NETLINK, std::format (" {}", ifa->ifa_name)); } break; case IFLA_BROADCAST: - log_debug (LOG_NETLINK, " interface broadcast (%d bytes)\n", RTA_PAYLOAD (attribute)); + log_debug (LOG_NETLINK, std::format (" interface broadcast ({} bytes)", RTA_PAYLOAD (attribute))); if (fill_ll_address (&sa, net_interface, RTA_DATA (attribute), RTA_PAYLOAD (attribute)) < 0) { goto error; } @@ -1031,7 +1030,7 @@ get_link_info (const struct nlmsghdr *message) break; case IFLA_ADDRESS: - log_debug (LOG_NETLINK, " interface address (%d bytes)\n", RTA_PAYLOAD (attribute)); + log_debug (LOG_NETLINK, std::format (" interface address ({} bytes)", RTA_PAYLOAD (attribute))); if (fill_ll_address (&sa, net_interface, RTA_DATA (attribute), RTA_PAYLOAD (attribute)) < 0) { goto error; } @@ -1040,7 +1039,7 @@ get_link_info (const struct nlmsghdr *message) default: #if DEBUG - log_debug (LOG_NETLINK, " rta_type: "); + log_debug (LOG_NETLINK, " rta_type: "sv); print_ifla_name (attribute->rta_type); #endif // DEBUG break; @@ -1048,7 +1047,7 @@ get_link_info (const struct nlmsghdr *message) attribute = RTA_NEXT (attribute, length); } - log_debug (LOG_NETLINK, "link flags: 0x%X", ifa->ifa_flags); + log_debug (LOG_NETLINK, std::format ("link flags: {:X}", ifa->ifa_flags)); return ifa; error: @@ -1143,7 +1142,7 @@ print_ifla_name (int id) int i = 0; while (1) { if (iflas [i].value == -1 && iflas [i].name == 0) { - log_info_nocheck (LOG_NETLINK, "Unknown ifla->name: unknown id %d\n", id); + log_info_nocheck (LOG_NETLINK, std::format ("Unknown ifla->name: unknown id {}", id)); break; } @@ -1151,7 +1150,7 @@ print_ifla_name (int id) i++; continue; } - log_info_nocheck (LOG_NETLINK, "ifla->name: %s (%d)\n", iflas [i].name, iflas [i].value); + log_info_nocheck (LOG_NETLINK, std::format ("ifla->name: {} ({})", iflas [i].name, iflas [i].value)); break; } } @@ -1166,7 +1165,7 @@ print_address_list (const char title[], struct _monodroid_ifaddrs *list) char *msg, *tmp; if (!list) { - log_info_nocheck (LOG_NETLINK, "monodroid-net", "No list to print in %s", __FUNCTION__); + log_info_nocheck (LOG_NETLINK, std::format ("No list to print in {}", __FUNCTION__)); return; } @@ -1181,7 +1180,7 @@ print_address_list (const char title[], struct _monodroid_ifaddrs *list) cur = cur->ifa_next; } - log_info_nocheck (LOG_NETLINK, "%s: %s", title, msg ? msg : "[no addresses]"); + log_info_nocheck (LOG_NETLINK, std::format ("{}: {}", title, msg ? msg : "[no addresses]"sv)); free (msg); } #endif diff --git a/src/native/pinvoke-override/pinvoke-override-api-impl.hh b/src/native/pinvoke-override/pinvoke-override-api-impl.hh index 36523f092a9..240223b396c 100644 --- a/src/native/pinvoke-override/pinvoke-override-api-impl.hh +++ b/src/native/pinvoke-override/pinvoke-override-api-impl.hh @@ -23,21 +23,21 @@ namespace xamarin::android { constexpr bool PREFER_AOT_CACHE = false; lib_handle = internal::MonodroidDl::monodroid_dlopen (library_name, MONO_DL_LOCAL, nullptr, PREFER_AOT_CACHE); if (lib_handle == nullptr) { - log_warn (LOG_ASSEMBLY, "Shared library '%s' not loaded, p/invoke '%s' may fail", library_name, symbol_name); + log_warn (LOG_ASSEMBLY, std::format ("Shared library '{}' not loaded, p/invoke '{}' may fail", library_name, symbol_name)); return nullptr; } if (dso_handle != nullptr) { void *expected_null = nullptr; if (!__atomic_compare_exchange (dso_handle, &expected_null, &lib_handle, false /* weak */, __ATOMIC_ACQUIRE /* success_memorder */, __ATOMIC_RELAXED /* xxxfailure_memorder */)) { - log_debug (LOG_ASSEMBLY, "Library '%s' handle already cached by another thread", library_name); + log_debug (LOG_ASSEMBLY, std::format ("Library '{}' handle already cached by another thread", library_name)); } } } void *entry_handle = internal::MonodroidDl::monodroid_dlsym (lib_handle, symbol_name, nullptr, nullptr); if (entry_handle == nullptr) { - log_warn (LOG_ASSEMBLY, "Symbol '%s' not found in shared library '%s', p/invoke may fail", symbol_name, library_name); + log_warn (LOG_ASSEMBLY, std::format ("Symbol '{}' not found in shared library '{}', p/invoke may fail", symbol_name, library_name)); return nullptr; } @@ -60,7 +60,7 @@ namespace xamarin::android { return nullptr; } - log_debug (LOG_ASSEMBLY, "Caching p/invoke entry %s @ %s", library_name.c_str (), entrypoint_name.c_str ()); + log_debug (LOG_ASSEMBLY, std::format ("Caching p/invoke entry {} @ {}", library_name, entrypoint_name)); (*api_map)[entrypoint_name] = entry_handle; return entry_handle; } @@ -73,15 +73,15 @@ namespace xamarin::android { bool already_loaded = !__atomic_compare_exchange ( /* ptr */ &entry.func, - /* expected */ &expected_null, - /* desired */ &entry_handle, - /* weak */ false, - /* success_memorder */ __ATOMIC_ACQUIRE, - /* failure_memorder */ __ATOMIC_RELAXED + /* expected */ &expected_null, + /* desired */ &entry_handle, + /* weak */ false, + /* success_memorder */ __ATOMIC_ACQUIRE, + /* failure_memorder */ __ATOMIC_RELAXED ); if (already_loaded) { - log_debug (LOG_ASSEMBLY, "Entry '%s' from library '%s' already loaded by another thread", entrypoint_name, library_name); + log_debug (LOG_ASSEMBLY, std::format ("Entry '{}' from library '{}' already loaded by another thread", entrypoint_name, library_name)); } } @@ -147,7 +147,7 @@ namespace xamarin::android { handle = fetch_or_create_pinvoke_map_entry (lib_name, entry_name, entrypoint_name_hash, lib_map, /* need_lock */ false); } else { if (iter->second == nullptr) [[unlikely]] { - log_warn (LOG_ASSEMBLY, "Internal error: null entry in p/invoke map for key '%s'", library_name); + log_warn (LOG_ASSEMBLY, std::format ("Internal error: null entry in p/invoke map for key '{}'", library_name)); return nullptr; // fall back to `monodroid_dlopen` } diff --git a/src/native/pinvoke-override/precompiled.cc b/src/native/pinvoke-override/precompiled.cc index 1c84095080a..90ad9214ecd 100644 --- a/src/native/pinvoke-override/precompiled.cc +++ b/src/native/pinvoke-override/precompiled.cc @@ -22,16 +22,16 @@ PinvokeOverride::monodroid_pinvoke_override (const char *library_name, const cha PinvokeEntry *entry = find_pinvoke_address (entrypoint_hash, internal_pinvokes.data (), internal_pinvokes_count); if (entry == nullptr) [[unlikely]] { - log_fatal (LOG_ASSEMBLY, "Internal p/invoke symbol '%s @ %s' (hash: 0x%zx) not found in compile-time map.", library_name, entrypoint_name, entrypoint_hash); - log_fatal (LOG_ASSEMBLY, "compile-time map contents:"); + log_fatal (LOG_ASSEMBLY, std::format ("Internal p/invoke symbol '{} @ {}' (hash: {:x}) not found in compile-time map.", library_name, entrypoint_name, entrypoint_hash)); + log_fatal (LOG_ASSEMBLY, "compile-time map contents:"sv); for (size_t i = 0uz; i < internal_pinvokes_count; i++) { PinvokeEntry const& e = internal_pinvokes[i]; - log_fatal (LOG_ASSEMBLY, "\t'%s'=%p (hash: 0x%zx)", e.name, e.func, e.hash); + log_fatal (LOG_ASSEMBLY, std::format ("\t'{}'={:p} (hash: {:x})", e.name, e.func, e.hash)); } Helpers::abort_application ( LOG_ASSEMBLY, - Util::monodroid_strdup_printf ( - "Failure handling a p/invoke request for '%s'@'%s'", + std::format ( + "Failure handling a p/invoke request for '{}'@'{}'", entrypoint_name, library_name ) @@ -75,7 +75,7 @@ PinvokeOverride::monodroid_pinvoke_override (const char *library_name, const cha } // It's possible we don't have an entry for some `dotnet` p/invoke, fall back to the slow path below - log_debug (LOG_ASSEMBLY, "Symbol '%s' in library '%s' not found in the generated tables, falling back to slow path", entrypoint_name, library_name); + log_debug (LOG_ASSEMBLY, std::format ("Symbol '{}' in library '{}' not found in the generated tables, falling back to slow path", entrypoint_name, library_name)); } return handle_other_pinvoke_request (library_name, library_name_hash, entrypoint_name, entrypoint_hash); diff --git a/src/native/runtime-base/android-system.cc b/src/native/runtime-base/android-system.cc index 44745a7f34f..9119fe783a1 100644 --- a/src/native/runtime-base/android-system.cc +++ b/src/native/runtime-base/android-system.cc @@ -65,7 +65,7 @@ AndroidSystem::lookup_system_property (const char *name, size_t &value_len) noex return nullptr; if (application_config.system_property_count % 2 != 0) { - log_warn (LOG_DEFAULT, "Corrupted environment variable array: does not contain an even number of entries (%u)", application_config.system_property_count); + log_warn (LOG_DEFAULT, std::format ("Corrupted environment variable array: does not contain an even number of entries ({})", application_config.system_property_count)); return nullptr; } @@ -138,7 +138,7 @@ AndroidSystem::_monodroid__system_property_get (const char *name, char *sp_value char *buf = nullptr; if (sp_value_len < PROPERTY_VALUE_BUFFER_LEN) { size_t alloc_size = Helpers::add_with_overflow_check (PROPERTY_VALUE_BUFFER_LEN, 1uz); - log_warn (LOG_DEFAULT, "Buffer to store system property may be too small, will copy only %u bytes", sp_value_len); + log_warn (LOG_DEFAULT, std::format ("Buffer to store system property may be too small, will copy only {} bytes", sp_value_len)); buf = new char [alloc_size]; } @@ -250,12 +250,12 @@ AndroidSystem::monodroid_get_system_property_from_overrides ([[maybe_unused]] co } std::unique_ptr override_file {Util::path_combine (od, name)}; - log_info (LOG_DEFAULT, "Trying to get property from %s", override_file.get ()); + log_info (LOG_DEFAULT, std::format ("Trying to get property from {}", override_file.get ())); size_t result = _monodroid_get_system_property_from_file (override_file.get (), value); if (result == 0 || value == nullptr || (*value) == nullptr || **value == '\0') { continue; } - log_info (LOG_DEFAULT, "Property '%s' from %s has value '%s'.", name, od, *value); + log_info (LOG_DEFAULT, std::format ("Property '{}' from {} has value '{}'.", name, od, *value)); return result; } #endif // def DEBUG @@ -281,7 +281,7 @@ AndroidSystem::create_update_dir (char *override_dir) noexcept override_dirs [0] = override_dir; Util::create_public_directory (override_dir); - log_warn (LOG_DEFAULT, "Creating public update directory: `%s`", override_dir); + log_warn (LOG_DEFAULT, std::format ("Creating public update directory: `{}`", override_dir)); } bool @@ -306,16 +306,16 @@ AndroidSystem::load_dso (const char *path, unsigned int dl_flags, bool skip_exis if (path == nullptr || *path == '\0') return nullptr; - log_info (LOG_ASSEMBLY, "Trying to load shared library '%s'", path); + log_info (LOG_ASSEMBLY, std::format ("Trying to load shared library '{}'", path)); if (!skip_exists_check && !is_embedded_dso_mode_enabled () && !Util::file_exists (path)) { - log_info (LOG_ASSEMBLY, "Shared library '%s' not found", path); + log_info (LOG_ASSEMBLY, std::format ("Shared library '{}' not found", path)); return nullptr; } char *error = nullptr; void *handle = java_interop_lib_load (path, dl_flags, &error); if (handle == nullptr && Util::should_log (LOG_ASSEMBLY)) - log_info_nocheck (LOG_ASSEMBLY, "Failed to load shared library '%s'. %s", path, error); + log_info_nocheck (LOG_ASSEMBLY, std::format ("Failed to load shared library '{}'. {}", path, error)); java_interop_free (error); return handle; } @@ -450,9 +450,9 @@ AndroidSystem::get_max_gref_count_from_system (void) noexcept if (max < 0) max = std::numeric_limits::max (); if (*e) { - log_warn (LOG_GC, "Unsupported '%s' value '%s'.", SharedConstants::DEBUG_MONO_MAX_GREFC.data (), override.get ()); + log_warn (LOG_GC, std::format ("Unsupported '{}' value '{}'.", SharedConstants::DEBUG_MONO_MAX_GREFC.data (), override.get ())); } - log_warn (LOG_GC, "Overriding max JNI Global Reference count to %i", max); + log_warn (LOG_GC, std::format ("Overriding max JNI Global Reference count to {}", max)); } return max; } @@ -478,7 +478,7 @@ AndroidSystem::setup_environment (const char *name, const char *value) noexcept if (isupper (name [0]) || name [0] == '_') { if (setenv (name, v, 1) < 0) - log_warn (LOG_DEFAULT, "(Debug) Failed to set environment variable: %s", strerror (errno)); + log_warn (LOG_DEFAULT, std::format ("(Debug) Failed to set environment variable: {}", strerror (errno))); return; } @@ -492,13 +492,13 @@ AndroidSystem::setup_environment_from_override_file (const char *path) noexcept struct stat sbuf; if (::stat (path, &sbuf) < 0) { - log_warn (LOG_DEFAULT, "Failed to stat the environment override file %s: %s", path, strerror (errno)); + log_warn (LOG_DEFAULT, std::format ("Failed to stat the environment override file {}: {}", path, strerror (errno))); return; } int fd = open (path, O_RDONLY); if (fd < 0) { - log_warn (LOG_DEFAULT, "Failed to open the environment override file %s: %s", path, strerror (errno)); + log_warn (LOG_DEFAULT, std::format ("Failed to open the environment override file {}: {}", path, strerror (errno))); return; } @@ -515,7 +515,7 @@ AndroidSystem::setup_environment_from_override_file (const char *path) noexcept } while (r < 0 && errno == EINTR); if (nread == 0) { - log_warn (LOG_DEFAULT, "Failed to read the environment override file %s: %s", path, strerror (errno)); + log_warn (LOG_DEFAULT, std::format ("Failed to read the environment override file {}: {}", path, strerror (errno))); return; } @@ -536,26 +536,26 @@ AndroidSystem::setup_environment_from_override_file (const char *path) noexcept // # Variable value, terminated with NUL and padded to [value width] with NUL characters // value\0 if (nread < OVERRIDE_ENVIRONMENT_FILE_HEADER_SIZE) { - log_warn (LOG_DEFAULT, "Invalid format of the environment override file %s: malformatted header", path); + log_warn (LOG_DEFAULT, std::format ("Invalid format of the environment override file {}: malformatted header", path)); return; } char *endptr; unsigned long name_width = strtoul (buf.get (), &endptr, 16); if ((name_width == std::numeric_limits::max () && errno == ERANGE) || (buf[0] != '\0' && *endptr != '\0')) { - log_warn (LOG_DEFAULT, "Malformed header of the environment override file %s: name width has invalid format", path); + log_warn (LOG_DEFAULT, std::format ("Malformed header of the environment override file {}: name width has invalid format", path)); return; } unsigned long value_width = strtoul (buf.get () + 11, &endptr, 16); if ((value_width == std::numeric_limits::max () && errno == ERANGE) || (buf[0] != '\0' && *endptr != '\0')) { - log_warn (LOG_DEFAULT, "Malformed header of the environment override file %s: value width has invalid format", path); + log_warn (LOG_DEFAULT, std::format ("Malformed header of the environment override file {}: value width has invalid format", path)); return; } uint64_t data_width = name_width + value_width; if (data_width > file_size - OVERRIDE_ENVIRONMENT_FILE_HEADER_SIZE || (file_size - OVERRIDE_ENVIRONMENT_FILE_HEADER_SIZE) % data_width != 0) { - log_warn (LOG_DEFAULT, "Malformed environment override file %s: invalid data size", path); + log_warn (LOG_DEFAULT, std::format ("Malformed environment override file {}: invalid data size", path)); return; } @@ -563,11 +563,11 @@ AndroidSystem::setup_environment_from_override_file (const char *path) noexcept char *name = buf.get () + OVERRIDE_ENVIRONMENT_FILE_HEADER_SIZE; while (data_size > 0 && data_size >= data_width) { if (*name == '\0') { - log_warn (LOG_DEFAULT, "Malformed environment override file %s: name at offset %lu is empty", path, name - buf.get ()); + log_warn (LOG_DEFAULT, std::format ("Malformed environment override file {}: name at offset {} is empty", path, name - buf.get ())); return; } - log_debug (LOG_DEFAULT, "Setting environment variable from the override file %s: '%s' = '%s'", path, name, name + name_width); + log_debug (LOG_DEFAULT, std::format ("Setting environment variable from the override file {}: '{}' = '{}'", path, name, name + name_width)); setup_environment (name, name + name_width); name += data_width; data_size -= data_width; @@ -602,18 +602,18 @@ AndroidSystem::setup_environment () noexcept } if (aotMode != MonoAotMode::MONO_AOT_MODE_LAST) { - log_debug (LOG_DEFAULT, "Mono AOT mode: %s", mono_aot_mode_name); + log_debug (LOG_DEFAULT, std::format ("Mono AOT mode: {}", mono_aot_mode_name)); } else { if (!is_interpreter_enabled ()) { - log_warn (LOG_DEFAULT, "Unknown Mono AOT mode: %s", mono_aot_mode_name); + log_warn (LOG_DEFAULT, std::format ("Unknown Mono AOT mode: {}", mono_aot_mode_name)); } else { - log_warn (LOG_DEFAULT, "Mono AOT mode: interpreter"); + log_warn (LOG_DEFAULT, "Mono AOT mode: interpreter"sv); } } } if (application_config.environment_variable_count % 2 != 0) { - log_warn (LOG_DEFAULT, "Corrupted environment variable array: does not contain an even number of entries (%u)", application_config.environment_variable_count); + log_warn (LOG_DEFAULT, std::format ("Corrupted environment variable array: does not contain an even number of entries ({})", application_config.environment_variable_count)); return; } @@ -629,21 +629,21 @@ AndroidSystem::setup_environment () noexcept var_value = ""; #if defined (DEBUG) - log_info (LOG_DEFAULT, "Setting environment variable '%s' to '%s'", var_name, var_value); + log_info (LOG_DEFAULT, std::format ("Setting environment variable '{}' to '{}'", var_name, var_value)); #endif // def DEBUG if (setenv (var_name, var_value, 1) < 0) - log_warn (LOG_DEFAULT, "Failed to set environment variable: %s", strerror (errno)); + log_warn (LOG_DEFAULT, std::format ("Failed to set environment variable: {}", strerror (errno))); } #if defined (DEBUG) - log_debug (LOG_DEFAULT, "Loading environment from override directories."); + log_debug (LOG_DEFAULT, "Loading environment from override directories."sv); for (const char *od : override_dirs) { if (od == nullptr) { continue; } std::unique_ptr env_override_file {Util::path_combine (od, OVERRIDE_ENVIRONMENT_FILE_NAME.data ())}; - log_debug (LOG_DEFAULT, "%s", env_override_file.get ()); + log_debug (LOG_DEFAULT, std::format ("{}", env_override_file.get ())); if (Util::file_exists (env_override_file.get ())) { - log_debug (LOG_DEFAULT, "Loading %s", env_override_file.get ()); + log_debug (LOG_DEFAULT, std::format ("Loading {}", env_override_file.get ())); setup_environment_from_override_file (env_override_file.get ()); } } @@ -671,12 +671,12 @@ AndroidSystem::detect_embedded_dso_mode (jstring_array_wrapper& appDirs) noexcep { // appDirs[SharedConstants::APP_DIRS_DATA_DIR_INDEX] points to the native library directory std::unique_ptr libmonodroid_path {Util::path_combine (appDirs[SharedConstants::APP_DIRS_DATA_DIR_INDEX].get_cstr (), "libmonodroid.so")}; - log_debug (LOG_ASSEMBLY, "Checking if libmonodroid was unpacked to %s", libmonodroid_path.get ()); + log_debug (LOG_ASSEMBLY, std::format ("Checking if libmonodroid was unpacked to {}", libmonodroid_path.get ())); if (!Util::file_exists (libmonodroid_path.get ())) { - log_debug (LOG_ASSEMBLY, "%s not found, assuming application/android:extractNativeLibs == false", libmonodroid_path.get ()); + log_debug (LOG_ASSEMBLY, std::format ("{} not found, assuming application/android:extractNativeLibs == false", libmonodroid_path.get ())); set_embedded_dso_mode_enabled (true); } else { - log_debug (LOG_ASSEMBLY, "Native libs extracted to %s, assuming application/android:extractNativeLibs == true", appDirs[SharedConstants::APP_DIRS_DATA_DIR_INDEX].get_cstr ()); + log_debug (LOG_ASSEMBLY, std::format ("Native libs extracted to {}, assuming application/android:extractNativeLibs == true", appDirs[SharedConstants::APP_DIRS_DATA_DIR_INDEX].get_cstr ())); set_embedded_dso_mode_enabled (false); } } @@ -685,13 +685,13 @@ void AndroidSystem::setup_app_library_directories (jstring_array_wrapper& runtimeApks, jstring_array_wrapper& appDirs, bool have_split_apks) noexcept { if (!is_embedded_dso_mode_enabled ()) { - log_debug (LOG_DEFAULT, "Setting up for DSO lookup in app data directories"); + log_debug (LOG_DEFAULT, "Setting up for DSO lookup in app data directories"sv); AndroidSystem::app_lib_directories = std::span (single_app_lib_directory); AndroidSystem::app_lib_directories [0] = Util::strdup_new (appDirs[SharedConstants::APP_DIRS_DATA_DIR_INDEX].get_cstr ()); - log_debug (LOG_ASSEMBLY, "Added filesystem DSO lookup location: %s", appDirs[SharedConstants::APP_DIRS_DATA_DIR_INDEX].get_cstr ()); + log_debug (LOG_ASSEMBLY, std::format ("Added filesystem DSO lookup location: {}", appDirs[SharedConstants::APP_DIRS_DATA_DIR_INDEX].get_cstr ())); } else { - log_debug (LOG_DEFAULT, "Setting up for DSO lookup directly in the APK"); + log_debug (LOG_DEFAULT, "Setting up for DSO lookup directly in the APK"sv); if (have_split_apks) { // If split apks are used, then we will have just a single app library directory. Don't allocate any memory @@ -725,7 +725,7 @@ AndroidSystem::add_apk_libdir (const char *apk, size_t &index, const char *abi) { abort_unless (index < app_lib_directories.size (), "Index out of range"); app_lib_directories [index] = Util::string_concat (apk, "!/lib/", abi); - log_debug (LOG_ASSEMBLY, "Added APK DSO lookup location: %s", app_lib_directories[index]); + log_debug (LOG_ASSEMBLY, std::format ("Added APK DSO lookup location: {}", app_lib_directories[index])); index++; } diff --git a/src/native/runtime-base/monodroid-dl.hh b/src/native/runtime-base/monodroid-dl.hh index 14455578f0e..43e1b891a0e 100644 --- a/src/native/runtime-base/monodroid-dl.hh +++ b/src/native/runtime-base/monodroid-dl.hh @@ -48,11 +48,11 @@ namespace xamarin::android::internal size_t arr_size; if constexpr (WhichCache == CacheKind::AOT) { - log_debug (LOG_ASSEMBLY, "Looking for hash 0x%x in AOT cache", hash); + log_debug (LOG_ASSEMBLY, std::format ("Looking for hash {:x} in AOT cache", hash)); arr = aot_dso_cache; arr_size = application_config.number_of_aot_cache_entries; } else if constexpr (WhichCache == CacheKind::DSO) { - log_debug (LOG_ASSEMBLY, "Looking for hash 0x%x in DSO cache", hash); + log_debug (LOG_ASSEMBLY, std::format ("Looking for hash {:x} in DSO cache", hash)); arr = dso_cache; arr_size = application_config.number_of_dso_cache_entries; } @@ -102,7 +102,7 @@ namespace xamarin::android::internal if (MonodroidState::is_startup_in_progress ()) { auto ignore_component = [&](const char *label, MonoComponent component) -> bool { if ((application_config.mono_components_mask & component) != component) { - log_info (LOG_ASSEMBLY, "Mono '%s' component requested but not packaged, ignoring", label); + log_info (LOG_ASSEMBLY, std::format ("Mono '{}' component requested but not packaged, ignoring", label)); return true; } @@ -145,12 +145,12 @@ namespace xamarin::android::internal static void* monodroid_dlopen (const char *name, int flags, char **err, bool prefer_aot_cache) noexcept { if (name == nullptr) { - log_warn (LOG_ASSEMBLY, "monodroid_dlopen got a null name. This is not supported in NET+"); + log_warn (LOG_ASSEMBLY, "monodroid_dlopen got a null name. This is not supported in NET+"sv); return nullptr; } hash_t name_hash = xxhash::hash (name, strlen (name)); - log_debug (LOG_ASSEMBLY, "monodroid_dlopen: hash for name '%s' is 0x%zx", name, name_hash); + log_debug (LOG_ASSEMBLY, std::format ("monodroid_dlopen: hash for name '{}' is {:x}", name, name_hash)); DSOCacheEntry *dso = nullptr; if (prefer_aot_cache) { @@ -167,7 +167,7 @@ namespace xamarin::android::internal dso = find_only_dso_cache_entry (name_hash); } - log_debug (LOG_ASSEMBLY, "monodroid_dlopen: hash match %sfound, DSO name is '%s'", dso == nullptr ? "not " : "", dso == nullptr ? "" : dso->name); + log_debug (LOG_ASSEMBLY, std::format ("monodroid_dlopen: hash match {}found, DSO name is '{}'", dso == nullptr ? "not "sv : ""sv, dso == nullptr ? ""sv : dso->name)); if (dso == nullptr) { // DSO not known at build time, try to load it @@ -177,7 +177,7 @@ namespace xamarin::android::internal } if (dso->ignore) { - log_info (LOG_ASSEMBLY, "Request to load '%s' ignored, it is known not to exist", dso->name); + log_info (LOG_ASSEMBLY, std::format ("Request to load '{}' ignored, it is known not to exist", dso->name)); return nullptr; } diff --git a/src/native/shared/log_types.hh b/src/native/shared/log_types.hh index f6fb1142597..ff558a8185a 100644 --- a/src/native/shared/log_types.hh +++ b/src/native/shared/log_types.hh @@ -8,11 +8,7 @@ #include "java-interop-logger.h" -// We redeclare macros as real functions here -#if defined(DO_LOG) -#undef DO_LOG -#endif - +// We redeclare macros here #if defined(log_debug) #undef log_debug #endif @@ -21,15 +17,17 @@ #undef log_info #endif -namespace xamarin::android { - namespace detail { - [[gnu::always_inline]] - static inline bool _category_is_enabled (LogCategories category) noexcept - { - return (log_categories & category) == category; - } - } +#define DO_LOG_FMT(_level, _category_, _message_) \ + do { \ + if ((log_categories & ((_category_))) != 0) { \ + ::log_ ## _level ## _nocheck ((_category_), _message_); \ + } \ + } while (0) + +#define log_debug(_category_, _message_) DO_LOG_FMT (debug, (_category_), (_message_)) +#define log_info(_category_, _message_) DO_LOG_FMT (info, (_category_), (_message_)) +namespace xamarin::android { enum class LogTimingCategories : uint32_t { Default = 0, @@ -54,109 +52,79 @@ namespace xamarin::android { // A slightly faster alternative to other log functions as it doesn't parse the message // for format placeholders nor it uses variable arguments void log_write (LogCategories category, LogLevel level, const char *message) noexcept; +} - template [[gnu::always_inline]] - static inline constexpr void log_debug (LogCategories category, const char *format, Args&& ...args) noexcept - { - if (detail::_category_is_enabled (category)) { - ::log_debug_nocheck (category, format, std::forward(args)...); - } - } - - template [[gnu::always_inline]] - static inline constexpr void log_debug (LogCategories category, std::string_view const& format, Args&& ...args) noexcept - { - if (detail::_category_is_enabled (category)) { - ::log_debug_nocheck (category, format.data (), std::forward(args)...); - } - } - - static inline constexpr void log_debug (LogCategories category, std::string const& message) noexcept - { - if (detail::_category_is_enabled (category)) { - ::log_debug_nocheck (category, message.c_str ()); - } - } - - // - // This will be enabled once all log_* calls are converted to std::format format - // - // template [[gnu::always_inline]] - // static inline constexpr void log_debug (LogCategories category, std::format_string fmt, Args&& ...args) - // { - // if (detail::_category_is_enabled (category)) { - - // log_debug_nocheck (category, std::format (fmt, std::forward(args)...).c_str ()); - // } - // } - - template [[gnu::always_inline]] - static inline constexpr void log_info (LogCategories category, const char *format, Args&& ...args) noexcept - { - if (detail::_category_is_enabled (category)) { - ::log_info_nocheck (category, format, std::forward(args)...); - } - } +// +// This will be enabled once all log_* calls are converted to std::format format +// +// template [[gnu::always_inline]] +// static inline constexpr void log_debug (LogCategories category, std::format_string fmt, Args&& ...args) +// { +// if (detail::_category_is_enabled (category)) { + +// log_debug_nocheck (category, std::format (fmt, std::forward(args)...).c_str ()); +// } +// } + +[[gnu::always_inline]] +static inline constexpr void log_debug_nocheck (LogCategories category, std::string const& message) noexcept +{ + log_write (category, xamarin::android::LogLevel::Debug, message.c_str ()); +} - template [[gnu::always_inline]] - static inline constexpr void log_info (LogCategories category, std::string_view const& format, Args&& ...args) noexcept - { - if (detail::_category_is_enabled (category)) { - ::log_info_nocheck (category, format.data (), std::forward(args)...); - } - } +[[gnu::always_inline]] +static inline constexpr void log_debug_nocheck (LogCategories category, std::string_view const& message) noexcept +{ + log_write (category, xamarin::android::LogLevel::Debug, message.data ()); +} - [[gnu::always_inline]] - static inline constexpr void log_info (LogCategories category, std::string const& message) noexcept - { - if (detail::_category_is_enabled (category)) { - ::log_info_nocheck (category, message.c_str ()); - } - } +[[gnu::always_inline]] +static inline constexpr void log_info_nocheck (LogCategories category, std::string const& message) noexcept +{ + log_write (category, xamarin::android::LogLevel::Info, message.c_str ()); +} - [[gnu::always_inline]] - static inline constexpr void log_info_nocheck (LogCategories category, std::string const& message) noexcept - { - if (detail::_category_is_enabled (category)) { - ::log_info_nocheck (category, message.c_str ()); - } - } +[[gnu::always_inline]] +static inline constexpr void log_info_nocheck (LogCategories category, std::string_view const& message) noexcept +{ + log_write (category, xamarin::android::LogLevel::Info, message.data ()); +} - [[gnu::always_inline]] - static inline constexpr void log_warn (LogCategories category, std::string const& message) noexcept - { - ::log_warn (category, message.c_str ()); - } +[[gnu::always_inline]] +static inline constexpr void log_warn (LogCategories category, std::string const& message) noexcept +{ + log_write (category, xamarin::android::LogLevel::Warn, message.c_str ()); +} - [[gnu::always_inline]] - static inline constexpr void log_warn (LogCategories category, std::string_view const& message) noexcept - { - ::log_warn (category, message.data ()); - } +[[gnu::always_inline]] +static inline constexpr void log_warn (LogCategories category, std::string_view const& message) noexcept +{ + log_write (category, xamarin::android::LogLevel::Warn, message.data ()); +} - [[gnu::always_inline]] - static inline constexpr void log_error (LogCategories category, std::string const& message) noexcept - { - ::log_error (category, message.c_str ()); - } +[[gnu::always_inline]] +static inline constexpr void log_error (LogCategories category, std::string const& message) noexcept +{ + log_write (category, xamarin::android::LogLevel::Error, message.c_str ()); +} - [[gnu::always_inline]] - static inline constexpr void log_error (LogCategories category, std::string_view const& message) noexcept - { - ::log_error (category, message.data ()); - } +[[gnu::always_inline]] +static inline constexpr void log_error (LogCategories category, std::string_view const& message) noexcept +{ + log_write (category, xamarin::android::LogLevel::Error, message.data ()); +} - [[gnu::always_inline]] - static inline constexpr void log_fatal (LogCategories category, std::string const& message) noexcept - { - ::log_fatal (category, message.c_str ()); - } +[[gnu::always_inline]] +static inline constexpr void log_fatal (LogCategories category, std::string const& message) noexcept +{ + log_write (category, xamarin::android::LogLevel::Fatal, message.c_str ()); +} - [[gnu::always_inline]] - static inline constexpr void log_fatal (LogCategories category, std::string_view const& message) noexcept - { - ::log_fatal (category, message.data ()); - } +[[gnu::always_inline]] +static inline constexpr void log_fatal (LogCategories category, std::string_view const& message) noexcept +{ + log_write (category, xamarin::android::LogLevel::Fatal, message.data ()); } + extern unsigned int log_categories; #endif // ndef LOG_LEVEL_HH From 4e3fa71a1d8872b153cfbb71a2d4665b942a60d3 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Wed, 27 Nov 2024 20:51:12 +0100 Subject: [PATCH 42/54] More std::format --- .../monodroid/embedded-assemblies-zip.cc | 2 +- src/native/monodroid/internal-pinvokes.cc | 16 +-- src/native/monodroid/mono-image-loader.hh | 6 +- .../monodroid/monodroid-glue-internal.hh | 2 +- src/native/monodroid/monodroid-networkinfo.cc | 18 +-- src/native/monodroid/monodroid-tracing.cc | 2 +- .../monodroid/xamarin-android-app-context.cc | 46 +++++--- src/native/pinvoke-override/precompiled.cc | 2 +- src/native/runtime-base/internal-pinvokes.hh | 2 +- src/native/runtime-base/logger.cc | 17 ++- src/native/runtime-base/strings.hh | 8 +- src/native/runtime-base/timing-internal.cc | 6 +- src/native/runtime-base/timing-internal.hh | 4 +- src/native/runtime-base/timing.hh | 24 +--- src/native/runtime-base/util.cc | 12 +- src/native/runtime-base/util.hh | 4 +- src/native/shared/cpp-util.hh | 2 +- src/native/shared/helpers.cc | 15 +-- src/native/shared/log_functions.cc | 2 +- src/native/shared/log_types.hh | 4 +- .../debug-app-helper.cc | 103 ++++-------------- 21 files changed, 119 insertions(+), 178 deletions(-) diff --git a/src/native/monodroid/embedded-assemblies-zip.cc b/src/native/monodroid/embedded-assemblies-zip.cc index 16b2c817b64..35ef82d68f7 100644 --- a/src/native/monodroid/embedded-assemblies-zip.cc +++ b/src/native/monodroid/embedded-assemblies-zip.cc @@ -45,7 +45,7 @@ EmbeddedAssemblies::zip_load_entry_common (size_t entry_index, std::vector + #include "android-system.hh" #include "globals.hh" #include "internal-pinvokes.hh" @@ -31,30 +33,30 @@ monodroid_log (LogLevel level, LogCategories category, const char *message) switch (level) { case LogLevel::Verbose: case LogLevel::Debug: - log_debug_nocheck (category, message); + log_debug_nocheck (category, std::string_view { message }); break; case LogLevel::Info: - log_info_nocheck (category, message); + log_info_nocheck (category, std::string_view { message }); break; case LogLevel::Warn: case LogLevel::Silent: // warn is always printed - log_warn (category, message); + log_warn (category, std::string_view { message }); break; case LogLevel::Error: - log_error (category, message); + log_error (category, std::string_view { message }); break; case LogLevel::Fatal: - log_fatal (category, message); + log_fatal (category, std::string_view { message }); break; default: case LogLevel::Unknown: case LogLevel::Default: - log_info_nocheck (category, message); + log_info_nocheck (category, std::string_view { message }); break; } } @@ -156,7 +158,7 @@ _monodroid_timezone_get_default_id () const char *mutf8 = env->GetStringUTFChars (id, nullptr); if (mutf8 == nullptr) { - log_error (LOG_DEFAULT, "Failed to convert Java TimeZone ID to UTF8 (out of memory?)"); + log_error (LOG_DEFAULT, "Failed to convert Java TimeZone ID to UTF8 (out of memory?)"sv); env->DeleteLocalRef (id); env->DeleteLocalRef (d); return nullptr; diff --git a/src/native/monodroid/mono-image-loader.hh b/src/native/monodroid/mono-image-loader.hh index 783b6af679c..d843bf32188 100644 --- a/src/native/monodroid/mono-image-loader.hh +++ b/src/native/monodroid/mono-image-loader.hh @@ -110,7 +110,7 @@ namespace xamarin::android::internal { force_inline static MonoImage* stash_and_return (MonoImage *image, MonoImageOpenStatus status, [[maybe_unused]] hash_t hash) noexcept { if (image == nullptr || status != MonoImageOpenStatus::MONO_IMAGE_OK) { - log_warn (LOG_ASSEMBLY, "Failed to open assembly image. %s", mono_image_strerror (status)); + log_warn (LOG_ASSEMBLY, std::format ("Failed to open assembly image. {}", mono_image_strerror (status))); return nullptr; } @@ -119,8 +119,8 @@ namespace xamarin::android::internal { if (index < 0) { Helpers::abort_application ( LOG_ASSEMBLY, - Util::monodroid_strdup_printf ( - "Failed to look up image index for hash 0x%zx", + std::format ( + "Failed to look up image index for hash {:x}", hash ) ); diff --git a/src/native/monodroid/monodroid-glue-internal.hh b/src/native/monodroid/monodroid-glue-internal.hh index 59f00ceffd2..dbd78121458 100644 --- a/src/native/monodroid/monodroid-glue-internal.hh +++ b/src/native/monodroid/monodroid-glue-internal.hh @@ -166,7 +166,7 @@ namespace xamarin::android::internal void *symptr = MonodroidDl::monodroid_dlsym (handle, name, &err, nullptr); if (symptr == nullptr) { - log_warn (LOG_DEFAULT, "Failed to load symbol '%s' library with handle %p. %s", name, handle, err == nullptr ? "Unknown error" : err); + log_warn (LOG_DEFAULT, std::format ("Failed to load symbol '{}' library with handle {}. {}", name, handle, err == nullptr ? "Unknown error"sv : err)); fnptr = nullptr; return; } diff --git a/src/native/monodroid/monodroid-networkinfo.cc b/src/native/monodroid/monodroid-networkinfo.cc index 50267299def..f9dcba4c181 100644 --- a/src/native/monodroid/monodroid-networkinfo.cc +++ b/src/native/monodroid/monodroid-networkinfo.cc @@ -76,10 +76,10 @@ _monodroid_get_network_interface_state (const char *ifname, mono_bool *is_up, mo if (!NetworkInterface_class || !NetworkInterface_getByName) { if (!NetworkInterface_class) - log_warn (LOG_NET, "Failed to find the 'java.net.NetworkInterface' Java class"); + log_warn (LOG_NET, "Failed to find the 'java.net.NetworkInterface' Java class"sv); if (!NetworkInterface_getByName) - log_warn (LOG_NET, "Failed to find the 'java.net.NetworkInterface.getByName' function"); - log_warn (LOG_NET, "Unable to determine network interface state because of missing Java API"); + log_warn (LOG_NET, "Failed to find the 'java.net.NetworkInterface.getByName' function"sv); + log_warn (LOG_NET, "Unable to determine network interface state because of missing Java API"sv); goto leave; } @@ -88,21 +88,21 @@ _monodroid_get_network_interface_state (const char *ifname, mono_bool *is_up, mo networkInterface = env->CallStaticObjectMethod (NetworkInterface_class, NetworkInterface_getByName, NetworkInterface_nameArg); env->DeleteLocalRef (NetworkInterface_nameArg); if (env->ExceptionOccurred ()) { - log_warn (LOG_NET, "Java exception occurred while looking up the interface '%s'", ifname); + log_warn (LOG_NET, std::format ("Java exception occurred while looking up the interface '{}'", ifname)); env->ExceptionDescribe (); env->ExceptionClear (); goto leave; } if (!networkInterface) { - log_warn (LOG_NET, "Failed to look up interface '%s' using Java API", ifname); + log_warn (LOG_NET, std::format ("Failed to look up interface '{}' using Java API", ifname)); ret = FALSE; goto leave; } if (is_up) { if (!NetworkInterface_isUp) { - log_warn (LOG_NET, "Failed to find the 'java.net.NetworkInterface.isUp' function. Unable to determine interface operational state"); + log_warn (LOG_NET, "Failed to find the 'java.net.NetworkInterface.isUp' function. Unable to determine interface operational state"sv); ret = FALSE; } else *is_up = (mono_bool)env->CallBooleanMethod (networkInterface, NetworkInterface_isUp); @@ -110,7 +110,7 @@ _monodroid_get_network_interface_state (const char *ifname, mono_bool *is_up, mo if (supports_multicast) { if (!NetworkInterface_supportsMulticast) { - log_warn (LOG_NET, "Failed to find the 'java.net.NetworkInterface.supportsMulticast' function. Unable to determine whether interface supports multicast"); + log_warn (LOG_NET, "Failed to find the 'java.net.NetworkInterface.supportsMulticast' function. Unable to determine whether interface supports multicast"sv); ret = FALSE; } else *supports_multicast = (mono_bool)env->CallBooleanMethod (networkInterface, NetworkInterface_supportsMulticast); @@ -118,7 +118,7 @@ _monodroid_get_network_interface_state (const char *ifname, mono_bool *is_up, mo leave: if (!ret) - log_warn (LOG_NET, "Unable to determine interface '%s' state using Java API", ifname); + log_warn (LOG_NET, std::format ("Unable to determine interface '{}' state using Java API", ifname)); if (networkInterface != nullptr && env != nullptr) { env->DeleteLocalRef (networkInterface); @@ -143,7 +143,7 @@ int _monodroid_get_dns_servers (void **dns_servers_array) { if (!dns_servers_array) { - log_warn (LOG_NET, "Unable to get DNS servers, no location to store data in"); + log_warn (LOG_NET, "Unable to get DNS servers, no location to store data in"sv); return -1; } *dns_servers_array = nullptr; diff --git a/src/native/monodroid/monodroid-tracing.cc b/src/native/monodroid/monodroid-tracing.cc index 7b5c3d9e4f2..56db0e50dd1 100644 --- a/src/native/monodroid/monodroid-tracing.cc +++ b/src/native/monodroid/monodroid-tracing.cc @@ -27,7 +27,7 @@ MonodroidRuntime::log_traces (JNIEnv *env, TraceKind kind, const char *first_lin char *err = nullptr; void *handle = MonodroidDl::monodroid_dlopen (SharedConstants::xamarin_native_tracing_name.data (), MONO_DL_EAGER, &err, nullptr); if (handle == nullptr) { - log_warn (LOG_DEFAULT, "Failed to load native tracing library '%s'. %s", SharedConstants::xamarin_native_tracing_name, err == nullptr ? "Unknown error" : err); + log_warn (LOG_DEFAULT, std::format ("Failed to load native tracing library '{}'. {}", SharedConstants::xamarin_native_tracing_name, err == nullptr ? "Unknown error"sv : err)); } else { load_symbol (handle, "xa_get_native_backtrace", _xa_get_native_backtrace); load_symbol (handle, "xa_get_managed_backtrace", _xa_get_managed_backtrace); diff --git a/src/native/monodroid/xamarin-android-app-context.cc b/src/native/monodroid/xamarin-android-app-context.cc index 925975c336f..e55635f2443 100644 --- a/src/native/monodroid/xamarin-android-app-context.cc +++ b/src/native/monodroid/xamarin-android-app-context.cc @@ -15,7 +15,7 @@ MonodroidRuntime::get_method_name (uint32_t mono_image_index, uint32_t method_to { uint64_t id = (static_cast(mono_image_index) << 32) | method_token; - log_debug (LOG_ASSEMBLY, "MM: looking for name of method with id 0x%llx, in mono image at index %u", id, mono_image_index); + log_debug (LOG_ASSEMBLY, std::format ("MM: looking for name of method with id {:x}, in mono image at index {}", id, mono_image_index)); size_t i = 0uz; while (mm_method_names[i].id != 0) { if (mm_method_names[i].id == id) { @@ -43,15 +43,16 @@ MonodroidRuntime::get_function_pointer (uint32_t mono_image_index, uint32_t clas { log_debug ( LOG_ASSEMBLY, - "MM: Trying to look up pointer to method '%s' (token 0x%x) in class '%s' (index %u)", - get_method_name (mono_image_index, method_token), method_token, - get_class_name (class_index), class_index + std::format ("MM: Trying to look up pointer to method '{}' (token {:x}) in class '{}' (index {})", + get_method_name (mono_image_index, method_token), method_token, + get_class_name (class_index), class_index + ) ); if (class_index >= marshal_methods_number_of_classes) [[unlikely]] { Helpers::abort_application ( - Util::monodroid_strdup_printf ( - "Internal error: invalid index for class cache (expected at most %u, got %u)", + std::format ( + "Internal error: invalid index for class cache (expected at most {}, got {})", marshal_methods_number_of_classes - 1, class_index ) @@ -78,29 +79,40 @@ MonodroidRuntime::get_function_pointer (uint32_t mono_image_index, uint32_t clas target_ptr = ret; } - log_debug (LOG_ASSEMBLY, "Loaded pointer to method %s (%p) (mono_image_index == %u; class_index == %u; method_token == 0x%x)", mono_method_full_name (method, true), ret, mono_image_index, class_index, method_token); + log_debug ( + LOG_ASSEMBLY, + std::format ("Loaded pointer to method {} ({:p}) (mono_image_index == {}; class_index == {}; method_token == {:x})", + mono_method_full_name (method, true), + ret, + mono_image_index, + class_index, + method_token + ) + ); return; } log_fatal ( LOG_DEFAULT, - "Failed to obtain function pointer to method '%s' in class '%s'", - get_method_name (mono_image_index, method_token), - get_class_name (class_index) + std::format ("Failed to obtain function pointer to method '{}' in class '{}'", + get_method_name (mono_image_index, method_token), + get_class_name (class_index) + ) ); log_fatal ( LOG_DEFAULT, - "Looked for image index %u, class index %u, method token 0x%x", - mono_image_index, - class_index, - method_token + std::format ("Looked for image index {}, class index {}, method token {:x}", + mono_image_index, + class_index, + method_token + ) ); if (image == nullptr) { - log_fatal (LOG_DEFAULT, "Failed to load MonoImage for the assembly"); + log_fatal (LOG_DEFAULT, "Failed to load MonoImage for the assembly"sv); } else if (method == nullptr) { - log_fatal (LOG_DEFAULT, "Failed to load class from the assembly"); + log_fatal (LOG_DEFAULT, "Failed to load class from the assembly"sv); } const char *message = nullptr; @@ -109,7 +121,7 @@ MonodroidRuntime::get_function_pointer (uint32_t mono_image_index, uint32_t clas } Helpers::abort_application ( - message == nullptr ? "Failure to obtain marshal methods function pointer" : message + message == nullptr ? "Failure to obtain marshal methods function pointer"sv : message ); } diff --git a/src/native/pinvoke-override/precompiled.cc b/src/native/pinvoke-override/precompiled.cc index 90ad9214ecd..1ef4bbfaba0 100644 --- a/src/native/pinvoke-override/precompiled.cc +++ b/src/native/pinvoke-override/precompiled.cc @@ -67,7 +67,7 @@ PinvokeOverride::monodroid_pinvoke_override (const char *library_name, const cha load_library_entry (library_name, entrypoint_name, *entry, dotnet_dso_handle); if (entry->func == nullptr) { - log_fatal (LOG_ASSEMBLY, "Failed to load symbol '%s' from shared library '%s'", entrypoint_name, library_name); + log_fatal (LOG_ASSEMBLY, std::format ("Failed to load symbol '{}' from shared library '{}'", entrypoint_name, library_name)); return nullptr; // let Mono deal with the fallout } diff --git a/src/native/runtime-base/internal-pinvokes.hh b/src/native/runtime-base/internal-pinvokes.hh index b73e390cccf..84477577de8 100644 --- a/src/native/runtime-base/internal-pinvokes.hh +++ b/src/native/runtime-base/internal-pinvokes.hh @@ -3,7 +3,7 @@ #include #include -#include +//#include #include #include diff --git a/src/native/runtime-base/logger.cc b/src/native/runtime-base/logger.cc index 5c4be349fae..cc2f2133a97 100644 --- a/src/native/runtime-base/logger.cc +++ b/src/native/runtime-base/logger.cc @@ -27,8 +27,15 @@ namespace { FILE *f; if (path && access (path, W_OK) < 0) { - log_warn (category, "Could not open path '%s' for logging (\"%s\"). Using '%s/%s' instead.", - path, strerror (errno), override_dir, filename); + log_warn (category, + std::format ( + "Could not open path '{}' for logging (\"{}\"). Using '{}/{}' instead.", + path, + strerror (errno), + override_dir, + filename + ) + ); path = NULL; } @@ -45,7 +52,7 @@ namespace { if (f) { Util::set_world_accessable (path); } else { - log_warn (category, "Could not open path '%s' for logging: %s", path, strerror (errno)); + log_warn (category, std::format ("Could not open path '{}' for logging: {}", path, strerror (errno))); } free (p); @@ -71,12 +78,12 @@ Logger::set_debugger_log_level (const char *level) noexcept unsigned long v = strtoul (level, nullptr, 0); if (v == std::numeric_limits::max () && errno == ERANGE) { - log_error (LOG_DEFAULT, "Invalid debugger log level value '%s', expecting a positive integer or zero", level); + log_error (LOG_DEFAULT, std::format ("Invalid debugger log level value '{}', expecting a positive integer or zero", level)); return; } if (v > std::numeric_limits::max ()) { - log_warn (LOG_DEFAULT, "Debugger log level value is higher than the maximum of %u, resetting to the maximum value.", std::numeric_limits::max ()); + log_warn (LOG_DEFAULT, std::format ("Debugger log level value is higher than the maximum of {}, resetting to the maximum value.", std::numeric_limits::max ())); v = std::numeric_limits::max (); } diff --git a/src/native/runtime-base/strings.hh b/src/native/runtime-base/strings.hh index 74fe498de4c..393a3783525 100644 --- a/src/native/runtime-base/strings.hh +++ b/src/native/runtime-base/strings.hh @@ -156,7 +156,7 @@ namespace xamarin::android::internal } if (!can_access (start_index)) { - log_error (LOG_DEFAULT, "Cannot convert string to integer, index %u is out of range", start_index); + log_error (LOG_DEFAULT, std::format ("Cannot convert string to integer, index {} is out of range", start_index)); return false; } @@ -180,17 +180,17 @@ namespace xamarin::android::internal } if (out_of_range || errno == ERANGE) { - log_error (LOG_DEFAULT, "Value %s is out of range of this type (%lld..%llu)", s, static_cast(min), static_cast(max)); + log_error (LOG_DEFAULT, std::format ("Value {} is out of range of this type ({}..{})", reinterpret_cast(s), static_cast(min), static_cast(max))); return false; } if (endp == s) { - log_error (LOG_DEFAULT, "Value %s does not represent a base %d integer", s, base); + log_error (LOG_DEFAULT, std::format ("Value {} does not represent a base {} integer", reinterpret_cast(s), base)); return false; } if (*endp != '\0') { - log_error (LOG_DEFAULT, "Value %s has non-numeric characters at the end", s); + log_error (LOG_DEFAULT, std::format ("Value {} has non-numeric characters at the end", reinterpret_cast(s))); return false; } diff --git a/src/native/runtime-base/timing-internal.cc b/src/native/runtime-base/timing-internal.cc index eaaee8c17ef..7b23705d880 100644 --- a/src/native/runtime-base/timing-internal.cc +++ b/src/native/runtime-base/timing-internal.cc @@ -78,11 +78,11 @@ FastTiming::dump () noexcept log_write (LOG_TIMING, LogLevel::Info, "[2/4] Accumulated performance results"); ns_to_time (total_assembly_load_time, sec, ms, ns); - log_info_nocheck (LOG_TIMING, " [2/5] Assembly load: %u:%u::%u", sec, ms, ns); + log_info_nocheck (LOG_TIMING, std::format (" [2/5] Assembly load: {}:{}::{}", sec, ms, ns)); ns_to_time (total_java_to_managed_time, sec, ms, ns); - log_info_nocheck (LOG_TIMING, " [2/6] Java to Managed lookup: %u:%u::%u", sec, ms, ns); + log_info_nocheck (LOG_TIMING, std::format (" [2/6] Java to Managed lookup: {}:{}::{}", sec, ms, ns)); ns_to_time (total_managed_to_java_time, sec, ms, ns); - log_info_nocheck (LOG_TIMING, " [2/7] Managed to Java lookup: %u:%u::%u", sec, ms, ns); + log_info_nocheck (LOG_TIMING, std::format (" [2/7] Managed to Java lookup: {}:{}::{}", sec, ms, ns)); } diff --git a/src/native/runtime-base/timing-internal.hh b/src/native/runtime-base/timing-internal.hh index 4e896c8fc94..27cc6da274f 100644 --- a/src/native/runtime-base/timing-internal.hh +++ b/src/native/runtime-base/timing-internal.hh @@ -144,7 +144,7 @@ namespace xamarin::android::internal // likely we'll run out of memory way, way, way before that happens size_t old_size = events.capacity (); events.reserve (old_size << 1); - log_warn (LOG_TIMING, "Reallocated timing event buffer from %zu to %zu", old_size, events.size ()); + log_warn (LOG_TIMING, std::format ("Reallocated timing event buffer from {} to {}", old_size, events.size ())); } } @@ -246,7 +246,7 @@ namespace xamarin::android::internal force_inline bool is_valid_event_index (size_t index, const char *method_name) noexcept { if (index >= events.capacity ()) [[unlikely]] { - log_warn (LOG_TIMING, "Invalid event index passed to method '%s'", method_name); + log_warn (LOG_TIMING, std::format ("Invalid event index passed to method '{}'", method_name)); return false; } diff --git a/src/native/runtime-base/timing.hh b/src/native/runtime-base/timing.hh index 815e256252c..31f9892e918 100644 --- a/src/native/runtime-base/timing.hh +++ b/src/native/runtime-base/timing.hh @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -69,11 +70,9 @@ namespace xamarin::android // This class is intended to be used by the managed code. It can be used by the native code as // well, but the overhead it has (out of necessity) might not be desirable in native code. -#define TIMING_FORMAT "; elapsed: %lis:%lu::%lu" - class Timing { - static constexpr char MESSAGE_FORMAT[] = "%s" TIMING_FORMAT; + static inline constexpr std::string_view MESSAGE_FORMAT { "{}; elapsed: {}:{}::{}" }; public: static constexpr size_t DEFAULT_POOL_SIZE = 16uz; @@ -94,14 +93,14 @@ namespace xamarin::android { timing_diff diff (period); - log_info_nocheck (LOG_TIMING, MESSAGE_FORMAT, message == nullptr ? "" : message, diff.sec, diff.ms, diff.ns); + log_info_nocheck (LOG_TIMING, std::format (MESSAGE_FORMAT, message == nullptr ? ""sv : message, diff.sec, diff.ms, diff.ns)); } static void warn (timing_period const &period, const char *message) noexcept { timing_diff diff (period); - log_warn (LOG_TIMING, MESSAGE_FORMAT, message == nullptr ? "" : message, diff.sec, diff.ms, diff.ns); + log_warn (LOG_TIMING, std::format (MESSAGE_FORMAT, message == nullptr ? ""sv : message, diff.sec, diff.ms, diff.ns)); } managed_timing_sequence* get_available_sequence () noexcept @@ -147,20 +146,5 @@ namespace xamarin::android size_t sequence_pool_size; xamarin::android::mutex sequence_lock; }; - - // This is a hack to avoid having to allocate memory when rendering messages that use additional - // format placeholders on the caller side. Memory allocation would be necessary since we append - // the standard timing suffix to every message printed. Using a variadic macro allows us to - // compose a call with all the elements present and make the composition compile-time. - // - // It could be done with template packs but that would result in extra code generated whenever a - // call with a different set of parameters would be made, plus the code to implement that would - // be a bit verbose and unwieldy, so we will stick to this simple method. -#define TIMING_DO_LOG(_level, _category_, ...) ::log_ ## _level ## _nocheck ((_category_), __VA_ARGS__) - -#define TIMING_LOG_INFO(__period__, __format__, ...) { \ - timing_diff diff ((__period__)); \ - TIMING_DO_LOG (info, LOG_TIMING, __format__ TIMING_FORMAT, __VA_ARGS__, diff.sec, diff.ms, diff.ns); \ - } } #endif // __TIMING_HH diff --git a/src/native/runtime-base/util.cc b/src/native/runtime-base/util.cc index 7a58a2836c1..f7350c82ba4 100644 --- a/src/native/runtime-base/util.cc +++ b/src/native/runtime-base/util.cc @@ -149,7 +149,7 @@ Util::create_public_directory (const char *dir) mode_t m = umask (0); int ret = mkdir (dir, 0777); if (ret < 0) { - log_warn (LOG_DEFAULT, "Failed to create directory '%s'. %s", dir, std::strerror (errno)); + log_warn (LOG_DEFAULT, std::format ("Failed to create directory '{}'. {}", dir, std::strerror (errno))); } umask (m); } @@ -197,7 +197,7 @@ Util::set_world_accessable ([[maybe_unused]] const char *path) } while (r == -1 && errno == EINTR); if (r == -1) { - log_error (LOG_DEFAULT, "chmod(\"%s\", 0664) failed: %s", path, strerror (errno)); + log_error (LOG_DEFAULT, std::format ("chmod(\"{}\", 0664) failed: {}", path, strerror (errno))); } } @@ -210,7 +210,7 @@ Util::set_user_executable ([[maybe_unused]] const char *path) } while (r == -1 && errno == EINTR); if (r == -1) { - log_error (LOG_DEFAULT, "chmod(\"%s\") failed: %s", path, strerror (errno)); + log_error (LOG_DEFAULT, std::format ("chmod(\"{}\") failed: {}", path, strerror (errno))); } } @@ -240,12 +240,12 @@ bool Util::file_copy (const char *to, const char *from) { if (to == nullptr || *to == '\0') { - log_error (LOG_DEFAULT, "Util::file_copy: `to` parameter must not be null or empty"); + log_error (LOG_DEFAULT, "Util::file_copy: `to` parameter must not be null or empty"sv); return false; } if (from == nullptr || *from == '\0') { - log_error (LOG_DEFAULT, "Util::file_copy: `from` parameter must not be null or empty"); + log_error (LOG_DEFAULT, "Util::file_copy: `from` parameter must not be null or empty"sv); return false; } @@ -297,7 +297,7 @@ Util::monodroid_fopen (const char *filename, const char *mode) */ ret = fopen (filename, mode); if (ret == nullptr) { - log_error (LOG_DEFAULT, "fopen failed for file %s: %s", filename, strerror (errno)); + log_error (LOG_DEFAULT, std::format ("fopen failed for file {}: {}", filename, strerror (errno))); return nullptr; } diff --git a/src/native/runtime-base/util.hh b/src/native/runtime-base/util.hh index 97db495dbea..35eb8c3c590 100644 --- a/src/native/runtime-base/util.hh +++ b/src/native/runtime-base/util.hh @@ -79,7 +79,7 @@ namespace xamarin::android { struct stat sbuf; if (fstatat (dirfd, file_name, &sbuf, 0) == -1) { - log_warn (LOG_ASSEMBLY, "Failed to stat file '%s': %s", file_name, std::strerror (errno)); + log_warn (LOG_ASSEMBLY, std::format ("Failed to stat file '{}': {}", file_name, std::strerror (errno))); return std::nullopt; } @@ -90,7 +90,7 @@ namespace xamarin::android { int fd = openat (dirfd, file_name, O_RDONLY); if (fd < 0) { - log_error (LOG_ASSEMBLY, "Failed to open file '%s' for reading: %s", file_name, std::strerror (errno)); + log_error (LOG_ASSEMBLY, std::format ("Failed to open file '{}' for reading: {}", file_name, std::strerror (errno))); return std::nullopt; } diff --git a/src/native/shared/cpp-util.hh b/src/native/shared/cpp-util.hh index f893d6614e3..8c2397218f5 100644 --- a/src/native/shared/cpp-util.hh +++ b/src/native/shared/cpp-util.hh @@ -83,7 +83,7 @@ abort_if_negative_integer_argument (int arg, const char *arg_name, std::source_l // of the calls present. force_inline inline void pd_log_location (std::source_location sloc = std::source_location::current ()) noexcept { - log_info_nocheck (LOG_DEFAULT, "loc: %s:%u ('%s')", sloc.file_name (), sloc.line (), sloc.function_name ()); + log_info_nocheck (LOG_DEFAULT, std::format ("loc: {}:{} ('{}')", sloc.file_name (), sloc.line (), sloc.function_name ())); } namespace xamarin::android diff --git a/src/native/shared/helpers.cc b/src/native/shared/helpers.cc index bf8a8bd5339..645f30e0d84 100644 --- a/src/native/shared/helpers.cc +++ b/src/native/shared/helpers.cc @@ -3,7 +3,7 @@ #include #include "helpers.hh" -#include "java-interop-logger.h" +#include "log_types.hh" using namespace xamarin::android; @@ -11,7 +11,7 @@ using namespace xamarin::android; Helpers::abort_application (LogCategories category, const char *message, bool log_location, std::source_location sloc) noexcept { // Log it, but also... - log_fatal (category, message); + log_fatal (category, std::string_view { message }); // ...let android include it in the tombstone, debuggerd output, stack trace etc android_set_abort_message (message); @@ -35,11 +35,12 @@ Helpers::abort_application (LogCategories category, const char *message, bool lo log_fatal ( category, - "Abort at %s:%u:%u ('%s')", - file_name, - sloc.line (), - sloc.column (), - sloc.function_name () + std::format ("Abort at {}:{}:{} ('%s')", + file_name, + sloc.line (), + sloc.column (), + sloc.function_name () + ) ); } std::abort (); diff --git a/src/native/shared/log_functions.cc b/src/native/shared/log_functions.cc index 114bc0186e7..e82f2bd5856 100644 --- a/src/native/shared/log_functions.cc +++ b/src/native/shared/log_functions.cc @@ -3,7 +3,7 @@ #include -#include "java-interop-logger.h" +//#include "java-interop-logger.h" #include "log_types.hh" // Must match the same ordering as LogCategories diff --git a/src/native/shared/log_types.hh b/src/native/shared/log_types.hh index ff558a8185a..31a1b22dac0 100644 --- a/src/native/shared/log_types.hh +++ b/src/native/shared/log_types.hh @@ -1,5 +1,4 @@ -#if !defined(LOG_LEVEL_HH) -#define LOG_LEVEL_HH +#pragma once #include #include @@ -127,4 +126,3 @@ static inline constexpr void log_fatal (LogCategories category, std::string_view } extern unsigned int log_categories; -#endif // ndef LOG_LEVEL_HH diff --git a/src/native/xamarin-debug-app-helper/debug-app-helper.cc b/src/native/xamarin-debug-app-helper/debug-app-helper.cc index e083f905ab4..ae8c2cd4bc6 100644 --- a/src/native/xamarin-debug-app-helper/debug-app-helper.cc +++ b/src/native/xamarin-debug-app-helper/debug-app-helper.cc @@ -14,33 +14,17 @@ #include "debug-app-helper.hh" #include "shared-constants.hh" #include "jni-wrappers.hh" +#include "log_types.hh" using namespace xamarin::android; using namespace xamarin::android::internal; -#undef DO_LOG -#undef log_info - -void log_info (LogCategories category, const char *format, ...); -void log_warn (LogCategories category, const char *format, ...); -void log_error (LogCategories category, const char *format, ...); -void log_fatal (LogCategories category, const char *format, ...); - static void copy_file_to_internal_location (char *to_dir, char *from_dir, char *file); static void copy_native_libraries_to_internal_location (); static const char* get_libmonosgen_path (); bool maybe_load_library (const char *path); -#define DO_LOG(_level_,_tag_,_format_,_args_) \ - va_start ((_args_), (_format_)); \ - __android_log_vprint ((_level_), (_tag_), (_format_), (_args_)); \ - va_end ((_args_)); - -static constexpr char TAG[] = "debug-app-helper"; - -unsigned int log_categories = LOG_DEFAULT | LOG_ASSEMBLY; - JNIEXPORT jint JNICALL JNI_OnLoad ([[maybe_unused]] JavaVM *vm, [[maybe_unused]] void *reserved) { @@ -64,7 +48,7 @@ Java_mono_android_DebugRuntime_init (JNIEnv *env, [[maybe_unused]] jclass klass, if (runtimeNativeLibDir != nullptr) { jstr = runtimeNativeLibDir; AndroidSystem::set_runtime_libdir (Util::strdup_new (jstr.get_cstr ())); - log_warn (LOG_DEFAULT, "Using runtime path: %s", AndroidSystem::get_runtime_libdir ()); + log_warn (LOG_DEFAULT, std::format ("Using runtime path: {}", AndroidSystem::get_runtime_libdir ())); } const char *monosgen_path = get_libmonosgen_path (); @@ -89,8 +73,12 @@ copy_file_to_internal_location (char *to_dir, char *from_dir, char *file) if (!from_file || !Util::file_exists (from_file)) break; - log_warn (LOG_DEFAULT, "Copying file `%s` from external location `%s` to internal location `%s`", - file, from_dir, to_dir); + log_warn (LOG_DEFAULT, + std::format ( + "Copying file `{}` from external location `{}` to internal location `{}`", + file, from_dir, to_dir + ) + ); to_file = Util::path_combine (to_dir, file); if (!to_file) @@ -98,12 +86,12 @@ copy_file_to_internal_location (char *to_dir, char *from_dir, char *file) int r = unlink (to_file); if (r < 0 && errno != ENOENT) { - log_warn (LOG_DEFAULT, "Unable to delete file `%s`: %s", to_file, strerror (errno)); + log_warn (LOG_DEFAULT, std::format ("Unable to delete file `{}`: {}", to_file, strerror (errno))); break; } if (!Util::file_copy (to_file, from_file)) { - log_warn (LOG_DEFAULT, "Copy failed from `%s` to `%s`: %s", from_file, to_file, strerror (errno)); + log_warn (LOG_DEFAULT, std::format ("Copy failed from `{}` to `{}`: {}", from_file, to_file, strerror (errno))); break; } @@ -122,22 +110,22 @@ copy_native_libraries_to_internal_location () dirent *e; char *dir_path = Util::path_combine (od, "lib"); - log_warn (LOG_DEFAULT, "checking directory: `%s`", dir_path); + log_warn (LOG_DEFAULT, std::format ("checking directory: `{}`", dir_path)); if (dir_path == nullptr || !Util::directory_exists (dir_path)) { - log_warn (LOG_DEFAULT, "directory does not exist: `%s`", dir_path); + log_warn (LOG_DEFAULT, std::format ("directory does not exist: `{}`", dir_path)); delete[] dir_path; continue; } if ((dir = ::opendir (dir_path)) == nullptr) { - log_warn (LOG_DEFAULT, "could not open directory: `%s`", dir_path); + log_warn (LOG_DEFAULT, std::format ("could not open directory: `{}`", dir_path)); delete[] dir_path; continue; } while ((e = readdir (dir)) != nullptr) { - log_warn (LOG_DEFAULT, "checking file: `%s`", e->d_name); + log_warn (LOG_DEFAULT, std::format ("checking file: `{}`", e->d_name)); if (Util::monodroid_dirent_hasextension (e, ".so")) { copy_file_to_internal_location (AndroidSystem::get_primary_override_dir (), dir_path, e->d_name); } @@ -154,9 +142,9 @@ runtime_exists (const char *dir, char*& libmonoso) return false; libmonoso = Util::path_combine (dir, SharedConstants::MONO_SGEN_SO); - log_warn (LOG_DEFAULT, "Checking whether Mono runtime exists at: %s", libmonoso); + log_warn (LOG_DEFAULT, std::format ("Checking whether Mono runtime exists at: {}", libmonoso)); if (Util::file_exists (libmonoso)) { - log_info (LOG_DEFAULT, "Mono runtime found at: %s", libmonoso); + log_info (LOG_DEFAULT, std::format ("Mono runtime found at: {}", libmonoso)); return true; } delete[] libmonoso; @@ -208,25 +196,25 @@ get_libmonosgen_path () if (!Util::file_exists (link)) { int result = symlink (libmonoso, link); if (result != 0 && errno == EEXIST) { - log_warn (LOG_DEFAULT, "symlink exists, recreating: %s -> %s", link, libmonoso); + log_warn (LOG_DEFAULT, std::format ("symlink exists, recreating: {} -> {}", link, libmonoso)); unlink (link); result = symlink (libmonoso, link); } if (result != 0) - log_warn (LOG_DEFAULT, "symlink failed with errno=%i %s", errno, strerror (errno)); + log_warn (LOG_DEFAULT, std::format ("symlink failed with errno={} {}", errno, strerror (errno))); } delete[] libmonoso; libmonoso = link; } - log_warn (LOG_DEFAULT, "Trying to load sgen from: %s", libmonoso != nullptr ? libmonoso : ""); + log_warn (LOG_DEFAULT, std::format ("Trying to load sgen from: {}", libmonoso != nullptr ? libmonoso : ""sv)); if (libmonoso != nullptr && Util::file_exists (libmonoso)) return libmonoso; delete[] libmonoso; if (runtime_exists (AndroidSystem::SYSTEM_LIB_PATH.data (), libmonoso)) return libmonoso; - log_fatal (LOG_DEFAULT, "Cannot find '%s'. Looked in the following locations:", SharedConstants::MONO_SGEN_SO); + log_fatal (LOG_DEFAULT, std::format ("Cannot find '{}'. Looked in the following locations:", SharedConstants::MONO_SGEN_SO)); for (const char *od : AndroidSystem::override_dirs) { if (od == nullptr) @@ -245,54 +233,3 @@ get_libmonosgen_path () return libmonoso; } - -void -log_debug_nocheck ([[maybe_unused]] LogCategories category, const char *format, ...) -{ - va_list args; - - if ((log_categories & category) == 0) - return; - - DO_LOG (ANDROID_LOG_DEBUG, TAG, format, args); -} - -void -log_info ([[maybe_unused]] LogCategories category, const char *format, ...) -{ - va_list args; - - DO_LOG (ANDROID_LOG_INFO, TAG, format, args); -} - -void -log_info_nocheck ([[maybe_unused]] LogCategories category, const char *format, ...) -{ - va_list args; - - if ((log_categories & category) == 0) - return; - - DO_LOG (ANDROID_LOG_INFO, TAG, format, args); -} - -void log_error ([[maybe_unused]] LogCategories category, const char* format, ...) -{ - va_list args; - - DO_LOG (ANDROID_LOG_ERROR, TAG, format, args); -} - -void log_fatal ([[maybe_unused]] LogCategories category, const char* format, ...) -{ - va_list args; - - DO_LOG (ANDROID_LOG_FATAL, TAG, format, args); -} - -void log_warn ([[maybe_unused]] LogCategories category, const char* format, ...) -{ - va_list args; - - DO_LOG (ANDROID_LOG_WARN, TAG, format, args); -} From 96679f0b902e4d450ece8010243c98f42628c460 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Thu, 28 Nov 2024 17:17:26 +0100 Subject: [PATCH 43/54] Friendlier, no need to use `std::format` directly in log_* anymore --- src/native/monodroid/debug.cc | 61 +++---- .../monodroid/embedded-assemblies-zip.cc | 69 ++++--- src/native/monodroid/embedded-assemblies.cc | 171 +++++++++--------- src/native/monodroid/embedded-assemblies.hh | 6 +- .../monodroid/monodroid-glue-internal.hh | 2 +- src/native/monodroid/monodroid-glue.cc | 73 ++++---- src/native/monodroid/monodroid-networkinfo.cc | 6 +- src/native/monodroid/monodroid-tracing.cc | 2 +- src/native/monodroid/osbridge.cc | 160 ++++++++-------- .../monodroid/xamarin-android-app-context.cc | 38 ++-- src/native/monodroid/xamarin_getifaddrs.cc | 56 +++--- .../pinvoke-override-api-impl.hh | 12 +- src/native/pinvoke-override/precompiled.cc | 8 +- src/native/runtime-base/android-system.cc | 64 +++---- src/native/runtime-base/logger.cc | 1 + src/native/runtime-base/monodroid-dl.hh | 12 +- src/native/runtime-base/strings.hh | 8 +- src/native/runtime-base/timing-internal.cc | 6 +- src/native/runtime-base/timing-internal.hh | 4 +- src/native/runtime-base/timing.hh | 4 +- src/native/runtime-base/util.cc | 8 +- src/native/runtime-base/util.hh | 4 +- src/native/shared/cpp-util.hh | 2 +- src/native/shared/helpers.cc | 13 +- src/native/shared/log_functions.cc | 4 +- src/native/shared/log_level.hh | 26 +++ src/native/shared/log_types.hh | 94 ++++------ .../debug-app-helper.cc | 32 ++-- 28 files changed, 459 insertions(+), 487 deletions(-) create mode 100644 src/native/shared/log_level.hh diff --git a/src/native/monodroid/debug.cc b/src/native/monodroid/debug.cc index 7aa2ec6abb2..cbcdeec2e87 100644 --- a/src/native/monodroid/debug.cc +++ b/src/native/monodroid/debug.cc @@ -95,10 +95,9 @@ Debug::monodroid_profiler_load (const char *libmono_path, const char *desc, cons if (!found) log_warn (LOG_DEFAULT, - std::format ("The '{}' profiler wasn't found in the main executable nor could it be loaded from '{}'.", - mname.get (), - libname.get () - ) + "The '{}' profiler wasn't found in the main executable nor could it be loaded from '{}'.", + mname.get (), + libname.get () ); } @@ -110,7 +109,7 @@ bool Debug::load_profiler (void *handle, const char *desc, const char *symbol) { ProfilerInitializer func = reinterpret_cast (java_interop_lib_symbol (handle, symbol, nullptr)); - log_warn (LOG_DEFAULT, std::format ("Looking for profiler init symbol '{}'? {:p}", symbol, reinterpret_cast(func))); + log_warn (LOG_DEFAULT, "Looking for profiler init symbol '{}'? {:p}", symbol, reinterpret_cast(func)); if (func != nullptr) { func (desc); @@ -140,7 +139,7 @@ Debug::parse_options (char *options, ConnOptions *opts) { char **args, **ptr; - log_info (LOG_DEFAULT, std::format ("Connection options: '{}'", options)); + log_info (LOG_DEFAULT, "Connection options: '{}'", options); args = Util::monodroid_strsplit (options, ",", 0); @@ -150,12 +149,12 @@ Debug::parse_options (char *options, ConnOptions *opts) if (strstr (arg, "port=") == arg) { int port = atoi (arg + strlen ("port=")); if (port < 0 || port > std::numeric_limits::max ()) { - log_error (LOG_DEFAULT, std::format ("Invalid debug port value {}", port)); + log_error (LOG_DEFAULT, "Invalid debug port value {}", port); continue; } conn_port = static_cast(port); - log_info (LOG_DEFAULT, std::format ("XS port = {}", conn_port)); + log_info (LOG_DEFAULT, "XS port = {}", conn_port); } else if (strstr (arg, "timeout=") == arg) { char *endp; @@ -164,7 +163,7 @@ Debug::parse_options (char *options, ConnOptions *opts) if ((endp == arg) || (*endp != '\0')) log_error (LOG_DEFAULT, "Invalid --timeout argument."sv); } else { - log_info (LOG_DEFAULT, std::format ("Unknown connection option: '{}'", arg)); + log_info (LOG_DEFAULT, "Unknown connection option: '{}'", arg); } } } @@ -188,7 +187,7 @@ Debug::start_connection (char *options) cur_time = time (nullptr); if (opts.timeout_time && cur_time > opts.timeout_time) { - log_warn (LOG_DEBUGGER, std::format ("Not connecting to IDE as the timeout value has been reached; current-time: {} timeout: {}", cur_time, opts.timeout_time)); + log_warn (LOG_DEBUGGER, "Not connecting to IDE as the timeout value has been reached; current-time: {} timeout: {}", cur_time, opts.timeout_time); return DebuggerConnectionStatus::Unconnected; } @@ -199,7 +198,7 @@ Debug::start_connection (char *options) res = pthread_create (&conn_thread_id, nullptr, xamarin::android::conn_thread, this); if (res) { - log_error (LOG_DEFAULT, std::format ("Failed to create connection thread: {}", strerror (errno))); + log_error (LOG_DEFAULT, "Failed to create connection thread: {}", strerror (errno)); return DebuggerConnectionStatus::Error; } @@ -263,20 +262,20 @@ Debug::process_connection (int fd) return false; } if (rv <= 0) { - log_info (LOG_DEFAULT, std::format ("Error while receiving command from XS ({})", strerror (errno))); + log_info (LOG_DEFAULT, "Error while receiving command from XS ({})", strerror (errno)); return false; } rv = Util::recv_uninterrupted (fd, command, cmd_len); if (rv <= 0) { - log_info (LOG_DEFAULT, std::format ("Error while receiving command from XS ({})", strerror (errno))); + log_info (LOG_DEFAULT, "Error while receiving command from XS ({})", strerror (errno)); return false; } // null-terminate command [cmd_len] = 0; - log_info (LOG_DEFAULT, std::format ("Received cmd: '{}'.", command)); + log_info (LOG_DEFAULT, "Received cmd: '{}'.", command); if (process_cmd (fd, command)) return true; @@ -288,14 +287,14 @@ Debug::handle_server_connection (void) { int listen_socket = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP); if (listen_socket == -1) { - log_info (LOG_DEFAULT, std::format ("Could not create socket for XS to connect to: {}", strerror (errno))); + log_info (LOG_DEFAULT, "Could not create socket for XS to connect to: {}", strerror (errno)); return 1; } int flags = 1; int rv = setsockopt (listen_socket, SOL_SOCKET, SO_REUSEADDR, &flags, sizeof (flags)); if (rv == -1 && Util::should_log (LOG_DEFAULT)) { - log_info_nocheck (LOG_DEFAULT, std::format ("Could not set SO_REUSEADDR on the listening socket ({})", strerror (errno))); + log_info_nocheck_fmt (LOG_DEFAULT, "Could not set SO_REUSEADDR on the listening socket ({})", strerror (errno)); // not a fatal failure } @@ -309,7 +308,7 @@ Debug::handle_server_connection (void) listen_addr.sin_addr.s_addr = INADDR_ANY; rv = bind (listen_socket, (struct sockaddr *) &listen_addr, sizeof (listen_addr)); if (rv == -1) { - log_info (LOG_DEFAULT, std::format ("Could not bind to address: {}", strerror (errno))); + log_info (LOG_DEFAULT, "Could not bind to address: {}", strerror (errno)); rv = 2; goto cleanup; } @@ -321,7 +320,7 @@ Debug::handle_server_connection (void) rv = listen (listen_socket, 1); if (rv == -1) { - log_info (LOG_DEFAULT, std::format ("Could not listen for XS: {}", strerror (errno))); + log_info (LOG_DEFAULT, "Could not listen for XS: {}", strerror (errno)); rv = 2; goto cleanup; } @@ -371,7 +370,7 @@ Debug::handle_server_connection (void) } while (rv == -1 && errno == EINTR); if (rv == -1) { - log_info (LOG_DEFAULT, std::format ("Failed while waiting for XS to connect: {}", strerror (errno))); + log_info (LOG_DEFAULT, "Failed while waiting for XS to connect: {}", strerror (errno)); rv = 2; goto cleanup; } @@ -379,18 +378,18 @@ Debug::handle_server_connection (void) socklen_t len = sizeof (struct sockaddr_in); int fd = accept (listen_socket, (struct sockaddr *) &listen_addr, &len); if (fd == -1) { - log_info (LOG_DEFAULT, std::format ("Failed to accept connection from XS: {}", strerror (errno))); + log_info (LOG_DEFAULT, "Failed to accept connection from XS: {}", strerror (errno)); rv = 3; goto cleanup; } flags = 1; if (setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, (char *) &flags, sizeof (flags)) < 0) { - log_info (LOG_DEFAULT, std::format ("Could not set TCP_NODELAY on socket ({})", strerror (errno))); + log_info (LOG_DEFAULT, "Could not set TCP_NODELAY on socket ({})", strerror (errno)); // not a fatal failure } - log_info (LOG_DEFAULT, std::format ("Successfully received connection from XS on port {}, fd: {}", listen_port, fd)); + log_info (LOG_DEFAULT, "Successfully received connection from XS on port {}, fd: {}", listen_port, fd); need_new_conn = process_connection (fd); } @@ -442,7 +441,7 @@ Debug::process_cmd (int fd, char *cmd) constexpr std::string_view PONG_REPLY { "pong" }; if (strcmp (cmd, PING_CMD.data ()) == 0) { if (!Util::send_uninterrupted (fd, const_cast (reinterpret_cast (PONG_REPLY.data ())), 5)) - log_error (LOG_DEFAULT, std::format ("Got keepalive request from XS, but could not send response back ({})", strerror (errno))); + log_error (LOG_DEFAULT, "Got keepalive request from XS, but could not send response back ({})", strerror (errno)); return false; } @@ -488,7 +487,7 @@ Debug::process_cmd (int fd, char *cmd) profiler_fd = fd; profiler_description = Util::monodroid_strdup_printf ("%s,output=#%i", prof, profiler_fd); } else { - log_error (LOG_DEFAULT, std::format ("Unknown profiler: '{}'", prof)); + log_error (LOG_DEFAULT, "Unknown profiler: '{}'", prof); } /* Notify the main thread (start_profiling ()) */ profiler_configured = true; @@ -497,7 +496,7 @@ Debug::process_cmd (int fd, char *cmd) pthread_mutex_unlock (&process_cmd_mutex); return use_fd; } else { - log_error (LOG_DEFAULT, std::format ("Unsupported command: '{}'", cmd)); + log_error (LOG_DEFAULT, "Unsupported command: '{}'", cmd); } return false; @@ -527,7 +526,7 @@ Debug::start_debugging (void) // this text is used in unit tests to check the debugger started // do not change it without updating the test. - log_warn (LOG_DEBUGGER, std::format ("Trying to initialize the debugger with options: {}", debug_arg)); + log_warn (LOG_DEBUGGER, "Trying to initialize the debugger with options: {}", debug_arg); if (enable_soft_breakpoints ()) { constexpr std::string_view soft_breakpoints { "--soft-breakpoints" }; @@ -554,7 +553,7 @@ Debug::start_profiling () if (!profiler_description) return; - log_info (LOG_DEFAULT, std::format ("Loading profiler: '{}'", profiler_description)); + log_info (LOG_DEFAULT, "Loading profiler: '{}'", profiler_description); monodroid_profiler_load (AndroidSystem::get_runtime_libdir (), profiler_description, nullptr); } @@ -574,7 +573,7 @@ Debug::enable_soft_breakpoints (void) uname (&name); for (const char** ptr = soft_breakpoint_kernel_list; *ptr; ptr++) { if (strcmp (name.release, *ptr) == 0) { - log_info (LOG_DEBUGGER, std::format ("soft breakpoints enabled due to kernel version match ({})", name.release)); + log_info (LOG_DEBUGGER, "soft breakpoints enabled due to kernel version match ({})", name.release); return 1; } } @@ -582,17 +581,17 @@ Debug::enable_soft_breakpoints (void) char *value; /* Soft breakpoints are enabled by default */ if (AndroidSystem::monodroid_get_system_property (SharedConstants::DEBUG_MONO_SOFT_BREAKPOINTS, &value) <= 0) { - log_info (LOG_DEBUGGER, std::format ("soft breakpoints enabled by default ({} property not defined)", SharedConstants::DEBUG_MONO_SOFT_BREAKPOINTS.data ())); + log_info (LOG_DEBUGGER, "soft breakpoints enabled by default ({} property not defined)", SharedConstants::DEBUG_MONO_SOFT_BREAKPOINTS.data ()); return 1; } bool ret; if (strcmp ("0", value) == 0) { ret = false; - log_info (LOG_DEBUGGER, std::format ("soft breakpoints disabled ({} property set to {})", SharedConstants::DEBUG_MONO_SOFT_BREAKPOINTS.data (), value)); + log_info (LOG_DEBUGGER, "soft breakpoints disabled ({} property set to {})", SharedConstants::DEBUG_MONO_SOFT_BREAKPOINTS.data (), value); } else { ret = true; - log_info (LOG_DEBUGGER, std::format ("soft breakpoints enabled ({} property set to {})", SharedConstants::DEBUG_MONO_SOFT_BREAKPOINTS.data (), value)); + log_info (LOG_DEBUGGER, "soft breakpoints enabled ({} property set to {})", SharedConstants::DEBUG_MONO_SOFT_BREAKPOINTS.data (), value); } delete[] value; return ret; diff --git a/src/native/monodroid/embedded-assemblies-zip.cc b/src/native/monodroid/embedded-assemblies-zip.cc index 35ef82d68f7..2497cab1c83 100644 --- a/src/native/monodroid/embedded-assemblies-zip.cc +++ b/src/native/monodroid/embedded-assemblies-zip.cc @@ -22,7 +22,7 @@ EmbeddedAssemblies::zip_load_entry_common (size_t entry_index, std::vector } auto [payload_start, payload_size] = get_wrapper_dso_payload_pointer_and_size (assembly_store_map, entry_name.get ()); - log_debug (LOG_ASSEMBLY, std::format ("Adjusted assembly store pointer: {:p}; size: {}", payload_start, payload_size)); + log_debug (LOG_ASSEMBLY, "Adjusted assembly store pointer: {:p}; size: {}", payload_start, payload_size); auto header = static_cast(payload_start); if (header->magic != ASSEMBLY_STORE_MAGIC) { @@ -264,7 +262,7 @@ EmbeddedAssemblies::zip_load_assembly_store_entries (std::vector const& dynamic_local_string entry_name; bool assembly_store_found = false; - log_debug (LOG_ASSEMBLY, std::format ("Looking for assembly stores in APK ('{}')", assembly_store_file_path.data ())); + log_debug (LOG_ASSEMBLY, "Looking for assembly stores in APK ('{}')", assembly_store_file_path.data ()); for (size_t i = 0uz; i < num_entries; i++) { if (all_required_zip_entries_found ()) { need_to_scan_more_apks = false; @@ -300,14 +298,12 @@ EmbeddedAssemblies::zip_load_assembly_store_entries (std::vector const& log_debug ( LOG_ASSEMBLY, - std::format ( - "Found a shared library entry {} (index: {}; name: {}; hash: {:x}; apk offset: {})", - entry_name.get (), - number_of_zip_dso_entries, - name, - apk_entry->name_hash, - apk_entry->offset - ) + "Found a shared library entry {} (index: {}; name: {}; hash: {:x}; apk offset: {})", + entry_name.get (), + number_of_zip_dso_entries, + name, + apk_entry->name_hash, + apk_entry->offset ); number_of_zip_dso_entries++; } @@ -331,9 +327,9 @@ EmbeddedAssemblies::zip_load_entries (int fd, const char *apk_name, [[maybe_unus ); } #ifdef DEBUG - log_info (LOG_ASSEMBLY, std::format ("Central directory offset: {}", cd_offset)); - log_info (LOG_ASSEMBLY, std::format ("Central directory size: {}", cd_size)); - log_info (LOG_ASSEMBLY, std::format ("Central directory entries: {}", cd_entries)); + log_info (LOG_ASSEMBLY, "Central directory offset: {}", cd_offset); + log_info (LOG_ASSEMBLY, "Central directory size: {}", cd_size); + log_info (LOG_ASSEMBLY, "Central directory entries: {}", cd_entries); #endif off_t retval = ::lseek (fd, static_cast(cd_offset), SEEK_SET); if (retval < 0) { @@ -411,9 +407,8 @@ EmbeddedAssemblies::set_entry_data (XamarinAndroidBundledAssembly &entry, ZipEnt log_debug ( LOG_ASSEMBLY, - std::format ("Set bundled assembly entry data. file name: '{}'; entry name: '{}'; data size: {}", - entry.file_name, entry.name, entry.data_size - ) + "Set bundled assembly entry data. file name: '{}'; entry name: '{}'; data size: {}", + entry.file_name, entry.name, entry.data_size ); } @@ -435,14 +430,14 @@ EmbeddedAssemblies::zip_read_cd_info (int fd, uint32_t& cd_offset, uint32_t& cd_ // The simplest case - no file comment off_t ret = ::lseek (fd, -ZIP_EOCD_LEN, SEEK_END); if (ret < 0) { - log_error (LOG_ASSEMBLY, std::format ("Unable to seek into the APK to find ECOD: {} (ret: {}; errno: {})", std::strerror (errno), ret, errno)); + log_error (LOG_ASSEMBLY, "Unable to seek into the APK to find ECOD: {} (ret: {}; errno: {})", std::strerror (errno), ret, errno); return false; } std::array eocd; ssize_t nread = ::read (fd, eocd.data (), eocd.size ()); if (nread < 0 || nread != eocd.size ()) { - log_error (LOG_ASSEMBLY, std::format ("Failed to read EOCD from the APK: {} (nread: {}; errno: {})", std::strerror (errno), nread, errno)); + log_error (LOG_ASSEMBLY, "Failed to read EOCD from the APK: {} (nread: {}; errno: {})", std::strerror (errno), nread, errno); return false; } @@ -462,7 +457,7 @@ EmbeddedAssemblies::zip_read_cd_info (int fd, uint32_t& cd_offset, uint32_t& cd_ constexpr size_t alloc_size = 65535uz + ZIP_EOCD_LEN; // 64k is the biggest comment size allowed ret = ::lseek (fd, static_cast(-alloc_size), SEEK_END); if (ret < 0) { - log_error (LOG_ASSEMBLY, std::format ("Unable to seek into the file to find ECOD before APK comment: {} (ret: {}; errno: {})", std::strerror (errno), ret, errno)); + log_error (LOG_ASSEMBLY, "Unable to seek into the file to find ECOD before APK comment: {} (ret: {}; errno: {})", std::strerror (errno), ret, errno); return false; } @@ -471,7 +466,7 @@ EmbeddedAssemblies::zip_read_cd_info (int fd, uint32_t& cd_offset, uint32_t& cd_ nread = ::read (fd, buf.data (), buf.size ()); if (nread < 0 || static_cast(nread) != alloc_size) { - log_error (LOG_ASSEMBLY, std::format ("Failed to read EOCD and comment from the APK: {} (nread: {}; errno: {})", std::strerror (errno), nread, errno)); + log_error (LOG_ASSEMBLY, "Failed to read EOCD and comment from the APK: {} (nread: {}; errno: {})", std::strerror (errno), nread, errno); return false; } @@ -505,10 +500,8 @@ EmbeddedAssemblies::zip_adjust_data_offset (int fd, ZipEntryLoadState &state) no if (result < 0) { log_error ( LOG_ASSEMBLY, - std::format ( - "Failed to seek to archive entry local header at offset {}. {} (result: {}; errno: {})", - state.local_header_offset, std::strerror (errno), result, errno - ) + "Failed to seek to archive entry local header at offset {}. {} (result: {}; errno: {})", + state.local_header_offset, std::strerror (errno), result, errno ); return false; } @@ -518,32 +511,32 @@ EmbeddedAssemblies::zip_adjust_data_offset (int fd, ZipEntryLoadState &state) no ssize_t nread = ::read (fd, local_header.data (), local_header.size ()); if (nread < 0 || nread != ZIP_LOCAL_LEN) { - log_error (LOG_ASSEMBLY, std::format ("Failed to read local header at offset {}: {} (nread: {}; errno: {})", state.local_header_offset, std::strerror (errno), nread, errno)); + log_error (LOG_ASSEMBLY, "Failed to read local header at offset {}: {} (nread: {}; errno: {})", state.local_header_offset, std::strerror (errno), nread, errno); return false; } size_t index = 0; if (!zip_read_field (local_header, index, signature)) { - log_error (LOG_ASSEMBLY, std::format ("Failed to read Local Header entry signature at offset {}", state.local_header_offset)); + log_error (LOG_ASSEMBLY, "Failed to read Local Header entry signature at offset {}", state.local_header_offset); return false; } if (memcmp (signature.data (), ZIP_LOCAL_MAGIC.data (), signature.size ()) != 0) { - log_error (LOG_ASSEMBLY, std::format ("Invalid Local Header entry signature at offset {}", state.local_header_offset)); + log_error (LOG_ASSEMBLY, "Invalid Local Header entry signature at offset {}", state.local_header_offset); return false; } uint16_t file_name_length; index = LH_FILE_NAME_LENGTH_OFFSET; if (!zip_read_field (local_header, index, file_name_length)) { - log_error (LOG_ASSEMBLY, std::format ("Failed to read Local Header 'file name length' field at offset {}", (state.local_header_offset + index))); + log_error (LOG_ASSEMBLY, "Failed to read Local Header 'file name length' field at offset {}", (state.local_header_offset + index)); return false; } uint16_t extra_field_length; index = LH_EXTRA_LENGTH_OFFSET; if (!zip_read_field (local_header, index, extra_field_length)) { - log_error (LOG_ASSEMBLY, std::format ("Failed to read Local Header 'extra field length' field at offset {}", (state.local_header_offset + index))); + log_error (LOG_ASSEMBLY, "Failed to read Local Header 'extra field length' field at offset {}", (state.local_header_offset + index)); return false; } @@ -585,7 +578,7 @@ force_inline bool EmbeddedAssemblies::zip_ensure_valid_params (T const& buf, size_t index, size_t to_read) noexcept { if (index + to_read > buf.size ()) { - log_error (LOG_ASSEMBLY, std::format ("Buffer too short to read {} bytes of data", to_read)); + log_error (LOG_ASSEMBLY, "Buffer too short to read {} bytes of data", to_read); return false; } diff --git a/src/native/monodroid/embedded-assemblies.cc b/src/native/monodroid/embedded-assemblies.cc index d03e99cc44e..c868da14469 100644 --- a/src/native/monodroid/embedded-assemblies.cc +++ b/src/native/monodroid/embedded-assemblies.cc @@ -130,7 +130,7 @@ EmbeddedAssemblies::get_assembly_data (uint8_t *data, uint32_t data_size, [[mayb ) ); } else { - log_debug (LOG_ASSEMBLY, std::format ("Compressed assembly '{}' is smaller than when the application was built. Adjusting accordingly.", name)); + log_debug (LOG_ASSEMBLY, "Compressed assembly '{}' is smaller than when the application was built. Adjusting accordingly.", name); } cad.uncompressed_file_size = header->uncompressed_length; } @@ -228,7 +228,7 @@ EmbeddedAssemblies::map_runtime_file (XamarinAndroidBundledAssembly& file) noexc ); if (already_mapped) { - log_debug (LOG_ASSEMBLY, std::format ("Assembly {} already mmapped by another thread, unmapping our copy", file.name)); + log_debug (LOG_ASSEMBLY, "Assembly {} already mmapped by another thread, unmapping our copy", file.name); munmap (map_info.area, file.data_size); map_info.area = nullptr; } @@ -243,18 +243,16 @@ EmbeddedAssemblies::map_runtime_file (XamarinAndroidBundledAssembly& file) noexc header[j] = isprint (p [j]) ? p [j] : '.'; header [header.size () - 1] = '\0'; - log_info_nocheck ( + log_info_nocheck_fmt ( LOG_ASSEMBLY, - std::format ( - "file-offset: {:<8x} start: {:<8p} end: {:<8p} len: {:<12} zip-entry: {} name: {} [{}]", - file.data_offset, - static_cast(file.data), - pointer_add (file.data, file.data_size), - file.data_size, - file.name, - file.name, - header.data () - ) + "file-offset: {:<8x} start: {:<8p} end: {:<8p} len: {:<12} zip-entry: {} name: {} [{}]", + file.data_offset, + static_cast(file.data), + pointer_add (file.data, file.data_size), + file.data_size, + file.name, + file.name, + header.data () ); } } @@ -289,7 +287,7 @@ EmbeddedAssemblies::load_bundled_assembly ( if (strcmp (assembly.name, abi_name.get ()) != 0) { return nullptr; } else { - log_debug (LOG_ASSEMBLY, std::format ("open_from_bundles: found architecture-specific: '{}'", abi_name.get ())); + log_debug (LOG_ASSEMBLY, "open_from_bundles: found architecture-specific: '{}'", abi_name.get ()); } } @@ -350,7 +348,7 @@ EmbeddedAssemblies::individual_assemblies_open_from_bundles (dynamic_local_strin name.append (SharedConstants::DLL_EXTENSION); } - log_debug (LOG_ASSEMBLY, std::format ("individual_assemblies_open_from_bundles: looking for bundled name: '{}'", name.get ())); + log_debug (LOG_ASSEMBLY, "individual_assemblies_open_from_bundles: looking for bundled name: '{}'", name.get ()); dynamic_local_string abi_name; abi_name @@ -397,7 +395,7 @@ force_inline MonoAssembly* EmbeddedAssemblies::assembly_store_open_from_bundles (dynamic_local_string& name, TLoaderData loader_data, bool ref_only) noexcept { hash_t name_hash = xxhash::hash (name.get (), name.length ()); - log_debug (LOG_ASSEMBLY, std::format ("assembly_store_open_from_bundles: looking for bundled name: '{}' (hash {:x})", name.get (), name_hash)); + log_debug (LOG_ASSEMBLY, "assembly_store_open_from_bundles: looking for bundled name: '{}' (hash {:x})", name.get (), name_hash); const AssemblyStoreIndexEntry *hash_entry = find_assembly_store_entry (name_hash, assembly_store_hashes, assembly_store.index_entry_count); if (hash_entry == nullptr) { @@ -430,16 +428,15 @@ EmbeddedAssemblies::assembly_store_open_from_bundles (dynamic_local_string(assembly_runtime_info.image_data), - static_cast(assembly_runtime_info.debug_info_data), - static_cast(assembly_runtime_info.config_data), - static_cast(assembly_runtime_info.descriptor), - assembly_runtime_info.descriptor->data_size, - assembly_runtime_info.descriptor->debug_data_size, - assembly_runtime_info.descriptor->config_data_size, - name.get () - ) + "Mapped: image_data == {:p}; debug_info_data == {:p}; config_data == {:p}; descriptor == {:p}; data size == {}; debug data size == {}; config data size == {}; name == '{}'", + static_cast(assembly_runtime_info.image_data), + static_cast(assembly_runtime_info.debug_info_data), + static_cast(assembly_runtime_info.config_data), + static_cast(assembly_runtime_info.descriptor), + assembly_runtime_info.descriptor->data_size, + assembly_runtime_info.descriptor->debug_data_size, + assembly_runtime_info.descriptor->config_data_size, + name.get () ); } @@ -554,7 +551,7 @@ EmbeddedAssemblies::binary_search (const Key *key, const Entry *base, size_t nme if constexpr (use_precalculated_size) { size = precalculated_size; - log_info (LOG_ASSEMBLY, std::format ("Pre-calculated entry size = {}", size)); + log_info (LOG_ASSEMBLY, "Pre-calculated entry size = {}", size); } while (nmemb > 0) { @@ -623,26 +620,26 @@ EmbeddedAssemblies::typemap_java_to_managed ([[maybe_unused]] hash_t hash, const entry = binary_search (java_type_name.get (), type_map.java_to_managed, type_map.entry_count); if (entry == nullptr) [[unlikely]] { - log_info (LOG_ASSEMBLY, std::format ("typemap: unable to find mapping to a managed type from Java type '{}'", java_type_name.get ())); + log_info (LOG_ASSEMBLY, "typemap: unable to find mapping to a managed type from Java type '{}'", java_type_name.get ()); return nullptr; } const char *managed_type_name = entry->to; if (managed_type_name == nullptr) { - log_debug (LOG_ASSEMBLY, std::format ("typemap: Java type '{}' maps either to an open generic type or an interface type.", java_type_name.get ())); + log_debug (LOG_ASSEMBLY, "typemap: Java type '{}' maps either to an open generic type or an interface type.", java_type_name.get ()); return nullptr; } - log_debug (LOG_DEFAULT, std::format ("typemap: Java type '{}' corresponds to managed type '{}'", java_type_name.get (), managed_type_name)); + log_debug (LOG_DEFAULT, "typemap: Java type '{}' corresponds to managed type '{}'", java_type_name.get (), managed_type_name); MonoType *type = mono_reflection_type_from_name (const_cast(managed_type_name), nullptr); if (type == nullptr) [[unlikely]] { - log_info (LOG_ASSEMBLY, std::format ("typemap: managed type '{}' (mapped from Java type '{}') could not be loaded", managed_type_name, java_type_name.get ())); + log_info (LOG_ASSEMBLY, "typemap: managed type '{}' (mapped from Java type '{}') could not be loaded", managed_type_name, java_type_name.get ()); return nullptr; } MonoReflectionType *ret = mono_type_get_object (Util::get_current_domain (), type); if (ret == nullptr) [[unlikely]] { - log_warn (LOG_ASSEMBLY, std::format ("typemap: unable to instantiate managed type '{}'", managed_type_name)); + log_warn (LOG_ASSEMBLY, "typemap: unable to instantiate managed type '{}'", managed_type_name); return nullptr; } @@ -662,16 +659,16 @@ EmbeddedAssemblies::typemap_java_to_managed (hash_t hash, const MonoString *java TypeMapModule *module = java_entry != nullptr && java_entry->module_index < map_module_count ? &map_modules[java_entry->module_index] : nullptr; if (module == nullptr) { if (java_entry == nullptr) { - log_info (LOG_ASSEMBLY, std::format ("typemap: unable to find mapping to a managed type from Java type '{}' (hash {:x})", to_utf8 (java_type_name).get (), hash)); + log_info (LOG_ASSEMBLY, "typemap: unable to find mapping to a managed type from Java type '{}' (hash {:x})", to_utf8 (java_type_name).get (), hash); } else { - log_warn (LOG_ASSEMBLY, std::format ("typemap: mapping from Java type '{}' to managed type has invalid module index {}", to_utf8 (java_type_name).get (), java_entry->module_index)); + log_warn (LOG_ASSEMBLY, "typemap: mapping from Java type '{}' to managed type has invalid module index {}", to_utf8 (java_type_name).get (), java_entry->module_index); } return nullptr; } const TypeMapModuleEntry *entry = binary_search (java_entry->type_token_id, module->map, module->entry_count); if (entry == nullptr) { - log_info (LOG_ASSEMBLY, std::format ("typemap: unable to find mapping from Java type '{}' to managed type with token ID {} in module [{}]", to_utf8 (java_type_name).get (), java_entry->type_token_id, MonoGuidString (module->module_uuid).get ())); + log_info (LOG_ASSEMBLY, "typemap: unable to find mapping from Java type '{}' to managed type with token ID {} in module [{}]", to_utf8 (java_type_name).get (), java_entry->type_token_id, MonoGuidString (module->module_uuid).get ()); return nullptr; } @@ -679,7 +676,7 @@ EmbeddedAssemblies::typemap_java_to_managed (hash_t hash, const MonoString *java module->image = mono_image_loaded (module->assembly_name); if (module->image == nullptr) { - log_debug (LOG_ASSEMBLY, std::format ("typemap: assembly '{}' hasn't been loaded yet, attempting a full load", module->assembly_name)); + log_debug (LOG_ASSEMBLY, "typemap: assembly '{}' hasn't been loaded yet, attempting a full load", module->assembly_name); // Fake a request from MonoVM to load the assembly. MonoAssemblyName *assembly_name = mono_assembly_name_new (module->assembly_name); @@ -702,15 +699,15 @@ EmbeddedAssemblies::typemap_java_to_managed (hash_t hash, const MonoString *java } if (module->image == nullptr) { - log_error (LOG_ASSEMBLY, std::format ("typemap: unable to load assembly '{}' when looking up managed type corresponding to Java type '{}'", module->assembly_name, to_utf8 (java_type_name).get ())); + log_error (LOG_ASSEMBLY, "typemap: unable to load assembly '{}' when looking up managed type corresponding to Java type '{}'", module->assembly_name, to_utf8 (java_type_name).get ()); return nullptr; } } - log_debug (LOG_ASSEMBLY, std::format ("typemap: java type '{}' corresponds to managed token id {} ({:x})", to_utf8 (java_type_name).get (), java_entry->type_token_id, java_entry->type_token_id)); + log_debug (LOG_ASSEMBLY, "typemap: java type '{}' corresponds to managed token id {} ({:x})", to_utf8 (java_type_name).get (), java_entry->type_token_id, java_entry->type_token_id); MonoClass *klass = mono_class_get (module->image, java_entry->type_token_id); if (klass == nullptr) [[unlikely]] { - log_error (LOG_ASSEMBLY, std::format ("typemap: unable to find managed type with token ID {} in assembly '{}', corresponding to Java type '{}'", java_entry->type_token_id, module->assembly_name, to_utf8 (java_type_name).get ())); + log_error (LOG_ASSEMBLY, "typemap: unable to find managed type with token ID {} in assembly '{}', corresponding to Java type '{}'", java_entry->type_token_id, module->assembly_name, to_utf8 (java_type_name).get ()); return nullptr; } @@ -721,7 +718,7 @@ EmbeddedAssemblies::typemap_java_to_managed (hash_t hash, const MonoString *java MonoReflectionType *ret = mono_type_get_object (domain, mono_class_get_type (klass)); if (ret == nullptr) { - log_warn (LOG_ASSEMBLY, std::format ("typemap: unable to instantiate managed type with token ID {} in assembly '{}', corresponding to Java type '{}'", java_entry->type_token_id, module->assembly_name, to_utf8 (java_type_name).get ())); + log_warn (LOG_ASSEMBLY, "typemap: unable to instantiate managed type with token ID {} in assembly '{}', corresponding to Java type '{}'", java_entry->type_token_id, module->assembly_name, to_utf8 (java_type_name).get ()); return nullptr; } @@ -786,7 +783,7 @@ EmbeddedAssemblies::typemap_managed_to_java ([[maybe_unused]] MonoType *type, Mo const TypeMapEntry *entry = typemap_managed_to_java (full_name.get ()); if (entry == nullptr) [[unlikely]] { - log_info (LOG_ASSEMBLY, std::format ("typemap: unable to find mapping to a Java type from managed type '{}'", full_name.get ())); + log_info (LOG_ASSEMBLY, "typemap: unable to find mapping to a Java type from managed type '{}'", full_name.get ()); return nullptr; } @@ -807,13 +804,13 @@ EmbeddedAssemblies::typemap_managed_to_java ([[maybe_unused]] MonoType *type, Mo if (mvid == nullptr) { log_warn (LOG_ASSEMBLY, "typemap: no mvid specified in call to typemap_managed_to_java"sv); } else { - log_info (LOG_ASSEMBLY, std::format ("typemap: module matching MVID [{}] not found.", MonoGuidString (mvid).get ())); + log_info (LOG_ASSEMBLY, "typemap: module matching MVID [{}] not found.", MonoGuidString (mvid).get ()); } return nullptr; } uint32_t token = mono_class_get_type_token (klass); - log_debug (LOG_ASSEMBLY, std::format ("typemap: MVID [{}] maps to assembly {}, looking for token {} ({:x}), table index {}", MonoGuidString (mvid).get (), match->assembly_name, token, token, token & 0x00FFFFFF)); + log_debug (LOG_ASSEMBLY, "typemap: MVID [{}] maps to assembly {}, looking for token {} ({:x}), table index {}", MonoGuidString (mvid).get (), match->assembly_name, token, token, token & 0x00FFFFFF); // Each map entry is a pair of 32-bit integers: [TypeTokenID][JavaMapArrayIndex] const TypeMapModuleEntry *entry = match->map != nullptr ? binary_search (token, match->map, match->entry_count) : nullptr; if (entry == nullptr) { @@ -823,41 +820,40 @@ EmbeddedAssemblies::typemap_managed_to_java ([[maybe_unused]] MonoType *type, Mo } if (match->duplicate_count > 0 && match->duplicate_map != nullptr) { - log_debug (LOG_ASSEMBLY, std::format ("typemap: searching module [{}] duplicate map for token {} ({:x})", MonoGuidString (mvid).get (), token, token)); + log_debug (LOG_ASSEMBLY, "typemap: searching module [{}] duplicate map for token {} ({:x})", MonoGuidString (mvid).get (), token, token); entry = binary_search (token, match->duplicate_map, match->duplicate_count); } if (entry == nullptr) { - log_info (LOG_ASSEMBLY, std::format ("typemap: type with token {} ({:x}) in module [{}] ({}) not found.", token, token, MonoGuidString (mvid).get (), match->assembly_name)); + log_info (LOG_ASSEMBLY, "typemap: type with token {} ({:x}) in module [{}] ({}) not found.", token, token, MonoGuidString (mvid).get (), match->assembly_name); return nullptr; } } if (entry->java_map_index >= java_type_count) [[unlikely]] { - log_warn (LOG_ASSEMBLY, std::format ("typemap: type with token {} ({:x}) in module [{}] ({}) has invalid Java type index {}", token, token, MonoGuidString (mvid).get (), match->assembly_name, entry->java_map_index)); + log_warn (LOG_ASSEMBLY, "typemap: type with token {} ({:x}) in module [{}] ({}) has invalid Java type index {}", token, token, MonoGuidString (mvid).get (), match->assembly_name, entry->java_map_index); return nullptr; } TypeMapJava const& java_entry = map_java[entry->java_map_index]; if (java_entry.java_name_index >= java_type_count) [[unlikely]] { - log_warn (LOG_ASSEMBLY, std::format ("typemap: type with token {} ({:x}) in module [{}] ({}) points to invalid Java type at index {} (invalid type name index {})", token, token, MonoGuidString (mvid).get (), match->assembly_name, entry->java_map_index, java_entry.java_name_index)); + log_warn (LOG_ASSEMBLY, "typemap: type with token {} ({:x}) in module [{}] ({}) points to invalid Java type at index {} (invalid type name index {})", token, token, MonoGuidString (mvid).get (), match->assembly_name, entry->java_map_index, java_entry.java_name_index); return nullptr; } const char *ret = java_type_names[java_entry.java_name_index]; if (ret == nullptr) [[unlikely]] { - log_warn (LOG_ASSEMBLY, std::format ("typemap: empty Java type name returned for entry at index {}", entry->java_map_index)); + log_warn (LOG_ASSEMBLY, "typemap: empty Java type name returned for entry at index {}", entry->java_map_index); } log_debug ( LOG_ASSEMBLY, - std::format ("typemap: type with token {} ({:x}) in module [{}] ({}) corresponds to Java type '{}'", - token, - token, - MonoGuidString (mvid).get (), - match->assembly_name, - ret - ) + "typemap: type with token {} ({:x}) in module [{}] ({}) corresponds to Java type '{}'", + token, + token, + MonoGuidString (mvid).get (), + match->assembly_name, + ret ); return ret; @@ -919,7 +915,7 @@ EmbeddedAssemblies::md_mmap_apk_file (int fd, uint32_t offset, size_t size, cons log_info ( LOG_ASSEMBLY, - std::format (" mmap_start: {:<8p}; mmap_end: {:<8p} mmap_len: {:<12} file_start: {:<8p} file_end: {:<8p} file_len: {:<12} apk descriptor: {} file: {}", + " mmap_start: {:<8p}; mmap_end: {:<8p} mmap_len: {:<12} file_start: {:<8p} file_end: {:<8p} file_len: {:<12} apk descriptor: {} file: {}", mmap_info.area, pointer_add (mmap_info.area, mmap_info.size), mmap_info.size, @@ -928,7 +924,6 @@ EmbeddedAssemblies::md_mmap_apk_file (int fd, uint32_t offset, size_t size, cons file_info.size, fd, filename - ) ); return file_info; @@ -948,7 +943,7 @@ EmbeddedAssemblies::gather_bundled_assemblies_from_apk (const char* apk, monodro ) ); } - log_debug (LOG_ASSEMBLY, std::format ("APK {} FD: {}", apk, fd)); + log_debug (LOG_ASSEMBLY, "APK {} FD: {}", apk, fd); zip_load_entries (fd, apk, should_register); } @@ -975,40 +970,40 @@ EmbeddedAssemblies::typemap_read_header ([[maybe_unused]] int dir_fd, const char struct stat sbuf; int res = fstatat (dir_fd, file_path, &sbuf, 0); if (res < 0) { - log_error (LOG_ASSEMBLY, std::format ("typemap: failed to stat {} file '{}/{}': {}", file_type, dir_path, file_path, strerror (errno))); + log_error (LOG_ASSEMBLY, "typemap: failed to stat {} file '{}/{}': {}", file_type, dir_path, file_path, strerror (errno)); return false; } file_size = static_cast(sbuf.st_size); if (file_size < sizeof (header)) { - log_error (LOG_ASSEMBLY, std::format ("typemap: {} file '{}/{}' is too small (must be at least {} bytes)", file_type, dir_path, file_path, sizeof (header))); + log_error (LOG_ASSEMBLY, "typemap: {} file '{}/{}' is too small (must be at least {} bytes)", file_type, dir_path, file_path, sizeof (header)); return false; } fd = openat (dir_fd, file_path, O_RDONLY); if (fd < 0) { - log_error (LOG_ASSEMBLY, std::format ("typemap: failed to open {} file {}/{} for reading: {}", file_type, dir_path, file_path, strerror (errno))); + log_error (LOG_ASSEMBLY, "typemap: failed to open {} file {}/{} for reading: {}", file_type, dir_path, file_path, strerror (errno)); return false; } ssize_t nread = do_read (fd, &header, sizeof (header)); if (nread <= 0) { if (nread < 0) { - log_error (LOG_ASSEMBLY, std::format ("typemap: failed to read {} file header from '{}/{}': {}", file_type, dir_path, file_path, strerror (errno))); + log_error (LOG_ASSEMBLY, "typemap: failed to read {} file header from '{}/{}': {}", file_type, dir_path, file_path, strerror (errno)); } else { - log_error (LOG_ASSEMBLY, std::format ("typemap: end of file while reading {} file header from '{}/{}'", file_type, dir_path, file_path)); + log_error (LOG_ASSEMBLY, "typemap: end of file while reading {} file header from '{}/{}'", file_type, dir_path, file_path); } return false; } if (header.magic != expected_magic) { - log_error (LOG_ASSEMBLY, std::format ("typemap: invalid magic value in the {} file header from '{}/{}': expected {:x}, got {:x}", file_type, dir_path, file_path, expected_magic, header.magic)); + log_error (LOG_ASSEMBLY, "typemap: invalid magic value in the {} file header from '{}/{}': expected {:x}, got {:x}", file_type, dir_path, file_path, expected_magic, header.magic); return false; } if (header.version != MODULE_FORMAT_VERSION) { - log_error (LOG_ASSEMBLY, std::format ("typemap: incompatible {} format version. This build supports only version {}, file '{}/{}' uses version {}", file_type, MODULE_FORMAT_VERSION, dir_path, file_path, header.version)); + log_error (LOG_ASSEMBLY, "typemap: incompatible {} format version. This build supports only version {}, file '{}/{}' uses version {}", file_type, MODULE_FORMAT_VERSION, dir_path, file_path, header.version); return false; } @@ -1021,14 +1016,14 @@ EmbeddedAssemblies::typemap_load_index (TypeMapIndexHeader &header, size_t file_ size_t entry_size = header.module_file_name_width; size_t data_size = entry_size * type_map_count; if (sizeof(header) + data_size > file_size) { - log_error (LOG_ASSEMBLY, std::format ("typemap: index file is too small, expected {}, found {} bytes", data_size + sizeof(header), file_size)); + log_error (LOG_ASSEMBLY, "typemap: index file is too small, expected {}, found {} bytes", data_size + sizeof(header), file_size); return nullptr; } auto data = std::make_unique (data_size); ssize_t nread = do_read (index_fd, data.get (), data_size); if (nread != static_cast(data_size)) { - log_error (LOG_ASSEMBLY, std::format ("typemap: failed to read {} bytes from index file. {}", data_size, strerror (errno))); + log_error (LOG_ASSEMBLY, "typemap: failed to read {} bytes from index file. {}", data_size, strerror (errno)); return nullptr; } @@ -1044,7 +1039,7 @@ EmbeddedAssemblies::typemap_load_index (TypeMapIndexHeader &header, size_t file_ std::unique_ptr EmbeddedAssemblies::typemap_load_index (int dir_fd, const char *dir_path, const char *index_path) { - log_debug (LOG_ASSEMBLY, std::format ("typemap: loading TypeMap index file '{}/{}'", dir_path, index_path)); + log_debug (LOG_ASSEMBLY, "typemap: loading TypeMap index file '{}/{}'", dir_path, index_path); TypeMapIndexHeader header; size_t file_size; @@ -1071,7 +1066,7 @@ EmbeddedAssemblies::typemap_load_file (BinaryTypeMapHeader &header, const char * ssize_t nread = do_read (file_fd, module.assembly_name, header.assembly_name_length); if (nread != static_cast(header.assembly_name_length)) { - log_error (LOG_ASSEMBLY, std::format ("typemap: failed to read map assembly name from '{}/{}': {}", dir_path, file_path, strerror (errno))); + log_error (LOG_ASSEMBLY, "typemap: failed to read map assembly name from '{}/{}': {}", dir_path, file_path, strerror (errno)); return false; } @@ -1080,16 +1075,14 @@ EmbeddedAssemblies::typemap_load_file (BinaryTypeMapHeader &header, const char * log_debug ( LOG_ASSEMBLY, - std::format ( - "typemap: '{}/{}':: entry count == {}; Java name field width == {}; Managed name width == {}; assembly name length == {}; assembly name == {}", - dir_path, - file_path, - header.entry_count, - header.java_name_width, - header.managed_name_width, - header.assembly_name_length, - module.assembly_name - ) + "typemap: '{}/{}':: entry count == {}; Java name field width == {}; Managed name width == {}; assembly name length == {}; assembly name == {}", + dir_path, + file_path, + header.entry_count, + header.java_name_width, + header.managed_name_width, + header.assembly_name_length, + module.assembly_name ); // [name][index] @@ -1103,7 +1096,7 @@ EmbeddedAssemblies::typemap_load_file (BinaryTypeMapHeader &header, const char * module.data = new uint8_t [data_size]; nread = do_read (file_fd, module.data, data_size); if (nread != static_cast(data_size)) { - log_error (LOG_ASSEMBLY, std::format ("typemap: failed to read map data from '{}/{}': {}", dir_path, file_path, strerror (errno))); + log_error (LOG_ASSEMBLY, "typemap: failed to read map data from '{}/{}': {}", dir_path, file_path, strerror (errno)); return false; } @@ -1147,7 +1140,7 @@ EmbeddedAssemblies::typemap_load_file (BinaryTypeMapHeader &header, const char * bool EmbeddedAssemblies::typemap_load_file (int dir_fd, const char *dir_path, const char *file_path, TypeMap &module) { - log_debug (LOG_ASSEMBLY, std::format ("typemap: loading TypeMap file '{}/{}'", dir_path, file_path)); + log_debug (LOG_ASSEMBLY, "typemap: loading TypeMap file '{}/{}'", dir_path, file_path); bool ret = true; BinaryTypeMapHeader header; @@ -1186,7 +1179,7 @@ EmbeddedAssemblies::register_from_apk (const char *apk_file, monodroid_should_re gather_bundled_assemblies_from_apk (apk_file, should_register); - log_info (LOG_ASSEMBLY, std::format ("Package '{}' contains {} assemblies", apk_file, number_of_found_assemblies - prev)); + log_info (LOG_ASSEMBLY, "Package '{}' contains {} assemblies", apk_file, number_of_found_assemblies - prev); return number_of_found_assemblies; } @@ -1290,10 +1283,10 @@ EmbeddedAssemblies::maybe_register_blob_from_filesystem ( force_inline size_t EmbeddedAssemblies::register_from_filesystem (const char *lib_dir_path,bool look_for_mangled_names, monodroid_should_register should_register) noexcept { - log_debug (LOG_ASSEMBLY, std::format ("Looking for assemblies in '{}'", lib_dir_path)); + log_debug (LOG_ASSEMBLY, "Looking for assemblies in '{}'", lib_dir_path); DIR *lib_dir = opendir (lib_dir_path); // TODO: put it in a scope guard at some point if (lib_dir == nullptr) { - log_warn (LOG_ASSEMBLY, std::format ("Unable to open app library directory '{}': {}", lib_dir_path, std::strerror (errno))); + log_warn (LOG_ASSEMBLY, "Unable to open app library directory '{}': {}", lib_dir_path, std::strerror (errno)); return 0; } @@ -1302,14 +1295,14 @@ EmbeddedAssemblies::register_from_filesystem (const char *lib_dir_path,bool look int dir_fd = dirfd (lib_dir); if (dir_fd < 0) [[unlikely]] { - log_warn (LOG_ASSEMBLY, std::format ("Unable to obtain file descriptor for directory '{}': {}", lib_dir_path, std::strerror (errno))); + log_warn (LOG_ASSEMBLY, "Unable to obtain file descriptor for directory '{}': {}", lib_dir_path, std::strerror (errno)); closedir (lib_dir); return 0; } state.file_fd = dup (dir_fd); if (state.file_fd < 0) [[unlikely]] { - log_warn (LOG_ASSEMBLY, std::format ("Unable to duplicate file descriptor {} for directory '{}': {}", dir_fd, lib_dir_path, std::strerror (errno))); + log_warn (LOG_ASSEMBLY, "Unable to duplicate file descriptor {} for directory '{}': {}", dir_fd, lib_dir_path, std::strerror (errno)); closedir (lib_dir); return 0; } @@ -1326,7 +1319,7 @@ EmbeddedAssemblies::register_from_filesystem (const char *lib_dir_path,bool look dirent *cur = readdir (lib_dir); if (cur == nullptr) { if (errno != 0) { - log_warn (LOG_ASSEMBLY, std::format ("Failed to open a directory entry from '{}': {}", lib_dir_path, std::strerror (errno))); + log_warn (LOG_ASSEMBLY, "Failed to open a directory entry from '{}': {}", lib_dir_path, std::strerror (errno)); continue; // keep going, no harm } break; // No more entries, we're done @@ -1346,7 +1339,7 @@ EmbeddedAssemblies::register_from_filesystem (const char *lib_dir_path,bool look // ...and we can handle the runtime config entry if (!runtime_config_blob_found && std::strncmp (cur->d_name, SharedConstants::RUNTIME_CONFIG_BLOB_NAME.data (), SharedConstants::RUNTIME_CONFIG_BLOB_NAME.size ()) == 0) { - log_debug (LOG_ASSEMBLY, std::format ("Mapping runtime config blob from '{}'", cur->d_name)); + log_debug (LOG_ASSEMBLY, "Mapping runtime config blob from '{}'", cur->d_name); auto file_size = Util::get_file_size_at (state.file_fd, cur->d_name); if (!file_size) { continue; @@ -1393,6 +1386,6 @@ EmbeddedAssemblies::register_from_filesystem (monodroid_should_register should_r ); #endif - log_debug (LOG_ASSEMBLY, std::format ("Found {} assemblies on the filesystem", assembly_count)); + log_debug (LOG_ASSEMBLY, "Found {} assemblies on the filesystem", assembly_count); return assembly_count; } diff --git a/src/native/monodroid/embedded-assemblies.hh b/src/native/monodroid/embedded-assemblies.hh index 21fc0de80b8..c17d957b4c2 100644 --- a/src/native/monodroid/embedded-assemblies.hh +++ b/src/native/monodroid/embedded-assemblies.hh @@ -310,7 +310,7 @@ namespace xamarin::android::internal { elf_header->e_ident[EI_MAG1] != ELFMAG1 || elf_header->e_ident[EI_MAG2] != ELFMAG2 || elf_header->e_ident[EI_MAG3] != ELFMAG3) { - log_debug (LOG_ASSEMBLY, std::format ("Not an ELF image: {}", file_name)); + log_debug (LOG_ASSEMBLY, "Not an ELF image: {}", file_name); // Not an ELF image, just return what we mmapped before return { map_info.area, map_info.size }; } @@ -329,7 +329,7 @@ namespace xamarin::android::internal { static void store_mapped_runtime_config_data (md_mmap_info const& map_info, const char *file_name) noexcept { auto [payload_start, payload_size] = get_wrapper_dso_payload_pointer_and_size (map_info, file_name); - log_debug (LOG_ASSEMBLY, std::format ("Runtime config: payload pointer {:p} ; size {}", payload_start, payload_size)); + log_debug (LOG_ASSEMBLY, "Runtime config: payload pointer {:p} ; size {}", payload_start, payload_size); runtime_config_data = payload_start; runtime_config_data_size = payload_size; runtime_config_blob_found = true; @@ -431,7 +431,7 @@ namespace xamarin::android::internal { } } } - log_debug (LOG_ASSEMBLY, std::format ("Unmangled name to '{}'", name.get ())); + log_debug (LOG_ASSEMBLY, "Unmangled name to '{}'", name.get ()); }; private: diff --git a/src/native/monodroid/monodroid-glue-internal.hh b/src/native/monodroid/monodroid-glue-internal.hh index dbd78121458..da7f9f6be2c 100644 --- a/src/native/monodroid/monodroid-glue-internal.hh +++ b/src/native/monodroid/monodroid-glue-internal.hh @@ -166,7 +166,7 @@ namespace xamarin::android::internal void *symptr = MonodroidDl::monodroid_dlsym (handle, name, &err, nullptr); if (symptr == nullptr) { - log_warn (LOG_DEFAULT, std::format ("Failed to load symbol '{}' library with handle {}. {}", name, handle, err == nullptr ? "Unknown error"sv : err)); + log_warn (LOG_DEFAULT, "Failed to load symbol '{}' library with handle {}. {}", name, handle, err == nullptr ? "Unknown error"sv : err); fnptr = nullptr; return; } diff --git a/src/native/monodroid/monodroid-glue.cc b/src/native/monodroid/monodroid-glue.cc index 25c10b07660..49e614a4455 100644 --- a/src/native/monodroid/monodroid-glue.cc +++ b/src/native/monodroid/monodroid-glue.cc @@ -174,12 +174,12 @@ MonodroidRuntime::open_from_update_dir (MonoAssemblyName *aname, [[maybe_unused] fullpath.append (SharedConstants::DLL_EXTENSION); } - log_debug (LOG_ASSEMBLY, std::format ("open_from_update_dir: trying to open assembly: {}", fullpath.get ())); + log_debug (LOG_ASSEMBLY, "open_from_update_dir: trying to open assembly: {}", fullpath.get ()); if (Util::file_exists (fullpath.get ())) { MonoImageOpenStatus status{}; result = mono_assembly_open_full (fullpath.get (), &status, 0); if (result == nullptr || status != MonoImageOpenStatus::MONO_IMAGE_OK) { - log_warn (LOG_ASSEMBLY, std::format ("Failed to load managed assembly '{}'. {}", fullpath.get (), mono_image_strerror (status))); + log_warn (LOG_ASSEMBLY, "Failed to load managed assembly '{}'. {}", fullpath.get (), mono_image_strerror (status)); } } else { log_warn (LOG_ASSEMBLY, "open_from_update_dir: assembly file DOES NOT EXIST"sv); @@ -191,7 +191,7 @@ MonodroidRuntime::open_from_update_dir (MonoAssemblyName *aname, [[maybe_unused] } if (result != nullptr && Util::should_log (LOG_ASSEMBLY)) { - log_info_nocheck (LOG_ASSEMBLY, std::format ("open_from_update_dir: loaded assembly: {:p}", reinterpret_cast(result))); + log_info_nocheck_fmt (LOG_ASSEMBLY, "open_from_update_dir: loaded assembly: {:p}", reinterpret_cast(result)); } return result; } @@ -378,7 +378,7 @@ MonodroidRuntime::parse_gdb_options () noexcept time_t secs = time (nullptr); if (v + 10 < secs) { - log_warn (LOG_DEFAULT, std::format ("Found stale {} property with value '{}', not waiting.", SharedConstants::DEBUG_MONO_GDB_PROPERTY.data (), val.get ())); + log_warn (LOG_DEFAULT, "Found stale {} property with value '{}', not waiting.", SharedConstants::DEBUG_MONO_GDB_PROPERTY.data (), val.get ()); do_wait = false; } } @@ -449,13 +449,13 @@ MonodroidRuntime::parse_runtime_args (dynamic_local_string std::numeric_limits::max ()) { - log_error (LOG_DEFAULT, std::format ("Invalid SDB port value {}", sdb_port)); + log_error (LOG_DEFAULT, "Invalid SDB port value {}", sdb_port); ret = false; continue; } if (out_port > std::numeric_limits::max ()) { - log_error (LOG_DEFAULT, std::format ("Invalid output port value {}", out_port)); + log_error (LOG_DEFAULT, "Invalid output port value {}", out_port); ret = false; continue; } @@ -480,7 +480,7 @@ MonodroidRuntime::parse_runtime_args (dynamic_local_string arg (token); - log_error (LOG_DEFAULT, std::format ("Unknown runtime argument: '{}'", arg.get ())); + log_error (LOG_DEFAULT, "Unknown runtime argument: '{}'", arg.get ()); ret = false; } } @@ -509,9 +509,9 @@ MonodroidRuntime::mono_runtime_init ([[maybe_unused]] JNIEnv *env, [[maybe_unuse cur_time = time (nullptr); if (!parse_runtime_args (runtime_args, &options)) { - log_error (LOG_DEFAULT, std::format ("Failed to parse runtime args: '{}'", runtime_args.get ())); + log_error (LOG_DEFAULT, "Failed to parse runtime args: '{}'", runtime_args.get ()); } else if (options.debug && cur_time > options.timeout_time) { - log_warn (LOG_DEBUGGER, std::format ("Not starting the debugger as the timeout value has been reached; current-time: {}; timeout: {}", cur_time, options.timeout_time)); + log_warn (LOG_DEBUGGER, "Not starting the debugger as the timeout value has been reached; current-time: {}; timeout: {}", cur_time, options.timeout_time); } else if (options.debug && cur_time <= options.timeout_time) { EmbeddedAssemblies::set_register_debug_symbols (true); @@ -537,7 +537,7 @@ MonodroidRuntime::mono_runtime_init ([[maybe_unused]] JNIEnv *env, [[maybe_unuse // this text is used in unit tests to check the debugger started // do not change it without updating the test. - log_warn (LOG_DEBUGGER, std::format ("Trying to initialize the debugger with options: {}", debug_arg)); + log_warn (LOG_DEBUGGER, "Trying to initialize the debugger with options: {}", debug_arg); if (options.out_port > 0) { int sock = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP); @@ -570,7 +570,7 @@ MonodroidRuntime::mono_runtime_init ([[maybe_unused]] JNIEnv *env, [[maybe_unuse if (options.server) { int accepted = monodroid_debug_accept (sock, addr); - log_warn (LOG_DEBUGGER, std::format ("Accepted stdout connection: {}", accepted)); + log_warn (LOG_DEBUGGER, "Accepted stdout connection: {}", accepted); if (accepted < 0) { Helpers::abort_application ( LOG_DEBUGGER, @@ -662,7 +662,7 @@ MonodroidRuntime::mono_runtime_init ([[maybe_unused]] JNIEnv *env, [[maybe_unuse if (AndroidSystem::monodroid_get_system_property (SharedConstants::DEBUG_MONO_RUNTIME_ARGS_PROPERTY, prop_val) > 0) { char **ptr; - log_warn (LOG_DEBUGGER, std::format ("passing '{}' as extra arguments to the runtime.", prop_val.get ())); + log_warn (LOG_DEBUGGER, "passing '{}' as extra arguments to the runtime.", prop_val.get ()); char **args = Util::monodroid_strsplit (prop_val.get (), " ", 0); int argc = 0; @@ -730,11 +730,9 @@ MonodroidRuntime::create_domain (JNIEnv *env, jstring_array_wrapper &runtimeApks if (user_assemblies_count == 0 && AndroidSystem::count_override_assemblies () == 0 && !is_running_on_desktop) { #if defined (DEBUG) log_fatal (LOG_DEFAULT, - std::format ( - "No assemblies found in '{}' or '{}'. Assuming this is part of Fast Deployment. Exiting...", - AndroidSystem::override_dirs [0], - (AndroidSystem::override_dirs.size () > 1 && AndroidSystem::override_dirs [1] != nullptr) ? AndroidSystem::override_dirs [1] : ""sv - ) + "No assemblies found in '{}' or '{}'. Assuming this is part of Fast Deployment. Exiting...", + AndroidSystem::override_dirs [0], + (AndroidSystem::override_dirs.size () > 1 && AndroidSystem::override_dirs [1] != nullptr) ? AndroidSystem::override_dirs [1] : ""sv ); #else log_fatal (LOG_DEFAULT, "No assemblies (or assembly blobs) were found in the application APK file(s) or on the filesystem"sv); @@ -858,7 +856,7 @@ MonodroidRuntime::init_android_runtime (JNIEnv *env, jclass runtimeClass, jobjec // GC threshold is 90% of the max GREF count init.grefGcThreshold = static_cast(AndroidSystem::get_gref_gc_threshold ()); - log_info (LOG_GC, std::format ("GREF GC Threshold: {}", init.grefGcThreshold)); + log_info (LOG_GC, "GREF GC Threshold: {}", init.grefGcThreshold); init.grefClass = RuntimeUtil::get_class_from_runtime_field (env, runtimeClass, "java_lang_Class", true); Class_getName = env->GetMethodID (init.grefClass, "getName", "()Ljava/lang/String;"); @@ -944,7 +942,7 @@ MonodroidRuntime::init_android_runtime (JNIEnv *env, jclass runtimeClass, jobjec auto initialize = reinterpret_cast (mono_method_get_unmanaged_callers_only_ftnptr (method, &error)); if (initialize == nullptr) { - log_fatal (LOG_DEFAULT, std::format ("Failed to get pointer to Initialize. Mono error: {}", mono_error_get_message (&error))); + log_fatal (LOG_DEFAULT, "Failed to get pointer to Initialize. Mono error: {}", mono_error_get_message (&error)); } abort_unless ( @@ -1000,7 +998,7 @@ MonodroidRuntime::set_environment_variable_for_directory (const char *name, jstr if (createDirectory) { int rv = Util::create_directory (value.get_cstr (), mode); if (rv < 0 && errno != EEXIST) - log_warn (LOG_DEFAULT, std::format ("Failed to create directory for environment variable {}. {}", name, strerror (errno))); + log_warn (LOG_DEFAULT, "Failed to create directory for environment variable {}. {}", name, strerror (errno)); } setenv (name, value.get_cstr (), 1); } @@ -1010,10 +1008,10 @@ MonodroidRuntime::create_xdg_directory (jstring_wrapper& home, size_t home_len, { static_local_string dir (home_len + relative_path.length ()); Util::path_combine (dir, home.get_cstr (), home_len, relative_path.data (), relative_path.length ()); - log_debug (LOG_DEFAULT, std::format ("Creating XDG directory: {}", dir.get ())); + log_debug (LOG_DEFAULT, "Creating XDG directory: {}", dir.get ()); int rv = Util::create_directory (dir.get (), DEFAULT_DIRECTORY_MODE); if (rv < 0 && errno != EEXIST) - log_warn (LOG_DEFAULT, std::format ("Failed to create XDG directory {}. {}", dir.get (), strerror (errno))); + log_warn (LOG_DEFAULT, "Failed to create XDG directory {}. {}", dir.get (), strerror (errno)); if (!environment_variable_name.empty ()) { setenv (environment_variable_name.data (), dir.get (), 1); } @@ -1042,7 +1040,7 @@ MonodroidRuntime::set_debug_env_vars (void) noexcept return; auto log_envvar = [](const char *name, const char *v) { - log_debug (LOG_DEFAULT, std::format ("Env variable '{}' set to '{}'.", name, v)); + log_debug (LOG_DEFAULT, "Env variable '{}' set to '{}'.", name, v); }; string_segment arg_token; @@ -1062,7 +1060,7 @@ MonodroidRuntime::set_debug_env_vars (void) noexcept log_envvar (arg.get (), one.data ()); } else if (index == 0) { // ’=value’ - log_warn (LOG_DEFAULT, std::format ("Attempt to set environment variable without specifying name: '{}'", arg.get ())); + log_warn (LOG_DEFAULT, "Attempt to set environment variable without specifying name: '{}'", arg.get ()); } else { // ’name=value’ arg[index] = '\0'; @@ -1142,10 +1140,10 @@ MonodroidRuntime::set_profile_options () noexcept .append (output_path.get (), output_path.length ()); } if (Util::create_directory (AndroidSystem::override_dirs[0], 0) < 0) { - log_warn (LOG_DEFAULT, std::format ("Failed to create directory '{}'. {}", AndroidSystem::override_dirs[0], std::strerror (errno))); + log_warn (LOG_DEFAULT, "Failed to create directory '{}'. {}", AndroidSystem::override_dirs[0], std::strerror (errno)); } - log_warn (LOG_DEFAULT, std::format ("Initializing profiler with options: {}", value.get ())); + log_warn (LOG_DEFAULT, "Initializing profiler with options: {}", value.get ()); debug.monodroid_profiler_load (AndroidSystem::get_runtime_libdir (), value.get (), output_path.get ()); } @@ -1470,7 +1468,7 @@ MonodroidRuntime::Java_mono_android_Runtime_initInternal (JNIEnv *env, jclass kl if (runtimeNativeLibDir != nullptr) { jstr = runtimeNativeLibDir; AndroidSystem::set_runtime_libdir (strdup (jstr.get_cstr ())); - log_debug (LOG_DEFAULT, std::format ("Using runtime path: {}", AndroidSystem::get_runtime_libdir ())); + log_debug (LOG_DEFAULT, "Using runtime path: {}", AndroidSystem::get_runtime_libdir ()); } AndroidSystem::setup_process_args (runtimeApks); @@ -1533,17 +1531,16 @@ MonodroidRuntime::Java_mono_android_Runtime_initInternal (JNIEnv *env, jclass kl } if (Util::should_log (LOG_DEFAULT)) [[unlikely]] { - log_info_nocheck ( + log_info_nocheck_fmt ( LOG_DEFAULT, - std::format (".NET for Android version: {} ({}; {}); built on {}; NDK version: {}; API level: {}; MonoVM version: {}", - BuildInfo::xa_version.data (), - BuildInfo::architecture.data (), - BuildInfo::kind.data (), - BuildInfo::date.data (), - BuildInfo::ndk_version.data (), - BuildInfo::ndk_api_level.data (), - mono_get_runtime_build_info () - ) + ".NET for Android version: {} ({}; {}); built on {}; NDK version: {}; API level: {}; MonoVM version: {}", + BuildInfo::xa_version.data (), + BuildInfo::architecture.data (), + BuildInfo::kind.data (), + BuildInfo::date.data (), + BuildInfo::ndk_version.data (), + BuildInfo::ndk_api_level.data (), + mono_get_runtime_build_info () ); } @@ -1666,7 +1663,7 @@ MonodroidRuntime::get_java_class_name_for_TypeManager (jclass klass) noexcept JNIEnv *env = osBridge.ensure_jnienv (); jstring name = reinterpret_cast (env->CallObjectMethod (klass, Class_getName)); if (name == nullptr) { - log_error (LOG_DEFAULT, std::format ("Failed to obtain Java class name for object at {:p}", reinterpret_cast(klass))); + log_error (LOG_DEFAULT, "Failed to obtain Java class name for object at {:p}", reinterpret_cast(klass)); return nullptr; } diff --git a/src/native/monodroid/monodroid-networkinfo.cc b/src/native/monodroid/monodroid-networkinfo.cc index f9dcba4c181..4e87c0079d3 100644 --- a/src/native/monodroid/monodroid-networkinfo.cc +++ b/src/native/monodroid/monodroid-networkinfo.cc @@ -88,14 +88,14 @@ _monodroid_get_network_interface_state (const char *ifname, mono_bool *is_up, mo networkInterface = env->CallStaticObjectMethod (NetworkInterface_class, NetworkInterface_getByName, NetworkInterface_nameArg); env->DeleteLocalRef (NetworkInterface_nameArg); if (env->ExceptionOccurred ()) { - log_warn (LOG_NET, std::format ("Java exception occurred while looking up the interface '{}'", ifname)); + log_warn (LOG_NET, "Java exception occurred while looking up the interface '{}'", ifname); env->ExceptionDescribe (); env->ExceptionClear (); goto leave; } if (!networkInterface) { - log_warn (LOG_NET, std::format ("Failed to look up interface '{}' using Java API", ifname)); + log_warn (LOG_NET, "Failed to look up interface '{}' using Java API", ifname); ret = FALSE; goto leave; } @@ -118,7 +118,7 @@ _monodroid_get_network_interface_state (const char *ifname, mono_bool *is_up, mo leave: if (!ret) - log_warn (LOG_NET, std::format ("Unable to determine interface '{}' state using Java API", ifname)); + log_warn (LOG_NET, "Unable to determine interface '{}' state using Java API", ifname); if (networkInterface != nullptr && env != nullptr) { env->DeleteLocalRef (networkInterface); diff --git a/src/native/monodroid/monodroid-tracing.cc b/src/native/monodroid/monodroid-tracing.cc index 56db0e50dd1..96c9778dd37 100644 --- a/src/native/monodroid/monodroid-tracing.cc +++ b/src/native/monodroid/monodroid-tracing.cc @@ -27,7 +27,7 @@ MonodroidRuntime::log_traces (JNIEnv *env, TraceKind kind, const char *first_lin char *err = nullptr; void *handle = MonodroidDl::monodroid_dlopen (SharedConstants::xamarin_native_tracing_name.data (), MONO_DL_EAGER, &err, nullptr); if (handle == nullptr) { - log_warn (LOG_DEFAULT, std::format ("Failed to load native tracing library '{}'. {}", SharedConstants::xamarin_native_tracing_name, err == nullptr ? "Unknown error"sv : err)); + log_warn (LOG_DEFAULT, "Failed to load native tracing library '{}'. {}", SharedConstants::xamarin_native_tracing_name, err == nullptr ? "Unknown error"sv : err); } else { load_symbol (handle, "xa_get_native_backtrace", _xa_get_native_backtrace); load_symbol (handle, "xa_get_managed_backtrace", _xa_get_managed_backtrace); diff --git a/src/native/monodroid/osbridge.cc b/src/native/monodroid/osbridge.cc index 94e0317d3e9..e909ab51ec2 100644 --- a/src/native/monodroid/osbridge.cc +++ b/src/native/monodroid/osbridge.cc @@ -188,7 +188,7 @@ OSBridge::_write_stack_trace (FILE *to, char *from, LogCategories category) *end = '\0'; if ((category == LOG_GREF && gref_to_logcat) || (category == LOG_LREF && lref_to_logcat)) { - log_debug (category, std::format ("{}", m)); + log_debug (category, "{}", m); } if (to != nullptr) { fprintf (to, "%s\n", m); @@ -202,7 +202,7 @@ void OSBridge::_monodroid_gref_log (const char *message) { if (gref_to_logcat) { - log_debug (LOG_GREF, std::format ("{}", message)); + log_debug (LOG_GREF, "{}", message); } if (!gref_log) return; @@ -217,22 +217,21 @@ OSBridge::_monodroid_gref_log_new (jobject curHandle, char curType, jobject newH if ((log_categories & LOG_GREF) == 0) return c; log_info (LOG_GREF, - std::format ("+g+ grefc {} gwrefc {} obj-handle {:p}/{} -> new-handle {:p}/{} from thread '{}'({})", - c, - gc_weak_gref_count, - reinterpret_cast(curHandle), - curType, - reinterpret_cast(newHandle), - newType, - threadName, - threadId - ) + "+g+ grefc {} gwrefc {} obj-handle {:p}/{} -> new-handle {:p}/{} from thread '{}'({})", + c, + gc_weak_gref_count, + reinterpret_cast(curHandle), + curType, + reinterpret_cast(newHandle), + newType, + threadName, + threadId ); if (gref_to_logcat) { if (from_writable) { _write_stack_trace (nullptr, const_cast(from), LOG_GREF); } else { - log_info (LOG_GREF, std::format ("{}", from)); + log_info (LOG_GREF, "{}", from); } } if (!gref_log) @@ -263,20 +262,19 @@ OSBridge::_monodroid_gref_log_delete (jobject handle, char type, const char *thr if ((log_categories & LOG_GREF) == 0) return; log_info (LOG_GREF, - std::format ("-g- grefc {} gwrefc {} handle {:p}/{} from thread '{}'({})", - c, - gc_weak_gref_count, - reinterpret_cast(handle), - type, - threadName, - threadId - ) + "-g- grefc {} gwrefc {} handle {:p}/{} from thread '{}'({})", + c, + gc_weak_gref_count, + reinterpret_cast(handle), + type, + threadName, + threadId ); if (gref_to_logcat) { if (from_writable) { _write_stack_trace (nullptr, const_cast(from), LOG_GREF); } else { - log_info (LOG_GREF, std::format ("{}", from)); + log_info (LOG_GREF, "{}", from); } } if (!gref_log) @@ -303,22 +301,21 @@ OSBridge::_monodroid_weak_gref_new (jobject curHandle, char curType, jobject new if ((log_categories & LOG_GREF) == 0) return; log_info (LOG_GREF, - std::format ("+w+ grefc {} gwrefc {} obj-handle {:p}/{} -> new-handle {:p}/{} from thread '{}'({})", - gc_gref_count, - gc_weak_gref_count, - reinterpret_cast(curHandle), - curType, - reinterpret_cast(newHandle), - newType, - threadName, - threadId - ) + "+w+ grefc {} gwrefc {} obj-handle {:p}/{} -> new-handle {:p}/{} from thread '{}'({})", + gc_gref_count, + gc_weak_gref_count, + reinterpret_cast(curHandle), + curType, + reinterpret_cast(newHandle), + newType, + threadName, + threadId ); if (gref_to_logcat) { if (from_writable) { _write_stack_trace (nullptr, const_cast(from), LOG_GREF); } else { - log_info (LOG_GREF, std::format ("{}", from)); + log_info (LOG_GREF, "{}", from); } } if (!gref_log) @@ -347,20 +344,19 @@ OSBridge::_monodroid_weak_gref_delete (jobject handle, char type, const char *th if ((log_categories & LOG_GREF) == 0) return; log_info (LOG_GREF, - std::format ("-w- grefc {} gwrefc {} handle {:p}/{} from thread '{}'({})", - gc_gref_count, - gc_weak_gref_count, - reinterpret_cast(handle), - type, - threadName, - threadId - ) + "-w- grefc {} gwrefc {} handle {:p}/{} from thread '{}'({})", + gc_gref_count, + gc_weak_gref_count, + reinterpret_cast(handle), + type, + threadName, + threadId ); if (gref_to_logcat) { if (from_writable) { _write_stack_trace (nullptr, const_cast(from), LOG_GREF); } else { - log_info (LOG_GREF, std::format ("{}", from)); + log_info (LOG_GREF, "{}", from); } } if (!gref_log) @@ -386,19 +382,18 @@ OSBridge::_monodroid_lref_log_new (int lrefc, jobject handle, char type, const c if ((log_categories & LOG_LREF) == 0) return; log_info (LOG_LREF, - std::format ("+l+ lrefc {} handle {:p}/{} from thread '{}'({})", - lrefc, - reinterpret_cast(handle), - type, - threadName, - threadId - ) + "+l+ lrefc {} handle {:p}/{} from thread '{}'({})", + lrefc, + reinterpret_cast(handle), + type, + threadName, + threadId ); if (lref_to_logcat) { if (from_writable) { _write_stack_trace (nullptr, const_cast(from), LOG_GREF); } else { - log_info (LOG_GREF, std::format ("{}", from)); + log_info (LOG_GREF, "{}", from); } } if (!lref_log) @@ -423,19 +418,18 @@ OSBridge::_monodroid_lref_log_delete (int lrefc, jobject handle, char type, cons if ((log_categories & LOG_LREF) == 0) return; log_info (LOG_LREF, - std::format ("-l- lrefc {} handle {:p}/{} from thread '{}'({})", - lrefc, - reinterpret_cast(handle), - type, - threadName, - threadId - ) + "-l- lrefc {} handle {:p}/{} from thread '{}'({})", + lrefc, + reinterpret_cast(handle), + type, + threadName, + threadId ); if (lref_to_logcat) { if (from_writable) { _write_stack_trace (nullptr, const_cast(from), LOG_GREF); } else { - log_info (LOG_GREF, std::format ("{}", from)); + log_info (LOG_GREF, "{}", from); } } if (!lref_log) @@ -548,11 +542,9 @@ OSBridge::gc_bridge_class_kind (MonoClass *klass) i = get_gc_bridge_index (klass); if (i == static_cast (-NUM_GC_BRIDGE_TYPES)) { log_info (LOG_GC, - std::format ( - "asked if a class {}.{} is a bridge before we inited java.lang.Object", - mono_class_get_namespace (klass), - mono_class_get_name (klass) - ) + "asked if a class {}.{} is a bridge before we inited java.lang.Object", + mono_class_get_namespace (klass), + mono_class_get_name (klass) ); return MonoGCBridgeObjectKind::GC_BRIDGE_TRANSPARENT_CLASS; } @@ -578,11 +570,9 @@ OSBridge::gc_is_bridge_object (MonoObject *object) #if DEBUG MonoClass *mclass = mono_object_get_class (object); log_info (LOG_GC, - std::format ( - "object of class {}.{} with null handle", - mono_class_get_namespace (mclass), - mono_class_get_name (mclass) - ) + "object of class {}.{} with null handle", + mono_class_get_namespace (mclass), + mono_class_get_name (mclass) ); #endif return 0; @@ -669,9 +659,9 @@ OSBridge::add_reference (JNIEnv *env, OSBridge::AddReferenceTarget target, OSBri *reffed_description = describe_target (reffed_target); if (success) - log_warn (LOG_GC, std::format ("Added reference for {} to {}", description, reffed_description)); + log_warn (LOG_GC, "Added reference for {} to {}", description, reffed_description); else - log_error (LOG_GC, std::format ("Missing monodroidAddReference method for {}", description)); + log_error (LOG_GC, "Missing monodroidAddReference method for {}", description); free (description); free (reffed_description); @@ -908,11 +898,9 @@ OSBridge::gc_cleanup_after_java_collection (JNIEnv *env, int num_sccs, MonoGCBri if (Logger::gc_spew_enabled ()) { klass = mono_object_get_class (obj); log_error (LOG_GC, - std::format ( - "Missing monodroidClearReferences method for object of class {}.{}", - mono_class_get_namespace (klass), - mono_class_get_name (klass) - ) + "Missing monodroidClearReferences method for object of class {}.{}", + mono_class_get_namespace (klass), + mono_class_get_name (klass) ); } #endif @@ -927,7 +915,7 @@ OSBridge::gc_cleanup_after_java_collection (JNIEnv *env, int num_sccs, MonoGCBri } } #if DEBUG - log_info (LOG_GC, std::format ("GC cleanup summary: {} objects tested - resurrecting {}.", total, alive)); + log_info (LOG_GC, "GC cleanup summary: {} objects tested - resurrecting {}.", total, alive); #endif } @@ -957,10 +945,10 @@ OSBridge::gc_cross_references (int num_sccs, MonoGCBridgeSCC **sccs, int num_xre if (Logger::gc_spew_enabled ()) { int i, j; - log_info (LOG_GC, std::format ("cross references callback invoked with {} sccs and {} xrefs.", num_sccs, num_xrefs)); + log_info (LOG_GC, "cross references callback invoked with {} sccs and {} xrefs.", num_sccs, num_xrefs); for (i = 0; i < num_sccs; ++i) { - log_info (LOG_GC, std::format ("group {} with {} objects", i, sccs [i]->num_objs)); + log_info (LOG_GC, "group {} with {} objects", i, sccs [i]->num_objs); for (j = 0; j < sccs [i]->num_objs; ++j) { MonoObject *obj = sccs [i]->objs [j]; @@ -975,21 +963,19 @@ OSBridge::gc_cross_references (int num_sccs, MonoGCBridgeSCC **sccs, int num_xre } MonoClass *klass = mono_object_get_class (obj); log_info (LOG_GC, - std::format ( - "\tobj {:p} [{}::{}] handle {:p} key_handle {:p}", - reinterpret_cast(obj), - mono_class_get_namespace (klass), - mono_class_get_name (klass), - reinterpret_cast(handle), - key_handle - ) + "\tobj {:p} [{}::{}] handle {:p} key_handle {:p}", + reinterpret_cast(obj), + mono_class_get_namespace (klass), + mono_class_get_name (klass), + reinterpret_cast(handle), + key_handle ); } } if (Util::should_log (LOG_GC)) { for (i = 0; i < num_xrefs; ++i) - log_info_nocheck (LOG_GC, std::format ("xref [{}] {} -> {}", i, xrefs [i].src_scc_index, xrefs [i].dst_scc_index)); + log_info_nocheck_fmt (LOG_GC, "xref [{}] {} -> {}", i, xrefs [i].src_scc_index, xrefs [i].dst_scc_index); } } diff --git a/src/native/monodroid/xamarin-android-app-context.cc b/src/native/monodroid/xamarin-android-app-context.cc index e55635f2443..75973eb020e 100644 --- a/src/native/monodroid/xamarin-android-app-context.cc +++ b/src/native/monodroid/xamarin-android-app-context.cc @@ -15,7 +15,7 @@ MonodroidRuntime::get_method_name (uint32_t mono_image_index, uint32_t method_to { uint64_t id = (static_cast(mono_image_index) << 32) | method_token; - log_debug (LOG_ASSEMBLY, std::format ("MM: looking for name of method with id {:x}, in mono image at index {}", id, mono_image_index)); + log_debug (LOG_ASSEMBLY, "MM: looking for name of method with id {:x}, in mono image at index {}", id, mono_image_index); size_t i = 0uz; while (mm_method_names[i].id != 0) { if (mm_method_names[i].id == id) { @@ -43,10 +43,9 @@ MonodroidRuntime::get_function_pointer (uint32_t mono_image_index, uint32_t clas { log_debug ( LOG_ASSEMBLY, - std::format ("MM: Trying to look up pointer to method '{}' (token {:x}) in class '{}' (index {})", - get_method_name (mono_image_index, method_token), method_token, - get_class_name (class_index), class_index - ) + "MM: Trying to look up pointer to method '{}' (token {:x}) in class '{}' (index {})", + get_method_name (mono_image_index, method_token), method_token, + get_class_name (class_index), class_index ); if (class_index >= marshal_methods_number_of_classes) [[unlikely]] { @@ -81,32 +80,29 @@ MonodroidRuntime::get_function_pointer (uint32_t mono_image_index, uint32_t clas log_debug ( LOG_ASSEMBLY, - std::format ("Loaded pointer to method {} ({:p}) (mono_image_index == {}; class_index == {}; method_token == {:x})", - mono_method_full_name (method, true), - ret, - mono_image_index, - class_index, - method_token - ) + "Loaded pointer to method {} ({:p}) (mono_image_index == {}; class_index == {}; method_token == {:x})", + mono_method_full_name (method, true), + ret, + mono_image_index, + class_index, + method_token ); return; } log_fatal ( LOG_DEFAULT, - std::format ("Failed to obtain function pointer to method '{}' in class '{}'", - get_method_name (mono_image_index, method_token), - get_class_name (class_index) - ) + "Failed to obtain function pointer to method '{}' in class '{}'", + get_method_name (mono_image_index, method_token), + get_class_name (class_index) ); log_fatal ( LOG_DEFAULT, - std::format ("Looked for image index {}, class index {}, method token {:x}", - mono_image_index, - class_index, - method_token - ) + "Looked for image index {}, class index {}, method token {:x}", + mono_image_index, + class_index, + method_token ); if (image == nullptr) { diff --git a/src/native/monodroid/xamarin_getifaddrs.cc b/src/native/monodroid/xamarin_getifaddrs.cc index 99ba01039e6..57c4935a7bf 100644 --- a/src/native/monodroid/xamarin_getifaddrs.cc +++ b/src/native/monodroid/xamarin_getifaddrs.cc @@ -421,7 +421,7 @@ open_netlink_session (netlink_session *session) memset (session, 0, sizeof (*session)); session->sock_fd = socket (AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); if (session->sock_fd == -1) { - log_warn (LOG_NETLINK, std::format ("Failed to create a netlink socket. {}", strerror (errno))); + log_warn (LOG_NETLINK, "Failed to create a netlink socket. {}", strerror (errno)); return -1; } @@ -440,7 +440,7 @@ open_netlink_session (netlink_session *session) session->them.nl_family = AF_NETLINK; if (bind (session->sock_fd, (struct sockaddr *)&session->us, sizeof (session->us)) < 0) { - log_warn (LOG_NETLINK, std::format ("Failed to bind to the netlink socket. {}", strerror (errno))); + log_warn (LOG_NETLINK, "Failed to bind to the netlink socket. {}", strerror (errno)); return -1; } @@ -478,7 +478,7 @@ send_netlink_dump_request (netlink_session *session, int type) session->message_header.msg_iov = &session->payload_vector; if (sendmsg (session->sock_fd, (const struct msghdr*)&session->message_header, 0) < 0) { - log_warn (LOG_NETLINK, std::format ("Failed to send netlink message. {}", strerror (errno))); + log_warn (LOG_NETLINK, "Failed to send netlink message. {}", strerror (errno)); return -1; } @@ -529,7 +529,7 @@ parse_netlink_reply (netlink_session *session, struct _monodroid_ifaddrs **ifadd abort_if_invalid_pointer_argument (last_ifaddr, "last_ifaddr"); size_t buf_size = static_cast(getpagesize ()); - log_debug (LOG_NETLINK, std::format ("receive buffer size == {}", buf_size)); + log_debug (LOG_NETLINK, "receive buffer size == {}", buf_size); size_t alloc_size = Helpers::multiply_with_overflow_check (sizeof(*response), buf_size); response = (unsigned char*)malloc (alloc_size); @@ -551,10 +551,10 @@ parse_netlink_reply (netlink_session *session, struct _monodroid_ifaddrs **ifadd netlink_reply.msg_iov = &reply_vector; length = recvmsg (session->sock_fd, &netlink_reply, 0); - log_debug (LOG_NETLINK, std::format (" length == {}", (int)length)); + log_debug (LOG_NETLINK, " length == {}", (int)length); if (length < 0) { - log_debug (LOG_NETLINK, std::format ("Failed to receive reply from netlink. {}", strerror (errno))); + log_debug (LOG_NETLINK, "Failed to receive reply from netlink. {}", strerror (errno)); goto cleanup; } @@ -582,7 +582,7 @@ parse_netlink_reply (netlink_session *session, struct _monodroid_ifaddrs **ifadd break; for (current_message = (struct nlmsghdr*)response; current_message && NLMSG_OK (current_message, static_cast(length)); current_message = NLMSG_NEXT (current_message, length)) { - log_debug (LOG_NETLINK, std::format ("next message... (type: {})", current_message->nlmsg_type)); + log_debug (LOG_NETLINK, "next message... (type: {})", current_message->nlmsg_type); switch (current_message->nlmsg_type) { /* See rtnetlink.h */ case RTM_NEWLINK: @@ -611,7 +611,7 @@ parse_netlink_reply (netlink_session *session, struct _monodroid_ifaddrs **ifadd break; default: - log_debug (LOG_NETLINK, std::format (" message type: {}", current_message->nlmsg_type)); + log_debug (LOG_NETLINK, " message type: {}", current_message->nlmsg_type); break; } } @@ -634,7 +634,7 @@ fill_sa_address (struct sockaddr **sa, struct ifaddrmsg *net_address, void *rta_ case AF_INET: { struct sockaddr_in *sa4; if (rta_payload_length != 4) /* IPv4 address length */ { - log_warn (LOG_NETLINK, std::format ("Unexpected IPv4 address payload length {}", rta_payload_length)); + log_warn (LOG_NETLINK, "Unexpected IPv4 address payload length {}", rta_payload_length); return -1; } sa4 = (struct sockaddr_in*)calloc (1, sizeof (*sa4)); @@ -650,7 +650,7 @@ fill_sa_address (struct sockaddr **sa, struct ifaddrmsg *net_address, void *rta_ case AF_INET6: { struct sockaddr_in6 *sa6; if (rta_payload_length != 16) /* IPv6 address length */ { - log_warn (LOG_NETLINK, std::format ("Unexpected IPv6 address payload length {}", rta_payload_length)); + log_warn (LOG_NETLINK, "Unexpected IPv6 address payload length {}", rta_payload_length); return -1; } sa6 = (struct sockaddr_in6*)calloc (1, sizeof (*sa6)); @@ -668,7 +668,7 @@ fill_sa_address (struct sockaddr **sa, struct ifaddrmsg *net_address, void *rta_ default: { struct sockaddr *sagen; if (rta_payload_length > sizeof (sagen->sa_data)) { - log_warn (LOG_NETLINK, std::format ("Unexpected RTA payload length {} (wanted at most {})", rta_payload_length, sizeof (sagen->sa_data))); + log_warn (LOG_NETLINK, "Unexpected RTA payload length {} (wanted at most {})", rta_payload_length, sizeof (sagen->sa_data)); return -1; } @@ -701,9 +701,9 @@ fill_ll_address (struct sockaddr_ll_extended **sa, struct ifinfomsg *net_interfa /* The assert can only fail for Iniband links, which are quite unlikely to be found * in any mobile devices */ - log_debug (LOG_NETLINK, std::format ("rta_payload_length == {}; sizeof sll_addr == {}; hw type == {:x}", rta_payload_length, sizeof ((*sa)->sll_addr), net_interface->ifi_type)); + log_debug (LOG_NETLINK, "rta_payload_length == {}; sizeof sll_addr == {}; hw type == {:x}", rta_payload_length, sizeof ((*sa)->sll_addr), net_interface->ifi_type); if (static_cast(rta_payload_length) > sizeof ((*sa)->sll_addr)) { - log_info (LOG_NETLINK, std::format ("Address is too long to place in sockaddr_ll ({} > {})", rta_payload_length, sizeof ((*sa)->sll_addr))); + log_info (LOG_NETLINK, "Address is too long to place in sockaddr_ll ({} > {})", rta_payload_length, sizeof ((*sa)->sll_addr)); free (*sa); *sa = NULL; return -1; @@ -817,14 +817,14 @@ calculate_address_netmask (struct _monodroid_ifaddrs *ifa, struct ifaddrmsg *net memset (netmask_data, 0xFF, prefix_bytes); if (postfix_bytes > 0) memset (netmask_data + prefix_bytes + 1, 0x00, postfix_bytes); - log_debug (LOG_NETLINK, std::format (" calculating netmask, prefix length is {} bits ({} bytes), data length is {} bytes\n", prefix_length, prefix_bytes, data_length)); + log_debug (LOG_NETLINK, " calculating netmask, prefix length is {} bits ({} bytes), data length is {} bytes\n", prefix_length, prefix_bytes, data_length); if (prefix_bytes + 2 < data_length) /* Set the rest of the mask bits in the byte following the last 0xFF value */ netmask_data [prefix_bytes + 1] = static_cast(0xff << (8 - (prefix_length % 8))); if (Util::should_log (LOG_NETLINK)) { log_debug_nocheck (LOG_NETLINK, " netmask is: "sv); for (uint32_t i = 0; i < data_length; i++) { - log_debug_nocheck (LOG_NETLINK, std::format ("{}{}", i == 0 ? " "sv : "."sv, (unsigned char)ifa->ifa_netmask->sa_data [i])); + log_debug_nocheck_fmt (LOG_NETLINK, "{}{}", i == 0 ? " "sv : "."sv, (unsigned char)ifa->ifa_netmask->sa_data [i]); } } } @@ -847,7 +847,7 @@ get_link_address (const struct nlmsghdr *message, struct _monodroid_ifaddrs **if abort_if_invalid_pointer_argument (message, "message"); net_address = reinterpret_cast (NLMSG_DATA (message)); length = static_cast(IFA_PAYLOAD (message)); - log_debug (LOG_NETLINK, std::format (" address data length: {}", length)); + log_debug (LOG_NETLINK, " address data length: {}", length); if (length <= 0) { goto error; } @@ -864,7 +864,7 @@ get_link_address (const struct nlmsghdr *message, struct _monodroid_ifaddrs **if log_debug (LOG_NETLINK, " reading attributes"sv); while (RTA_OK (attribute, length)) { payload_size = RTA_PAYLOAD (attribute); - log_debug (LOG_NETLINK, std::format (" attribute payload_size == {}", payload_size)); + log_debug (LOG_NETLINK, " attribute payload_size == {}", payload_size); sa = NULL; switch (attribute->rta_type) { @@ -943,7 +943,7 @@ get_link_address (const struct nlmsghdr *message, struct _monodroid_ifaddrs **if break; default: - log_debug (LOG_NETLINK, std::format (" attribute type: {}", attribute->rta_type)); + log_debug (LOG_NETLINK, " attribute type: {}", attribute->rta_type); break; } @@ -962,7 +962,7 @@ get_link_address (const struct nlmsghdr *message, struct _monodroid_ifaddrs **if log_debug (LOG_NETLINK, " address has no name/label, getting one from interface"sv); ifa->ifa_name = name ? strdup (name) : NULL; } - log_debug (LOG_NETLINK, std::format (" address label: {}", ifa->ifa_name)); + log_debug (LOG_NETLINK, " address label: {}", ifa->ifa_name); if (calculate_address_netmask (ifa, net_address) < 0) { goto error; @@ -1016,13 +1016,13 @@ get_link_info (const struct nlmsghdr *message) goto error; } if (Util::should_log (LOG_NETLINK)) { - log_debug_nocheck (LOG_NETLINK, std::format (" interface name (payload length: {}; string length: {})", RTA_PAYLOAD (attribute), strlen (ifa->ifa_name))); - log_debug_nocheck (LOG_NETLINK, std::format (" {}", ifa->ifa_name)); + log_debug_nocheck_fmt (LOG_NETLINK, " interface name (payload length: {}; string length: {})", RTA_PAYLOAD (attribute), strlen (ifa->ifa_name)); + log_debug_nocheck_fmt (LOG_NETLINK, " {}", ifa->ifa_name); } break; case IFLA_BROADCAST: - log_debug (LOG_NETLINK, std::format (" interface broadcast ({} bytes)", RTA_PAYLOAD (attribute))); + log_debug (LOG_NETLINK, " interface broadcast ({} bytes)", RTA_PAYLOAD (attribute)); if (fill_ll_address (&sa, net_interface, RTA_DATA (attribute), RTA_PAYLOAD (attribute)) < 0) { goto error; } @@ -1030,7 +1030,7 @@ get_link_info (const struct nlmsghdr *message) break; case IFLA_ADDRESS: - log_debug (LOG_NETLINK, std::format (" interface address ({} bytes)", RTA_PAYLOAD (attribute))); + log_debug (LOG_NETLINK, " interface address ({} bytes)", RTA_PAYLOAD (attribute)); if (fill_ll_address (&sa, net_interface, RTA_DATA (attribute), RTA_PAYLOAD (attribute)) < 0) { goto error; } @@ -1047,7 +1047,7 @@ get_link_info (const struct nlmsghdr *message) attribute = RTA_NEXT (attribute, length); } - log_debug (LOG_NETLINK, std::format ("link flags: {:X}", ifa->ifa_flags)); + log_debug (LOG_NETLINK, "link flags: {:X}", ifa->ifa_flags); return ifa; error: @@ -1142,7 +1142,7 @@ print_ifla_name (int id) int i = 0; while (1) { if (iflas [i].value == -1 && iflas [i].name == 0) { - log_info_nocheck (LOG_NETLINK, std::format ("Unknown ifla->name: unknown id {}", id)); + log_info_nocheck_fmt (LOG_NETLINK, "Unknown ifla->name: unknown id {}", id); break; } @@ -1150,7 +1150,7 @@ print_ifla_name (int id) i++; continue; } - log_info_nocheck (LOG_NETLINK, std::format ("ifla->name: {} ({})", iflas [i].name, iflas [i].value)); + log_info_nocheck_fmt (LOG_NETLINK, "ifla->name: {} ({})", iflas [i].name, iflas [i].value); break; } } @@ -1165,7 +1165,7 @@ print_address_list (const char title[], struct _monodroid_ifaddrs *list) char *msg, *tmp; if (!list) { - log_info_nocheck (LOG_NETLINK, std::format ("No list to print in {}", __FUNCTION__)); + log_info_nocheck_fmt (LOG_NETLINK, "No list to print in {}", __FUNCTION__); return; } @@ -1180,7 +1180,7 @@ print_address_list (const char title[], struct _monodroid_ifaddrs *list) cur = cur->ifa_next; } - log_info_nocheck (LOG_NETLINK, std::format ("{}: {}", title, msg ? msg : "[no addresses]"sv)); + log_info_nocheck_fmt (LOG_NETLINK, "{}: {}", title, msg ? msg : "[no addresses]"sv); free (msg); } #endif diff --git a/src/native/pinvoke-override/pinvoke-override-api-impl.hh b/src/native/pinvoke-override/pinvoke-override-api-impl.hh index 240223b396c..f6c402c46e7 100644 --- a/src/native/pinvoke-override/pinvoke-override-api-impl.hh +++ b/src/native/pinvoke-override/pinvoke-override-api-impl.hh @@ -23,21 +23,21 @@ namespace xamarin::android { constexpr bool PREFER_AOT_CACHE = false; lib_handle = internal::MonodroidDl::monodroid_dlopen (library_name, MONO_DL_LOCAL, nullptr, PREFER_AOT_CACHE); if (lib_handle == nullptr) { - log_warn (LOG_ASSEMBLY, std::format ("Shared library '{}' not loaded, p/invoke '{}' may fail", library_name, symbol_name)); + log_warn (LOG_ASSEMBLY, "Shared library '{}' not loaded, p/invoke '{}' may fail", library_name, symbol_name); return nullptr; } if (dso_handle != nullptr) { void *expected_null = nullptr; if (!__atomic_compare_exchange (dso_handle, &expected_null, &lib_handle, false /* weak */, __ATOMIC_ACQUIRE /* success_memorder */, __ATOMIC_RELAXED /* xxxfailure_memorder */)) { - log_debug (LOG_ASSEMBLY, std::format ("Library '{}' handle already cached by another thread", library_name)); + log_debug (LOG_ASSEMBLY, "Library '{}' handle already cached by another thread", library_name); } } } void *entry_handle = internal::MonodroidDl::monodroid_dlsym (lib_handle, symbol_name, nullptr, nullptr); if (entry_handle == nullptr) { - log_warn (LOG_ASSEMBLY, std::format ("Symbol '{}' not found in shared library '{}', p/invoke may fail", symbol_name, library_name)); + log_warn (LOG_ASSEMBLY, "Symbol '{}' not found in shared library '{}', p/invoke may fail", symbol_name, library_name); return nullptr; } @@ -60,7 +60,7 @@ namespace xamarin::android { return nullptr; } - log_debug (LOG_ASSEMBLY, std::format ("Caching p/invoke entry {} @ {}", library_name, entrypoint_name)); + log_debug (LOG_ASSEMBLY, "Caching p/invoke entry {} @ {}", library_name, entrypoint_name); (*api_map)[entrypoint_name] = entry_handle; return entry_handle; } @@ -81,7 +81,7 @@ namespace xamarin::android { ); if (already_loaded) { - log_debug (LOG_ASSEMBLY, std::format ("Entry '{}' from library '{}' already loaded by another thread", entrypoint_name, library_name)); + log_debug (LOG_ASSEMBLY, "Entry '{}' from library '{}' already loaded by another thread", entrypoint_name, library_name); } } @@ -147,7 +147,7 @@ namespace xamarin::android { handle = fetch_or_create_pinvoke_map_entry (lib_name, entry_name, entrypoint_name_hash, lib_map, /* need_lock */ false); } else { if (iter->second == nullptr) [[unlikely]] { - log_warn (LOG_ASSEMBLY, std::format ("Internal error: null entry in p/invoke map for key '{}'", library_name)); + log_warn (LOG_ASSEMBLY, "Internal error: null entry in p/invoke map for key '{}'", library_name); return nullptr; // fall back to `monodroid_dlopen` } diff --git a/src/native/pinvoke-override/precompiled.cc b/src/native/pinvoke-override/precompiled.cc index 1ef4bbfaba0..e5c54608ff3 100644 --- a/src/native/pinvoke-override/precompiled.cc +++ b/src/native/pinvoke-override/precompiled.cc @@ -22,11 +22,11 @@ PinvokeOverride::monodroid_pinvoke_override (const char *library_name, const cha PinvokeEntry *entry = find_pinvoke_address (entrypoint_hash, internal_pinvokes.data (), internal_pinvokes_count); if (entry == nullptr) [[unlikely]] { - log_fatal (LOG_ASSEMBLY, std::format ("Internal p/invoke symbol '{} @ {}' (hash: {:x}) not found in compile-time map.", library_name, entrypoint_name, entrypoint_hash)); + log_fatal (LOG_ASSEMBLY, "Internal p/invoke symbol '{} @ {}' (hash: {:x}) not found in compile-time map.", library_name, entrypoint_name, entrypoint_hash); log_fatal (LOG_ASSEMBLY, "compile-time map contents:"sv); for (size_t i = 0uz; i < internal_pinvokes_count; i++) { PinvokeEntry const& e = internal_pinvokes[i]; - log_fatal (LOG_ASSEMBLY, std::format ("\t'{}'={:p} (hash: {:x})", e.name, e.func, e.hash)); + log_fatal (LOG_ASSEMBLY, "\t'{}'={:p} (hash: {:x})", e.name, e.func, e.hash); } Helpers::abort_application ( LOG_ASSEMBLY, @@ -67,7 +67,7 @@ PinvokeOverride::monodroid_pinvoke_override (const char *library_name, const cha load_library_entry (library_name, entrypoint_name, *entry, dotnet_dso_handle); if (entry->func == nullptr) { - log_fatal (LOG_ASSEMBLY, std::format ("Failed to load symbol '{}' from shared library '{}'", entrypoint_name, library_name)); + log_fatal (LOG_ASSEMBLY, "Failed to load symbol '{}' from shared library '{}'", entrypoint_name, library_name); return nullptr; // let Mono deal with the fallout } @@ -75,7 +75,7 @@ PinvokeOverride::monodroid_pinvoke_override (const char *library_name, const cha } // It's possible we don't have an entry for some `dotnet` p/invoke, fall back to the slow path below - log_debug (LOG_ASSEMBLY, std::format ("Symbol '{}' in library '{}' not found in the generated tables, falling back to slow path", entrypoint_name, library_name)); + log_debug (LOG_ASSEMBLY, "Symbol '{}' in library '{}' not found in the generated tables, falling back to slow path", entrypoint_name, library_name); } return handle_other_pinvoke_request (library_name, library_name_hash, entrypoint_name, entrypoint_hash); diff --git a/src/native/runtime-base/android-system.cc b/src/native/runtime-base/android-system.cc index 9119fe783a1..d3c8b2c56e4 100644 --- a/src/native/runtime-base/android-system.cc +++ b/src/native/runtime-base/android-system.cc @@ -65,7 +65,7 @@ AndroidSystem::lookup_system_property (const char *name, size_t &value_len) noex return nullptr; if (application_config.system_property_count % 2 != 0) { - log_warn (LOG_DEFAULT, std::format ("Corrupted environment variable array: does not contain an even number of entries ({})", application_config.system_property_count)); + log_warn (LOG_DEFAULT, "Corrupted environment variable array: does not contain an even number of entries ({})", application_config.system_property_count); return nullptr; } @@ -138,7 +138,7 @@ AndroidSystem::_monodroid__system_property_get (const char *name, char *sp_value char *buf = nullptr; if (sp_value_len < PROPERTY_VALUE_BUFFER_LEN) { size_t alloc_size = Helpers::add_with_overflow_check (PROPERTY_VALUE_BUFFER_LEN, 1uz); - log_warn (LOG_DEFAULT, std::format ("Buffer to store system property may be too small, will copy only {} bytes", sp_value_len)); + log_warn (LOG_DEFAULT, "Buffer to store system property may be too small, will copy only {} bytes", sp_value_len); buf = new char [alloc_size]; } @@ -250,12 +250,12 @@ AndroidSystem::monodroid_get_system_property_from_overrides ([[maybe_unused]] co } std::unique_ptr override_file {Util::path_combine (od, name)}; - log_info (LOG_DEFAULT, std::format ("Trying to get property from {}", override_file.get ())); + log_info (LOG_DEFAULT, "Trying to get property from {}", override_file.get ()); size_t result = _monodroid_get_system_property_from_file (override_file.get (), value); if (result == 0 || value == nullptr || (*value) == nullptr || **value == '\0') { continue; } - log_info (LOG_DEFAULT, std::format ("Property '{}' from {} has value '{}'.", name, od, *value)); + log_info (LOG_DEFAULT, "Property '{}' from {} has value '{}'.", name, od, *value); return result; } #endif // def DEBUG @@ -281,7 +281,7 @@ AndroidSystem::create_update_dir (char *override_dir) noexcept override_dirs [0] = override_dir; Util::create_public_directory (override_dir); - log_warn (LOG_DEFAULT, std::format ("Creating public update directory: `{}`", override_dir)); + log_warn (LOG_DEFAULT, "Creating public update directory: `{}`", override_dir); } bool @@ -306,16 +306,16 @@ AndroidSystem::load_dso (const char *path, unsigned int dl_flags, bool skip_exis if (path == nullptr || *path == '\0') return nullptr; - log_info (LOG_ASSEMBLY, std::format ("Trying to load shared library '{}'", path)); + log_info (LOG_ASSEMBLY, "Trying to load shared library '{}'", path); if (!skip_exists_check && !is_embedded_dso_mode_enabled () && !Util::file_exists (path)) { - log_info (LOG_ASSEMBLY, std::format ("Shared library '{}' not found", path)); + log_info (LOG_ASSEMBLY, "Shared library '{}' not found", path); return nullptr; } char *error = nullptr; void *handle = java_interop_lib_load (path, dl_flags, &error); if (handle == nullptr && Util::should_log (LOG_ASSEMBLY)) - log_info_nocheck (LOG_ASSEMBLY, std::format ("Failed to load shared library '{}'. {}", path, error)); + log_info_nocheck (LOG_ASSEMBLY, "Failed to load shared library '{}'. {}", path, error); java_interop_free (error); return handle; } @@ -450,9 +450,9 @@ AndroidSystem::get_max_gref_count_from_system (void) noexcept if (max < 0) max = std::numeric_limits::max (); if (*e) { - log_warn (LOG_GC, std::format ("Unsupported '{}' value '{}'.", SharedConstants::DEBUG_MONO_MAX_GREFC.data (), override.get ())); + log_warn (LOG_GC, "Unsupported '{}' value '{}'.", SharedConstants::DEBUG_MONO_MAX_GREFC.data (), override.get ()); } - log_warn (LOG_GC, std::format ("Overriding max JNI Global Reference count to {}", max)); + log_warn (LOG_GC, "Overriding max JNI Global Reference count to {}", max); } return max; } @@ -478,7 +478,7 @@ AndroidSystem::setup_environment (const char *name, const char *value) noexcept if (isupper (name [0]) || name [0] == '_') { if (setenv (name, v, 1) < 0) - log_warn (LOG_DEFAULT, std::format ("(Debug) Failed to set environment variable: {}", strerror (errno))); + log_warn (LOG_DEFAULT, "(Debug) Failed to set environment variable: {}", strerror (errno)); return; } @@ -492,13 +492,13 @@ AndroidSystem::setup_environment_from_override_file (const char *path) noexcept struct stat sbuf; if (::stat (path, &sbuf) < 0) { - log_warn (LOG_DEFAULT, std::format ("Failed to stat the environment override file {}: {}", path, strerror (errno))); + log_warn (LOG_DEFAULT, "Failed to stat the environment override file {}: {}", path, strerror (errno)); return; } int fd = open (path, O_RDONLY); if (fd < 0) { - log_warn (LOG_DEFAULT, std::format ("Failed to open the environment override file {}: {}", path, strerror (errno))); + log_warn (LOG_DEFAULT, "Failed to open the environment override file {}: {}", path, strerror (errno)); return; } @@ -515,7 +515,7 @@ AndroidSystem::setup_environment_from_override_file (const char *path) noexcept } while (r < 0 && errno == EINTR); if (nread == 0) { - log_warn (LOG_DEFAULT, std::format ("Failed to read the environment override file {}: {}", path, strerror (errno))); + log_warn (LOG_DEFAULT, "Failed to read the environment override file {}: {}", path, strerror (errno)); return; } @@ -536,26 +536,26 @@ AndroidSystem::setup_environment_from_override_file (const char *path) noexcept // # Variable value, terminated with NUL and padded to [value width] with NUL characters // value\0 if (nread < OVERRIDE_ENVIRONMENT_FILE_HEADER_SIZE) { - log_warn (LOG_DEFAULT, std::format ("Invalid format of the environment override file {}: malformatted header", path)); + log_warn (LOG_DEFAULT, "Invalid format of the environment override file {}: malformatted header", path); return; } char *endptr; unsigned long name_width = strtoul (buf.get (), &endptr, 16); if ((name_width == std::numeric_limits::max () && errno == ERANGE) || (buf[0] != '\0' && *endptr != '\0')) { - log_warn (LOG_DEFAULT, std::format ("Malformed header of the environment override file {}: name width has invalid format", path)); + log_warn (LOG_DEFAULT, "Malformed header of the environment override file {}: name width has invalid format", path); return; } unsigned long value_width = strtoul (buf.get () + 11, &endptr, 16); if ((value_width == std::numeric_limits::max () && errno == ERANGE) || (buf[0] != '\0' && *endptr != '\0')) { - log_warn (LOG_DEFAULT, std::format ("Malformed header of the environment override file {}: value width has invalid format", path)); + log_warn (LOG_DEFAULT, "Malformed header of the environment override file {}: value width has invalid format", path); return; } uint64_t data_width = name_width + value_width; if (data_width > file_size - OVERRIDE_ENVIRONMENT_FILE_HEADER_SIZE || (file_size - OVERRIDE_ENVIRONMENT_FILE_HEADER_SIZE) % data_width != 0) { - log_warn (LOG_DEFAULT, std::format ("Malformed environment override file {}: invalid data size", path)); + log_warn (LOG_DEFAULT, "Malformed environment override file {}: invalid data size", path); return; } @@ -563,11 +563,11 @@ AndroidSystem::setup_environment_from_override_file (const char *path) noexcept char *name = buf.get () + OVERRIDE_ENVIRONMENT_FILE_HEADER_SIZE; while (data_size > 0 && data_size >= data_width) { if (*name == '\0') { - log_warn (LOG_DEFAULT, std::format ("Malformed environment override file {}: name at offset {} is empty", path, name - buf.get ())); + log_warn (LOG_DEFAULT, "Malformed environment override file {}: name at offset {} is empty", path, name - buf.get ()); return; } - log_debug (LOG_DEFAULT, std::format ("Setting environment variable from the override file {}: '{}' = '{}'", path, name, name + name_width)); + log_debug (LOG_DEFAULT, "Setting environment variable from the override file {}: '{}' = '{}'", path, name, name + name_width); setup_environment (name, name + name_width); name += data_width; data_size -= data_width; @@ -602,10 +602,10 @@ AndroidSystem::setup_environment () noexcept } if (aotMode != MonoAotMode::MONO_AOT_MODE_LAST) { - log_debug (LOG_DEFAULT, std::format ("Mono AOT mode: {}", mono_aot_mode_name)); + log_debug (LOG_DEFAULT, "Mono AOT mode: {}", mono_aot_mode_name); } else { if (!is_interpreter_enabled ()) { - log_warn (LOG_DEFAULT, std::format ("Unknown Mono AOT mode: {}", mono_aot_mode_name)); + log_warn (LOG_DEFAULT, "Unknown Mono AOT mode: {}", mono_aot_mode_name); } else { log_warn (LOG_DEFAULT, "Mono AOT mode: interpreter"sv); } @@ -613,7 +613,7 @@ AndroidSystem::setup_environment () noexcept } if (application_config.environment_variable_count % 2 != 0) { - log_warn (LOG_DEFAULT, std::format ("Corrupted environment variable array: does not contain an even number of entries ({})", application_config.environment_variable_count)); + log_warn (LOG_DEFAULT, "Corrupted environment variable array: does not contain an even number of entries ({})", application_config.environment_variable_count); return; } @@ -629,10 +629,10 @@ AndroidSystem::setup_environment () noexcept var_value = ""; #if defined (DEBUG) - log_info (LOG_DEFAULT, std::format ("Setting environment variable '{}' to '{}'", var_name, var_value)); + log_info (LOG_DEFAULT, "Setting environment variable '{}' to '{}'", var_name, var_value); #endif // def DEBUG if (setenv (var_name, var_value, 1) < 0) - log_warn (LOG_DEFAULT, std::format ("Failed to set environment variable: {}", strerror (errno))); + log_warn (LOG_DEFAULT, "Failed to set environment variable: {}", strerror (errno)); } #if defined (DEBUG) log_debug (LOG_DEFAULT, "Loading environment from override directories."sv); @@ -641,9 +641,9 @@ AndroidSystem::setup_environment () noexcept continue; } std::unique_ptr env_override_file {Util::path_combine (od, OVERRIDE_ENVIRONMENT_FILE_NAME.data ())}; - log_debug (LOG_DEFAULT, std::format ("{}", env_override_file.get ())); + log_debug (LOG_DEFAULT, "{}", env_override_file.get ()); if (Util::file_exists (env_override_file.get ())) { - log_debug (LOG_DEFAULT, std::format ("Loading {}", env_override_file.get ())); + log_debug (LOG_DEFAULT, "Loading {}", env_override_file.get ()); setup_environment_from_override_file (env_override_file.get ()); } } @@ -671,12 +671,12 @@ AndroidSystem::detect_embedded_dso_mode (jstring_array_wrapper& appDirs) noexcep { // appDirs[SharedConstants::APP_DIRS_DATA_DIR_INDEX] points to the native library directory std::unique_ptr libmonodroid_path {Util::path_combine (appDirs[SharedConstants::APP_DIRS_DATA_DIR_INDEX].get_cstr (), "libmonodroid.so")}; - log_debug (LOG_ASSEMBLY, std::format ("Checking if libmonodroid was unpacked to {}", libmonodroid_path.get ())); + log_debug (LOG_ASSEMBLY, "Checking if libmonodroid was unpacked to {}", libmonodroid_path.get ()); if (!Util::file_exists (libmonodroid_path.get ())) { - log_debug (LOG_ASSEMBLY, std::format ("{} not found, assuming application/android:extractNativeLibs == false", libmonodroid_path.get ())); + log_debug (LOG_ASSEMBLY, "{} not found, assuming application/android:extractNativeLibs == false", libmonodroid_path.get ()); set_embedded_dso_mode_enabled (true); } else { - log_debug (LOG_ASSEMBLY, std::format ("Native libs extracted to {}, assuming application/android:extractNativeLibs == true", appDirs[SharedConstants::APP_DIRS_DATA_DIR_INDEX].get_cstr ())); + log_debug (LOG_ASSEMBLY, "Native libs extracted to {}, assuming application/android:extractNativeLibs == true", appDirs[SharedConstants::APP_DIRS_DATA_DIR_INDEX].get_cstr ()); set_embedded_dso_mode_enabled (false); } } @@ -689,7 +689,7 @@ AndroidSystem::setup_app_library_directories (jstring_array_wrapper& runtimeApks AndroidSystem::app_lib_directories = std::span (single_app_lib_directory); AndroidSystem::app_lib_directories [0] = Util::strdup_new (appDirs[SharedConstants::APP_DIRS_DATA_DIR_INDEX].get_cstr ()); - log_debug (LOG_ASSEMBLY, std::format ("Added filesystem DSO lookup location: {}", appDirs[SharedConstants::APP_DIRS_DATA_DIR_INDEX].get_cstr ())); + log_debug (LOG_ASSEMBLY, "Added filesystem DSO lookup location: {}", appDirs[SharedConstants::APP_DIRS_DATA_DIR_INDEX].get_cstr ()); } else { log_debug (LOG_DEFAULT, "Setting up for DSO lookup directly in the APK"sv); @@ -725,7 +725,7 @@ AndroidSystem::add_apk_libdir (const char *apk, size_t &index, const char *abi) { abort_unless (index < app_lib_directories.size (), "Index out of range"); app_lib_directories [index] = Util::string_concat (apk, "!/lib/", abi); - log_debug (LOG_ASSEMBLY, std::format ("Added APK DSO lookup location: {}", app_lib_directories[index])); + log_debug (LOG_ASSEMBLY, "Added APK DSO lookup location: {}", app_lib_directories[index]); index++; } diff --git a/src/native/runtime-base/logger.cc b/src/native/runtime-base/logger.cc index cc2f2133a97..a331d7112bb 100644 --- a/src/native/runtime-base/logger.cc +++ b/src/native/runtime-base/logger.cc @@ -12,6 +12,7 @@ #include "android-system.hh" #include "cpp-util.hh" +#include "log_level.hh" #include "logger.hh" #include "shared-constants.hh" #include "util.hh" diff --git a/src/native/runtime-base/monodroid-dl.hh b/src/native/runtime-base/monodroid-dl.hh index 43e1b891a0e..4c3df81e077 100644 --- a/src/native/runtime-base/monodroid-dl.hh +++ b/src/native/runtime-base/monodroid-dl.hh @@ -48,11 +48,11 @@ namespace xamarin::android::internal size_t arr_size; if constexpr (WhichCache == CacheKind::AOT) { - log_debug (LOG_ASSEMBLY, std::format ("Looking for hash {:x} in AOT cache", hash)); + log_debug (LOG_ASSEMBLY, "Looking for hash {:x} in AOT cache", hash); arr = aot_dso_cache; arr_size = application_config.number_of_aot_cache_entries; } else if constexpr (WhichCache == CacheKind::DSO) { - log_debug (LOG_ASSEMBLY, std::format ("Looking for hash {:x} in DSO cache", hash)); + log_debug (LOG_ASSEMBLY, "Looking for hash {:x} in DSO cache", hash); arr = dso_cache; arr_size = application_config.number_of_dso_cache_entries; } @@ -102,7 +102,7 @@ namespace xamarin::android::internal if (MonodroidState::is_startup_in_progress ()) { auto ignore_component = [&](const char *label, MonoComponent component) -> bool { if ((application_config.mono_components_mask & component) != component) { - log_info (LOG_ASSEMBLY, std::format ("Mono '{}' component requested but not packaged, ignoring", label)); + log_info (LOG_ASSEMBLY, "Mono '{}' component requested but not packaged, ignoring", label); return true; } @@ -150,7 +150,7 @@ namespace xamarin::android::internal } hash_t name_hash = xxhash::hash (name, strlen (name)); - log_debug (LOG_ASSEMBLY, std::format ("monodroid_dlopen: hash for name '{}' is {:x}", name, name_hash)); + log_debug (LOG_ASSEMBLY, "monodroid_dlopen: hash for name '{}' is {:x}", name, name_hash); DSOCacheEntry *dso = nullptr; if (prefer_aot_cache) { @@ -167,7 +167,7 @@ namespace xamarin::android::internal dso = find_only_dso_cache_entry (name_hash); } - log_debug (LOG_ASSEMBLY, std::format ("monodroid_dlopen: hash match {}found, DSO name is '{}'", dso == nullptr ? "not "sv : ""sv, dso == nullptr ? ""sv : dso->name)); + log_debug (LOG_ASSEMBLY, "monodroid_dlopen: hash match {}found, DSO name is '{}'", dso == nullptr ? "not "sv : ""sv, dso == nullptr ? ""sv : dso->name); if (dso == nullptr) { // DSO not known at build time, try to load it @@ -177,7 +177,7 @@ namespace xamarin::android::internal } if (dso->ignore) { - log_info (LOG_ASSEMBLY, std::format ("Request to load '{}' ignored, it is known not to exist", dso->name)); + log_info (LOG_ASSEMBLY, "Request to load '{}' ignored, it is known not to exist", dso->name); return nullptr; } diff --git a/src/native/runtime-base/strings.hh b/src/native/runtime-base/strings.hh index 393a3783525..65f6603e501 100644 --- a/src/native/runtime-base/strings.hh +++ b/src/native/runtime-base/strings.hh @@ -156,7 +156,7 @@ namespace xamarin::android::internal } if (!can_access (start_index)) { - log_error (LOG_DEFAULT, std::format ("Cannot convert string to integer, index {} is out of range", start_index)); + log_error (LOG_DEFAULT, "Cannot convert string to integer, index {} is out of range", start_index); return false; } @@ -180,17 +180,17 @@ namespace xamarin::android::internal } if (out_of_range || errno == ERANGE) { - log_error (LOG_DEFAULT, std::format ("Value {} is out of range of this type ({}..{})", reinterpret_cast(s), static_cast(min), static_cast(max))); + log_error (LOG_DEFAULT, "Value {} is out of range of this type ({}..{})", reinterpret_cast(s), static_cast(min), static_cast(max)); return false; } if (endp == s) { - log_error (LOG_DEFAULT, std::format ("Value {} does not represent a base {} integer", reinterpret_cast(s), base)); + log_error (LOG_DEFAULT, "Value {} does not represent a base {} integer", reinterpret_cast(s), base); return false; } if (*endp != '\0') { - log_error (LOG_DEFAULT, std::format ("Value {} has non-numeric characters at the end", reinterpret_cast(s))); + log_error (LOG_DEFAULT, "Value {} has non-numeric characters at the end", reinterpret_cast(s)); return false; } diff --git a/src/native/runtime-base/timing-internal.cc b/src/native/runtime-base/timing-internal.cc index 7b23705d880..6efcfdae461 100644 --- a/src/native/runtime-base/timing-internal.cc +++ b/src/native/runtime-base/timing-internal.cc @@ -78,11 +78,11 @@ FastTiming::dump () noexcept log_write (LOG_TIMING, LogLevel::Info, "[2/4] Accumulated performance results"); ns_to_time (total_assembly_load_time, sec, ms, ns); - log_info_nocheck (LOG_TIMING, std::format (" [2/5] Assembly load: {}:{}::{}", sec, ms, ns)); + log_info_nocheck (LOG_TIMING, " [2/5] Assembly load: {}:{}::{}", sec, ms, ns); ns_to_time (total_java_to_managed_time, sec, ms, ns); - log_info_nocheck (LOG_TIMING, std::format (" [2/6] Java to Managed lookup: {}:{}::{}", sec, ms, ns)); + log_info_nocheck (LOG_TIMING, " [2/6] Java to Managed lookup: {}:{}::{}", sec, ms, ns); ns_to_time (total_managed_to_java_time, sec, ms, ns); - log_info_nocheck (LOG_TIMING, std::format (" [2/7] Managed to Java lookup: {}:{}::{}", sec, ms, ns)); + log_info_nocheck (LOG_TIMING, " [2/7] Managed to Java lookup: {}:{}::{}", sec, ms, ns); } diff --git a/src/native/runtime-base/timing-internal.hh b/src/native/runtime-base/timing-internal.hh index 27cc6da274f..d87595ac9bd 100644 --- a/src/native/runtime-base/timing-internal.hh +++ b/src/native/runtime-base/timing-internal.hh @@ -144,7 +144,7 @@ namespace xamarin::android::internal // likely we'll run out of memory way, way, way before that happens size_t old_size = events.capacity (); events.reserve (old_size << 1); - log_warn (LOG_TIMING, std::format ("Reallocated timing event buffer from {} to {}", old_size, events.size ())); + log_warn (LOG_TIMING, "Reallocated timing event buffer from {} to {}", old_size, events.size ()); } } @@ -246,7 +246,7 @@ namespace xamarin::android::internal force_inline bool is_valid_event_index (size_t index, const char *method_name) noexcept { if (index >= events.capacity ()) [[unlikely]] { - log_warn (LOG_TIMING, std::format ("Invalid event index passed to method '{}'", method_name)); + log_warn (LOG_TIMING, "Invalid event index passed to method '{}'", method_name); return false; } diff --git a/src/native/runtime-base/timing.hh b/src/native/runtime-base/timing.hh index 31f9892e918..191ec55df2f 100644 --- a/src/native/runtime-base/timing.hh +++ b/src/native/runtime-base/timing.hh @@ -93,14 +93,14 @@ namespace xamarin::android { timing_diff diff (period); - log_info_nocheck (LOG_TIMING, std::format (MESSAGE_FORMAT, message == nullptr ? ""sv : message, diff.sec, diff.ms, diff.ns)); + log_info_nocheck (LOG_TIMING, MESSAGE_FORMAT.data (), message == nullptr ? ""sv : message, diff.sec, diff.ms, diff.ns); } static void warn (timing_period const &period, const char *message) noexcept { timing_diff diff (period); - log_warn (LOG_TIMING, std::format (MESSAGE_FORMAT, message == nullptr ? ""sv : message, diff.sec, diff.ms, diff.ns)); + log_warn (LOG_TIMING, MESSAGE_FORMAT.data (), message == nullptr ? ""sv : message, diff.sec, diff.ms, diff.ns); } managed_timing_sequence* get_available_sequence () noexcept diff --git a/src/native/runtime-base/util.cc b/src/native/runtime-base/util.cc index f7350c82ba4..e0c568124ea 100644 --- a/src/native/runtime-base/util.cc +++ b/src/native/runtime-base/util.cc @@ -149,7 +149,7 @@ Util::create_public_directory (const char *dir) mode_t m = umask (0); int ret = mkdir (dir, 0777); if (ret < 0) { - log_warn (LOG_DEFAULT, std::format ("Failed to create directory '{}'. {}", dir, std::strerror (errno))); + log_warn (LOG_DEFAULT, "Failed to create directory '{}'. {}", dir, std::strerror (errno)); } umask (m); } @@ -197,7 +197,7 @@ Util::set_world_accessable ([[maybe_unused]] const char *path) } while (r == -1 && errno == EINTR); if (r == -1) { - log_error (LOG_DEFAULT, std::format ("chmod(\"{}\", 0664) failed: {}", path, strerror (errno))); + log_error (LOG_DEFAULT, "chmod(\"{}\", 0664) failed: {}", path, strerror (errno)); } } @@ -210,7 +210,7 @@ Util::set_user_executable ([[maybe_unused]] const char *path) } while (r == -1 && errno == EINTR); if (r == -1) { - log_error (LOG_DEFAULT, std::format ("chmod(\"{}\") failed: {}", path, strerror (errno))); + log_error (LOG_DEFAULT, "chmod(\"{}\") failed: {}", path, strerror (errno)); } } @@ -297,7 +297,7 @@ Util::monodroid_fopen (const char *filename, const char *mode) */ ret = fopen (filename, mode); if (ret == nullptr) { - log_error (LOG_DEFAULT, std::format ("fopen failed for file {}: {}", filename, strerror (errno))); + log_error (LOG_DEFAULT, "fopen failed for file {}: {}", filename, strerror (errno)); return nullptr; } diff --git a/src/native/runtime-base/util.hh b/src/native/runtime-base/util.hh index 35eb8c3c590..986f7f2e49a 100644 --- a/src/native/runtime-base/util.hh +++ b/src/native/runtime-base/util.hh @@ -79,7 +79,7 @@ namespace xamarin::android { struct stat sbuf; if (fstatat (dirfd, file_name, &sbuf, 0) == -1) { - log_warn (LOG_ASSEMBLY, std::format ("Failed to stat file '{}': {}", file_name, std::strerror (errno))); + log_warn (LOG_ASSEMBLY, "Failed to stat file '{}': {}", file_name, std::strerror (errno)); return std::nullopt; } @@ -90,7 +90,7 @@ namespace xamarin::android { int fd = openat (dirfd, file_name, O_RDONLY); if (fd < 0) { - log_error (LOG_ASSEMBLY, std::format ("Failed to open file '{}' for reading: {}", file_name, std::strerror (errno))); + log_error (LOG_ASSEMBLY, "Failed to open file '{}' for reading: {}", file_name, std::strerror (errno)); return std::nullopt; } diff --git a/src/native/shared/cpp-util.hh b/src/native/shared/cpp-util.hh index 8c2397218f5..3951b81f474 100644 --- a/src/native/shared/cpp-util.hh +++ b/src/native/shared/cpp-util.hh @@ -83,7 +83,7 @@ abort_if_negative_integer_argument (int arg, const char *arg_name, std::source_l // of the calls present. force_inline inline void pd_log_location (std::source_location sloc = std::source_location::current ()) noexcept { - log_info_nocheck (LOG_DEFAULT, std::format ("loc: {}:{} ('{}')", sloc.file_name (), sloc.line (), sloc.function_name ())); + log_info_nocheck (LOG_DEFAULT, "loc: {}:{} ('{}')", sloc.file_name (), sloc.line (), sloc.function_name ()); } namespace xamarin::android diff --git a/src/native/shared/helpers.cc b/src/native/shared/helpers.cc index 645f30e0d84..9638b16ebd5 100644 --- a/src/native/shared/helpers.cc +++ b/src/native/shared/helpers.cc @@ -11,7 +11,7 @@ using namespace xamarin::android; Helpers::abort_application (LogCategories category, const char *message, bool log_location, std::source_location sloc) noexcept { // Log it, but also... - log_fatal (category, std::string_view { message }); + log_fatal (category, "{}", message); // ...let android include it in the tombstone, debuggerd output, stack trace etc android_set_abort_message (message); @@ -35,12 +35,11 @@ Helpers::abort_application (LogCategories category, const char *message, bool lo log_fatal ( category, - std::format ("Abort at {}:{}:{} ('%s')", - file_name, - sloc.line (), - sloc.column (), - sloc.function_name () - ) + "Abort at {}:{}:{} ('%s')", + file_name, + sloc.line (), + sloc.column (), + sloc.function_name () ); } std::abort (); diff --git a/src/native/shared/log_functions.cc b/src/native/shared/log_functions.cc index e82f2bd5856..c6d61f54d0d 100644 --- a/src/native/shared/log_functions.cc +++ b/src/native/shared/log_functions.cc @@ -3,8 +3,8 @@ #include -//#include "java-interop-logger.h" -#include "log_types.hh" +#include "java-interop-logger.h" +#include "log_level.hh" // Must match the same ordering as LogCategories static constexpr std::array log_names = { diff --git a/src/native/shared/log_level.hh b/src/native/shared/log_level.hh new file mode 100644 index 00000000000..fc7a7566910 --- /dev/null +++ b/src/native/shared/log_level.hh @@ -0,0 +1,26 @@ +#pragma once + +#include + +namespace xamarin::android { + enum class LogTimingCategories : uint32_t + { + Default = 0, + Bare = 1 << 0, + FastBare = 1 << 1, + }; + + // Keep in sync with LogLevel defined in JNIEnv.cs + enum class LogLevel : unsigned int + { + Unknown = 0x00, + Default = 0x01, + Verbose = 0x02, + Debug = 0x03, + Info = 0x04, + Warn = 0x05, + Error = 0x06, + Fatal = 0x07, + Silent = 0x08 + }; +} diff --git a/src/native/shared/log_types.hh b/src/native/shared/log_types.hh index 31a1b22dac0..66b1cae5097 100644 --- a/src/native/shared/log_types.hh +++ b/src/native/shared/log_types.hh @@ -6,6 +6,7 @@ #include #include "java-interop-logger.h" +#include "log_level.hh" // We redeclare macros here #if defined(log_debug) @@ -16,59 +17,42 @@ #undef log_info #endif -#define DO_LOG_FMT(_level, _category_, _message_) \ +#define DO_LOG_FMT(_level, _category_, _fmt_, ...) \ do { \ if ((log_categories & ((_category_))) != 0) { \ - ::log_ ## _level ## _nocheck ((_category_), _message_); \ + ::log_ ## _level ## _nocheck_fmt ((_category_), _fmt_ __VA_OPT__(,) __VA_ARGS__); \ } \ } while (0) -#define log_debug(_category_, _message_) DO_LOG_FMT (debug, (_category_), (_message_)) -#define log_info(_category_, _message_) DO_LOG_FMT (info, (_category_), (_message_)) +// +// For std::format spec, see https://en.cppreference.com/w/cpp/utility/format/spec +// -namespace xamarin::android { - enum class LogTimingCategories : uint32_t - { - Default = 0, - Bare = 1 << 0, - FastBare = 1 << 1, - }; - - // Keep in sync with LogLevel defined in JNIEnv.cs - enum class LogLevel : unsigned int - { - Unknown = 0x00, - Default = 0x01, - Verbose = 0x02, - Debug = 0x03, - Info = 0x04, - Warn = 0x05, - Error = 0x06, - Fatal = 0x07, - Silent = 0x08 - }; +// NOTE: _fmt_ takes arguments in the std::format style not the POSIX printf style +#define log_debug(_category_, _fmt_, ...) DO_LOG_FMT (debug, (_category_), (_fmt_) __VA_OPT__(,) __VA_ARGS__) + +// NOTE: _fmt_ takes arguments in the std::format style not the POSIX printf style +#define log_info(_category_, _fmt_, ...) DO_LOG_FMT (info, (_category_), (_fmt_) __VA_OPT__(,) __VA_ARGS__) + +// NOTE: _fmt_ takes arguments in the std::format style not the POSIX printf style +#define log_warn(_category_, _fmt_, ...) log_warn_fmt ((_category_), (_fmt_) __VA_OPT__(,) __VA_ARGS__) +// NOTE: _fmt_ takes arguments in the std::format style not the POSIX printf style +#define log_error(_category_, _fmt_, ...) log_error_fmt ((_category_), (_fmt_) __VA_OPT__(,) __VA_ARGS__) + +// NOTE: _fmt_ takes arguments in the std::format style not the POSIX printf style +#define log_fatal(_category_, _fmt_, ...) log_fatal_fmt ((_category_), (_fmt_) __VA_OPT__(,) __VA_ARGS__) + +namespace xamarin::android { // A slightly faster alternative to other log functions as it doesn't parse the message // for format placeholders nor it uses variable arguments void log_write (LogCategories category, LogLevel level, const char *message) noexcept; } -// -// This will be enabled once all log_* calls are converted to std::format format -// -// template [[gnu::always_inline]] -// static inline constexpr void log_debug (LogCategories category, std::format_string fmt, Args&& ...args) -// { -// if (detail::_category_is_enabled (category)) { - -// log_debug_nocheck (category, std::format (fmt, std::forward(args)...).c_str ()); -// } -// } - -[[gnu::always_inline]] -static inline constexpr void log_debug_nocheck (LogCategories category, std::string const& message) noexcept +template [[gnu::always_inline]] +static inline constexpr void log_debug_nocheck_fmt (LogCategories category, std::format_string fmt, Args&& ...args) { - log_write (category, xamarin::android::LogLevel::Debug, message.c_str ()); + log_write (category, xamarin::android::LogLevel::Debug, std::format (fmt, std::forward(args)...).c_str ()); } [[gnu::always_inline]] @@ -77,10 +61,10 @@ static inline constexpr void log_debug_nocheck (LogCategories category, std::str log_write (category, xamarin::android::LogLevel::Debug, message.data ()); } -[[gnu::always_inline]] -static inline constexpr void log_info_nocheck (LogCategories category, std::string const& message) noexcept +template [[gnu::always_inline]] +static inline constexpr void log_info_nocheck_fmt (LogCategories category, std::format_string fmt, Args&& ...args) { - log_write (category, xamarin::android::LogLevel::Info, message.c_str ()); + log_write (category, xamarin::android::LogLevel::Info, std::format (fmt, std::forward(args)...).c_str ()); } [[gnu::always_inline]] @@ -89,38 +73,38 @@ static inline constexpr void log_info_nocheck (LogCategories category, std::stri log_write (category, xamarin::android::LogLevel::Info, message.data ()); } -[[gnu::always_inline]] -static inline constexpr void log_warn (LogCategories category, std::string const& message) noexcept +template [[gnu::always_inline]] +static inline constexpr void log_warn_fmt (LogCategories category, std::format_string fmt, Args&& ...args) noexcept { - log_write (category, xamarin::android::LogLevel::Warn, message.c_str ()); + log_write (category, xamarin::android::LogLevel::Warn, std::format (fmt, std::forward(args)...).c_str ()); } [[gnu::always_inline]] -static inline constexpr void log_warn (LogCategories category, std::string_view const& message) noexcept +static inline constexpr void log_warn_fmt (LogCategories category, std::string_view const& message) noexcept { log_write (category, xamarin::android::LogLevel::Warn, message.data ()); } -[[gnu::always_inline]] -static inline constexpr void log_error (LogCategories category, std::string const& message) noexcept +template [[gnu::always_inline]] +static inline constexpr void log_error_fmt (LogCategories category, std::format_string fmt, Args&& ...args) noexcept { - log_write (category, xamarin::android::LogLevel::Error, message.c_str ()); + log_write (category, xamarin::android::LogLevel::Error, std::format (fmt, std::forward(args)...).c_str ()); } [[gnu::always_inline]] -static inline constexpr void log_error (LogCategories category, std::string_view const& message) noexcept +static inline constexpr void log_error_fmt (LogCategories category, std::string_view const& message) noexcept { log_write (category, xamarin::android::LogLevel::Error, message.data ()); } -[[gnu::always_inline]] -static inline constexpr void log_fatal (LogCategories category, std::string const& message) noexcept +template [[gnu::always_inline]] +static inline constexpr void log_fatal_fmt (LogCategories category, std::format_string fmt, Args&& ...args) noexcept { - log_write (category, xamarin::android::LogLevel::Fatal, message.c_str ()); + log_write (category, xamarin::android::LogLevel::Fatal, std::format (fmt, std::forward(args)...).c_str ()); } [[gnu::always_inline]] -static inline constexpr void log_fatal (LogCategories category, std::string_view const& message) noexcept +static inline constexpr void log_fatal_fmt (LogCategories category, std::string_view const& message) noexcept { log_write (category, xamarin::android::LogLevel::Fatal, message.data ()); } diff --git a/src/native/xamarin-debug-app-helper/debug-app-helper.cc b/src/native/xamarin-debug-app-helper/debug-app-helper.cc index ae8c2cd4bc6..ac3e9e75e81 100644 --- a/src/native/xamarin-debug-app-helper/debug-app-helper.cc +++ b/src/native/xamarin-debug-app-helper/debug-app-helper.cc @@ -48,7 +48,7 @@ Java_mono_android_DebugRuntime_init (JNIEnv *env, [[maybe_unused]] jclass klass, if (runtimeNativeLibDir != nullptr) { jstr = runtimeNativeLibDir; AndroidSystem::set_runtime_libdir (Util::strdup_new (jstr.get_cstr ())); - log_warn (LOG_DEFAULT, std::format ("Using runtime path: {}", AndroidSystem::get_runtime_libdir ())); + log_warn (LOG_DEFAULT, "Using runtime path: {}", AndroidSystem::get_runtime_libdir ()); } const char *monosgen_path = get_libmonosgen_path (); @@ -74,10 +74,8 @@ copy_file_to_internal_location (char *to_dir, char *from_dir, char *file) break; log_warn (LOG_DEFAULT, - std::format ( - "Copying file `{}` from external location `{}` to internal location `{}`", - file, from_dir, to_dir - ) + "Copying file `{}` from external location `{}` to internal location `{}`", + file, from_dir, to_dir ); to_file = Util::path_combine (to_dir, file); @@ -86,12 +84,12 @@ copy_file_to_internal_location (char *to_dir, char *from_dir, char *file) int r = unlink (to_file); if (r < 0 && errno != ENOENT) { - log_warn (LOG_DEFAULT, std::format ("Unable to delete file `{}`: {}", to_file, strerror (errno))); + log_warn (LOG_DEFAULT, "Unable to delete file `{}`: {}", to_file, strerror (errno)); break; } if (!Util::file_copy (to_file, from_file)) { - log_warn (LOG_DEFAULT, std::format ("Copy failed from `{}` to `{}`: {}", from_file, to_file, strerror (errno))); + log_warn (LOG_DEFAULT, "Copy failed from `{}` to `{}`: {}", from_file, to_file, strerror (errno)); break; } @@ -110,22 +108,22 @@ copy_native_libraries_to_internal_location () dirent *e; char *dir_path = Util::path_combine (od, "lib"); - log_warn (LOG_DEFAULT, std::format ("checking directory: `{}`", dir_path)); + log_warn (LOG_DEFAULT, "checking directory: `{}`", dir_path); if (dir_path == nullptr || !Util::directory_exists (dir_path)) { - log_warn (LOG_DEFAULT, std::format ("directory does not exist: `{}`", dir_path)); + log_warn (LOG_DEFAULT, "directory does not exist: `{}`", dir_path); delete[] dir_path; continue; } if ((dir = ::opendir (dir_path)) == nullptr) { - log_warn (LOG_DEFAULT, std::format ("could not open directory: `{}`", dir_path)); + log_warn (LOG_DEFAULT, "could not open directory: `{}`", dir_path); delete[] dir_path; continue; } while ((e = readdir (dir)) != nullptr) { - log_warn (LOG_DEFAULT, std::format ("checking file: `{}`", e->d_name)); + log_warn (LOG_DEFAULT, "checking file: `{}`", e->d_name); if (Util::monodroid_dirent_hasextension (e, ".so")) { copy_file_to_internal_location (AndroidSystem::get_primary_override_dir (), dir_path, e->d_name); } @@ -142,9 +140,9 @@ runtime_exists (const char *dir, char*& libmonoso) return false; libmonoso = Util::path_combine (dir, SharedConstants::MONO_SGEN_SO); - log_warn (LOG_DEFAULT, std::format ("Checking whether Mono runtime exists at: {}", libmonoso)); + log_warn (LOG_DEFAULT, "Checking whether Mono runtime exists at: {}", libmonoso); if (Util::file_exists (libmonoso)) { - log_info (LOG_DEFAULT, std::format ("Mono runtime found at: {}", libmonoso)); + log_info (LOG_DEFAULT, "Mono runtime found at: {}", libmonoso); return true; } delete[] libmonoso; @@ -196,25 +194,25 @@ get_libmonosgen_path () if (!Util::file_exists (link)) { int result = symlink (libmonoso, link); if (result != 0 && errno == EEXIST) { - log_warn (LOG_DEFAULT, std::format ("symlink exists, recreating: {} -> {}", link, libmonoso)); + log_warn (LOG_DEFAULT, "symlink exists, recreating: {} -> {}", link, libmonoso); unlink (link); result = symlink (libmonoso, link); } if (result != 0) - log_warn (LOG_DEFAULT, std::format ("symlink failed with errno={} {}", errno, strerror (errno))); + log_warn (LOG_DEFAULT, "symlink failed with errno={} {}", errno, strerror (errno)); } delete[] libmonoso; libmonoso = link; } - log_warn (LOG_DEFAULT, std::format ("Trying to load sgen from: {}", libmonoso != nullptr ? libmonoso : ""sv)); + log_warn (LOG_DEFAULT, "Trying to load sgen from: {}", libmonoso != nullptr ? libmonoso : ""sv); if (libmonoso != nullptr && Util::file_exists (libmonoso)) return libmonoso; delete[] libmonoso; if (runtime_exists (AndroidSystem::SYSTEM_LIB_PATH.data (), libmonoso)) return libmonoso; - log_fatal (LOG_DEFAULT, std::format ("Cannot find '{}'. Looked in the following locations:", SharedConstants::MONO_SGEN_SO)); + log_fatal (LOG_DEFAULT, "Cannot find '{}'. Looked in the following locations:", SharedConstants::MONO_SGEN_SO); for (const char *od : AndroidSystem::override_dirs) { if (od == nullptr) From df0e22a8acced541addbf98f8eaede17ccb9090f Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Fri, 29 Nov 2024 09:54:16 +0100 Subject: [PATCH 44/54] Cleanup --- src/native/shared/helpers.hh | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/native/shared/helpers.hh b/src/native/shared/helpers.hh index 078da3afac0..c69d49d7ee3 100644 --- a/src/native/shared/helpers.hh +++ b/src/native/shared/helpers.hh @@ -2,14 +2,12 @@ #define __HELPERS_HH #include -#include #include #include #include #include #include "platform-compat.hh" -#include "log_types.hh" using namespace std::string_view_literals; From 4cb2c57e9f62d0033f043c2408640f7d15cb68be Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Fri, 29 Nov 2024 10:01:06 +0100 Subject: [PATCH 45/54] Cleanup --- src/native/runtime-base/internal-pinvokes.hh | 1 - 1 file changed, 1 deletion(-) diff --git a/src/native/runtime-base/internal-pinvokes.hh b/src/native/runtime-base/internal-pinvokes.hh index 84477577de8..b8e7a4ae424 100644 --- a/src/native/runtime-base/internal-pinvokes.hh +++ b/src/native/runtime-base/internal-pinvokes.hh @@ -3,7 +3,6 @@ #include #include -//#include #include #include From 41a3acf5c835a2752ad6fe35b2202738257aa96e Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Fri, 29 Nov 2024 10:11:56 +0100 Subject: [PATCH 46/54] Update apkdesc files --- .../BuildReleaseArm64SimpleDotNet.apkdesc | 14 +++--- .../BuildReleaseArm64XFormsDotNet.apkdesc | 45 +++++++++---------- 2 files changed, 28 insertions(+), 31 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleDotNet.apkdesc b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleDotNet.apkdesc index b94b94d9485..69f5f2ca92d 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleDotNet.apkdesc +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleDotNet.apkdesc @@ -5,7 +5,7 @@ "Size": 3036 }, "classes.dex": { - "Size": 389632 + "Size": 22444 }, "lib/arm64-v8a/lib__Microsoft.Android.Resource.Designer.dll.so": { "Size": 18296 @@ -14,10 +14,10 @@ "Size": 86352 }, "lib/arm64-v8a/lib_Mono.Android.dll.so": { - "Size": 116768 + "Size": 116920 }, "lib/arm64-v8a/lib_Mono.Android.Runtime.dll.so": { - "Size": 22416 + "Size": 22408 }, "lib/arm64-v8a/lib_System.Console.dll.so": { "Size": 24376 @@ -44,7 +44,7 @@ "Size": 87432 }, "lib/arm64-v8a/libmonodroid.so": { - "Size": 903032 + "Size": 1501240 }, "lib/arm64-v8a/libmonosgen-2.0.so": { "Size": 3196512 @@ -62,10 +62,10 @@ "Size": 160232 }, "lib/arm64-v8a/libxamarin-app.so": { - "Size": 13016 + "Size": 18264 }, "META-INF/BNDLTOOL.RSA": { - "Size": 1223 + "Size": 1221 }, "META-INF/BNDLTOOL.SF": { "Size": 3266 @@ -98,5 +98,5 @@ "Size": 1904 } }, - "PackageSize": 2984469 + "PackageSize": 3111445 } \ No newline at end of file diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsDotNet.apkdesc b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsDotNet.apkdesc index 40a70162747..eb04b2212b1 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsDotNet.apkdesc +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsDotNet.apkdesc @@ -5,10 +5,7 @@ "Size": 6652 }, "classes.dex": { - "Size": 9448880 - }, - "classes2.dex": { - "Size": 154180 + "Size": 9172764 }, "kotlin/annotation/annotation.kotlin_builtins": { "Size": 928 @@ -35,16 +32,16 @@ "Size": 19544 }, "lib/arm64-v8a/lib_FormsViewGroup.dll.so": { - "Size": 25184 + "Size": 25424 }, "lib/arm64-v8a/lib_Java.Interop.dll.so": { "Size": 94736 }, "lib/arm64-v8a/lib_Mono.Android.dll.so": { - "Size": 522832 + "Size": 524256 }, "lib/arm64-v8a/lib_Mono.Android.Runtime.dll.so": { - "Size": 22416 + "Size": 22408 }, "lib/arm64-v8a/lib_mscorlib.dll.so": { "Size": 21432 @@ -173,31 +170,31 @@ "Size": 22096 }, "lib/arm64-v8a/lib_Xamarin.AndroidX.Activity.dll.so": { - "Size": 34760 + "Size": 34960 }, "lib/arm64-v8a/lib_Xamarin.AndroidX.AppCompat.AppCompatResources.dll.so": { - "Size": 24296 + "Size": 24512 }, "lib/arm64-v8a/lib_Xamarin.AndroidX.AppCompat.dll.so": { - "Size": 163072 + "Size": 163240 }, "lib/arm64-v8a/lib_Xamarin.AndroidX.CardView.dll.so": { "Size": 24560 }, "lib/arm64-v8a/lib_Xamarin.AndroidX.CoordinatorLayout.dll.so": { - "Size": 35680 + "Size": 35912 }, "lib/arm64-v8a/lib_Xamarin.AndroidX.Core.dll.so": { - "Size": 151216 + "Size": 151408 }, "lib/arm64-v8a/lib_Xamarin.AndroidX.CursorAdapter.dll.so": { "Size": 27168 }, "lib/arm64-v8a/lib_Xamarin.AndroidX.DrawerLayout.dll.so": { - "Size": 33760 + "Size": 33944 }, "lib/arm64-v8a/lib_Xamarin.AndroidX.Fragment.dll.so": { - "Size": 72224 + "Size": 72528 }, "lib/arm64-v8a/lib_Xamarin.AndroidX.Legacy.Support.Core.UI.dll.so": { "Size": 23896 @@ -215,16 +212,16 @@ "Size": 31592 }, "lib/arm64-v8a/lib_Xamarin.AndroidX.RecyclerView.dll.so": { - "Size": 111896 + "Size": 112248 }, "lib/arm64-v8a/lib_Xamarin.AndroidX.SavedState.dll.so": { "Size": 23144 }, "lib/arm64-v8a/lib_Xamarin.AndroidX.SwipeRefreshLayout.dll.so": { - "Size": 31672 + "Size": 31952 }, "lib/arm64-v8a/lib_Xamarin.AndroidX.ViewPager.dll.so": { - "Size": 37752 + "Size": 38048 }, "lib/arm64-v8a/lib_Xamarin.Forms.Core.dll.so": { "Size": 581000 @@ -239,7 +236,7 @@ "Size": 80632 }, "lib/arm64-v8a/lib_Xamarin.Google.Android.Material.dll.so": { - "Size": 84400 + "Size": 84768 }, "lib/arm64-v8a/libarc.bin.so": { "Size": 18776 @@ -248,7 +245,7 @@ "Size": 87432 }, "lib/arm64-v8a/libmonodroid.so": { - "Size": 903032 + "Size": 1501240 }, "lib/arm64-v8a/libmonosgen-2.0.so": { "Size": 3196512 @@ -266,7 +263,7 @@ "Size": 160232 }, "lib/arm64-v8a/libxamarin-app.so": { - "Size": 120016 + "Size": 349440 }, "META-INF/androidx.activity_activity.version": { "Size": 6 @@ -419,10 +416,10 @@ "Size": 6 }, "META-INF/BNDLTOOL.RSA": { - "Size": 1221 + "Size": 1223 }, "META-INF/BNDLTOOL.SF": { - "Size": 98661 + "Size": 98577 }, "META-INF/com.android.tools/proguard/coroutines.pro": { "Size": 1345 @@ -449,7 +446,7 @@ "Size": 5 }, "META-INF/MANIFEST.MF": { - "Size": 98534 + "Size": 98450 }, "META-INF/maven/com.google.guava/listenablefuture/pom.properties": { "Size": 96 @@ -2489,5 +2486,5 @@ "Size": 812848 } }, - "PackageSize": 10796357 + "PackageSize": 10947851 } \ No newline at end of file From c57ba4646123fd6a129c97bb27625651a745e0ab Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Fri, 29 Nov 2024 18:10:25 +0100 Subject: [PATCH 47/54] std::format doesn't like null pointers when printing strings --- src/native/monodroid/debug.cc | 22 +- .../monodroid/embedded-assemblies-zip.cc | 33 +-- src/native/monodroid/embedded-assemblies.cc | 196 +++++++++++++----- src/native/monodroid/embedded-assemblies.hh | 9 +- src/native/monodroid/mono-image-loader.hh | 2 +- src/native/monodroid/monodroid-glue.cc | 40 ++-- src/native/monodroid/osbridge.cc | 75 +++---- .../monodroid/xamarin-android-app-context.cc | 10 +- src/native/monodroid/xamarin_getifaddrs.cc | 8 +- .../pinvoke-override-api-impl.hh | 8 +- src/native/pinvoke-override/precompiled.cc | 15 +- src/native/runtime-base/logger.cc | 18 +- src/native/shared/helpers.hh | 10 + .../debug-app-helper.cc | 30 +-- 14 files changed, 293 insertions(+), 183 deletions(-) diff --git a/src/native/monodroid/debug.cc b/src/native/monodroid/debug.cc index cbcdeec2e87..8839ded308a 100644 --- a/src/native/monodroid/debug.cc +++ b/src/native/monodroid/debug.cc @@ -96,8 +96,8 @@ Debug::monodroid_profiler_load (const char *libmono_path, const char *desc, cons if (!found) log_warn (LOG_DEFAULT, "The '{}' profiler wasn't found in the main executable nor could it be loaded from '{}'.", - mname.get (), - libname.get () + optional_string (mname.get ()), + optional_string (libname.get ()) ); } @@ -109,7 +109,7 @@ bool Debug::load_profiler (void *handle, const char *desc, const char *symbol) { ProfilerInitializer func = reinterpret_cast (java_interop_lib_symbol (handle, symbol, nullptr)); - log_warn (LOG_DEFAULT, "Looking for profiler init symbol '{}'? {:p}", symbol, reinterpret_cast(func)); + log_warn (LOG_DEFAULT, "Looking for profiler init symbol '{}'? {:p}", optional_string (symbol), reinterpret_cast(func)); if (func != nullptr) { func (desc); @@ -139,7 +139,7 @@ Debug::parse_options (char *options, ConnOptions *opts) { char **args, **ptr; - log_info (LOG_DEFAULT, "Connection options: '{}'", options); + log_info (LOG_DEFAULT, "Connection options: '{}'", optional_string (options)); args = Util::monodroid_strsplit (options, ",", 0); @@ -163,7 +163,7 @@ Debug::parse_options (char *options, ConnOptions *opts) if ((endp == arg) || (*endp != '\0')) log_error (LOG_DEFAULT, "Invalid --timeout argument."sv); } else { - log_info (LOG_DEFAULT, "Unknown connection option: '{}'", arg); + log_info (LOG_DEFAULT, "Unknown connection option: '{}'", optional_string (arg)); } } } @@ -275,7 +275,7 @@ Debug::process_connection (int fd) // null-terminate command [cmd_len] = 0; - log_info (LOG_DEFAULT, "Received cmd: '{}'.", command); + log_info (LOG_DEFAULT, "Received cmd: '{}'.", optional_string (command)); if (process_cmd (fd, command)) return true; @@ -487,7 +487,7 @@ Debug::process_cmd (int fd, char *cmd) profiler_fd = fd; profiler_description = Util::monodroid_strdup_printf ("%s,output=#%i", prof, profiler_fd); } else { - log_error (LOG_DEFAULT, "Unknown profiler: '{}'", prof); + log_error (LOG_DEFAULT, "Unknown profiler: '{}'", optional_string (prof)); } /* Notify the main thread (start_profiling ()) */ profiler_configured = true; @@ -496,7 +496,7 @@ Debug::process_cmd (int fd, char *cmd) pthread_mutex_unlock (&process_cmd_mutex); return use_fd; } else { - log_error (LOG_DEFAULT, "Unsupported command: '{}'", cmd); + log_error (LOG_DEFAULT, "Unsupported command: '{}'", optional_string (cmd)); } return false; @@ -526,7 +526,7 @@ Debug::start_debugging (void) // this text is used in unit tests to check the debugger started // do not change it without updating the test. - log_warn (LOG_DEBUGGER, "Trying to initialize the debugger with options: {}", debug_arg); + log_warn (LOG_DEBUGGER, "Trying to initialize the debugger with options: {}", optional_string (debug_arg)); if (enable_soft_breakpoints ()) { constexpr std::string_view soft_breakpoints { "--soft-breakpoints" }; @@ -588,10 +588,10 @@ Debug::enable_soft_breakpoints (void) bool ret; if (strcmp ("0", value) == 0) { ret = false; - log_info (LOG_DEBUGGER, "soft breakpoints disabled ({} property set to {})", SharedConstants::DEBUG_MONO_SOFT_BREAKPOINTS.data (), value); + log_info (LOG_DEBUGGER, "soft breakpoints disabled ({} property set to {})", SharedConstants::DEBUG_MONO_SOFT_BREAKPOINTS.data (), optional_string (value)); } else { ret = true; - log_info (LOG_DEBUGGER, "soft breakpoints enabled ({} property set to {})", SharedConstants::DEBUG_MONO_SOFT_BREAKPOINTS.data (), value); + log_info (LOG_DEBUGGER, "soft breakpoints enabled ({} property set to {})", SharedConstants::DEBUG_MONO_SOFT_BREAKPOINTS.data (), optional_string (value)); } delete[] value; return ret; diff --git a/src/native/monodroid/embedded-assemblies-zip.cc b/src/native/monodroid/embedded-assemblies-zip.cc index 2497cab1c83..453ff56d437 100644 --- a/src/native/monodroid/embedded-assemblies-zip.cc +++ b/src/native/monodroid/embedded-assemblies-zip.cc @@ -22,14 +22,14 @@ EmbeddedAssemblies::zip_load_entry_common (size_t entry_index, std::vector LOG_ASSEMBLY, std::format ( "Assembly store '{}' is not a valid .NET for Android assembly store file", - entry_name.get () + optional_string (entry_name.get ()) ) ); } @@ -232,7 +237,7 @@ EmbeddedAssemblies::map_assembly_store (dynamic_local_string LOG_ASSEMBLY, std::format ( "Assembly store '{}' uses format version {:x}, instead of the expected {:x}", - entry_name.get (), + optional_string (entry_name.get ()), header->version, ASSEMBLY_STORE_FORMAT_VERSION ) @@ -299,9 +304,9 @@ EmbeddedAssemblies::zip_load_assembly_store_entries (std::vector const& log_debug ( LOG_ASSEMBLY, "Found a shared library entry {} (index: {}; name: {}; hash: {:x}; apk offset: {})", - entry_name.get (), + optional_string (entry_name.get ()), number_of_zip_dso_entries, - name, + optional_string (name), apk_entry->name_hash, apk_entry->offset ); @@ -322,7 +327,7 @@ EmbeddedAssemblies::zip_load_entries (int fd, const char *apk_name, [[maybe_unus LOG_ASSEMBLY, std::format ( "Failed to read the EOCD record from APK file %s", - apk_name + optional_string (apk_name) ) ); } @@ -340,7 +345,7 @@ EmbeddedAssemblies::zip_load_entries (int fd, const char *apk_name, [[maybe_unus std::strerror (errno), retval, errno, - apk_name + optional_string (apk_name) ) ); } @@ -371,7 +376,7 @@ EmbeddedAssemblies::zip_load_entries (int fd, const char *apk_name, [[maybe_unus std::strerror (errno), nread, errno, - apk_name + optional_string (apk_name) ) ); } @@ -408,7 +413,9 @@ EmbeddedAssemblies::set_entry_data (XamarinAndroidBundledAssembly &entry, ZipEnt log_debug ( LOG_ASSEMBLY, "Set bundled assembly entry data. file name: '{}'; entry name: '{}'; data size: {}", - entry.file_name, entry.name, entry.data_size + optional_string (entry.file_name), + optional_string (entry.name), + entry.data_size ); } diff --git a/src/native/monodroid/embedded-assemblies.cc b/src/native/monodroid/embedded-assemblies.cc index c868da14469..6adb6f27fe6 100644 --- a/src/native/monodroid/embedded-assemblies.cc +++ b/src/native/monodroid/embedded-assemblies.cc @@ -124,13 +124,13 @@ EmbeddedAssemblies::get_assembly_data (uint8_t *data, uint32_t data_size, [[mayb LOG_ASSEMBLY, std::format ( "Compressed assembly '{}' is larger than when the application was built (expected at most {}, got {}). Assemblies don't grow just like that!", - name, + optional_string (name), cad.uncompressed_file_size, header->uncompressed_length ) ); } else { - log_debug (LOG_ASSEMBLY, "Compressed assembly '{}' is smaller than when the application was built. Adjusting accordingly.", name); + log_debug (LOG_ASSEMBLY, "Compressed assembly '{}' is smaller than when the application was built. Adjusting accordingly.", optional_string (name)); } cad.uncompressed_file_size = header->uncompressed_length; } @@ -143,7 +143,7 @@ EmbeddedAssemblies::get_assembly_data (uint8_t *data, uint32_t data_size, [[mayb LOG_ASSEMBLY, std::format ( "Decompression of assembly {} failed with code {}", - name, + optional_string (name), ret ) ); @@ -154,7 +154,7 @@ EmbeddedAssemblies::get_assembly_data (uint8_t *data, uint32_t data_size, [[mayb LOG_ASSEMBLY, std::format ( "Decompression of assembly {} yielded a different size (expected {}, got {})", - name, + optional_string (name), cad.uncompressed_file_size, static_cast(ret) ) @@ -228,7 +228,7 @@ EmbeddedAssemblies::map_runtime_file (XamarinAndroidBundledAssembly& file) noexc ); if (already_mapped) { - log_debug (LOG_ASSEMBLY, "Assembly {} already mmapped by another thread, unmapping our copy", file.name); + log_debug (LOG_ASSEMBLY, "Assembly {} already mmapped by another thread, unmapping our copy", optional_string (file.name)); munmap (map_info.area, file.data_size); map_info.area = nullptr; } @@ -250,8 +250,8 @@ EmbeddedAssemblies::map_runtime_file (XamarinAndroidBundledAssembly& file) noexc static_cast(file.data), pointer_add (file.data, file.data_size), file.data_size, - file.name, - file.name, + optional_string (file.name), + optional_string (file.name), header.data () ); } @@ -287,7 +287,7 @@ EmbeddedAssemblies::load_bundled_assembly ( if (strcmp (assembly.name, abi_name.get ()) != 0) { return nullptr; } else { - log_debug (LOG_ASSEMBLY, "open_from_bundles: found architecture-specific: '{}'", abi_name.get ()); + log_debug (LOG_ASSEMBLY, "open_from_bundles: found architecture-specific: '{}'", optional_string (abi_name.get ())); } } @@ -321,7 +321,7 @@ EmbeddedAssemblies::load_bundled_assembly ( if (debug_file.data != nullptr) { if (debug_file.data_size > std::numeric_limits::max ()) { - log_warn (LOG_ASSEMBLY, std::format ("Debug info file '{}' is too big for Mono to consume", debug_file.name)); + log_warn (LOG_ASSEMBLY, "Debug info file '{}' is too big for Mono to consume", optional_string (debug_file.name)); } else { mono_debug_open_image_from_memory (image, reinterpret_cast(debug_file.data), static_cast(debug_file.data_size)); } @@ -333,7 +333,7 @@ EmbeddedAssemblies::load_bundled_assembly ( MonoImageOpenStatus status; MonoAssembly *a = mono_assembly_load_from_full (image, name.get (), &status, ref_only); if (a == nullptr || status != MonoImageOpenStatus::MONO_IMAGE_OK) { - log_warn (LOG_ASSEMBLY, std::format ("Failed to load managed assembly '{}'. {}", name.get (), mono_image_strerror (status))); + log_warn (LOG_ASSEMBLY, "Failed to load managed assembly '{}'. {}", optional_string (name.get ()), optional_string (mono_image_strerror (status))); return nullptr; } @@ -348,7 +348,7 @@ EmbeddedAssemblies::individual_assemblies_open_from_bundles (dynamic_local_strin name.append (SharedConstants::DLL_EXTENSION); } - log_debug (LOG_ASSEMBLY, "individual_assemblies_open_from_bundles: looking for bundled name: '{}'", name.get ()); + log_debug (LOG_ASSEMBLY, "individual_assemblies_open_from_bundles: looking for bundled name: '{}'", optional_string (name.get ())); dynamic_local_string abi_name; abi_name @@ -395,11 +395,11 @@ force_inline MonoAssembly* EmbeddedAssemblies::assembly_store_open_from_bundles (dynamic_local_string& name, TLoaderData loader_data, bool ref_only) noexcept { hash_t name_hash = xxhash::hash (name.get (), name.length ()); - log_debug (LOG_ASSEMBLY, "assembly_store_open_from_bundles: looking for bundled name: '{}' (hash {:x})", name.get (), name_hash); + log_debug (LOG_ASSEMBLY, "assembly_store_open_from_bundles: looking for bundled name: '{}' (hash {:x})", optional_string (name.get ()), name_hash); const AssemblyStoreIndexEntry *hash_entry = find_assembly_store_entry (name_hash, assembly_store_hashes, assembly_store.index_entry_count); if (hash_entry == nullptr) { - log_warn (LOG_ASSEMBLY, std::format ("Assembly '{}' (hash {:x}) not found", name.get (), name_hash)); + log_warn (LOG_ASSEMBLY, "Assembly '{}' (hash {:x}) not found", optional_string (name.get ()), name_hash); return nullptr; } @@ -436,7 +436,7 @@ EmbeddedAssemblies::assembly_store_open_from_bundles (dynamic_local_stringdata_size, assembly_runtime_info.descriptor->debug_data_size, assembly_runtime_info.descriptor->config_data_size, - name.get () + optional_string (name.get ()) ); } @@ -446,7 +446,7 @@ EmbeddedAssemblies::assembly_store_open_from_bundles (dynamic_local_string(managed_type_name), nullptr); if (type == nullptr) [[unlikely]] { - log_info (LOG_ASSEMBLY, "typemap: managed type '{}' (mapped from Java type '{}') could not be loaded", managed_type_name, java_type_name.get ()); + log_info (LOG_ASSEMBLY, "typemap: managed type '{}' (mapped from Java type '{}') could not be loaded", optional_string (managed_type_name), java_type_name.get ()); return nullptr; } MonoReflectionType *ret = mono_type_get_object (Util::get_current_domain (), type); if (ret == nullptr) [[unlikely]] { - log_warn (LOG_ASSEMBLY, "typemap: unable to instantiate managed type '{}'", managed_type_name); + log_warn (LOG_ASSEMBLY, "typemap: unable to instantiate managed type '{}'", optional_string (managed_type_name)); return nullptr; } @@ -676,14 +676,14 @@ EmbeddedAssemblies::typemap_java_to_managed (hash_t hash, const MonoString *java module->image = mono_image_loaded (module->assembly_name); if (module->image == nullptr) { - log_debug (LOG_ASSEMBLY, "typemap: assembly '{}' hasn't been loaded yet, attempting a full load", module->assembly_name); + log_debug (LOG_ASSEMBLY, "typemap: assembly '{}' hasn't been loaded yet, attempting a full load", optional_string (module->assembly_name)); // Fake a request from MonoVM to load the assembly. MonoAssemblyName *assembly_name = mono_assembly_name_new (module->assembly_name); MonoAssembly *assm; if (assembly_name == nullptr) { - log_error (LOG_ASSEMBLY, std::format ("typemap: failed to create Mono assembly name for '{}'", module->assembly_name)); + log_error (LOG_ASSEMBLY, "typemap: failed to create Mono assembly name for '{}'", optional_string (module->assembly_name)); assm = nullptr; } else { MonoAssemblyLoadContextGCHandle alc_gchandle = mono_alc_get_default_gchandle (); @@ -692,14 +692,14 @@ EmbeddedAssemblies::typemap_java_to_managed (hash_t hash, const MonoString *java } if (assm == nullptr) { - log_warn (LOG_ASSEMBLY, std::format ("typemap: failed to load managed assembly '{}'", module->assembly_name)); + log_warn (LOG_ASSEMBLY, "typemap: failed to load managed assembly '{}'", optional_string (module->assembly_name)); } else { module->image = mono_assembly_get_image (assm); } } if (module->image == nullptr) { - log_error (LOG_ASSEMBLY, "typemap: unable to load assembly '{}' when looking up managed type corresponding to Java type '{}'", module->assembly_name, to_utf8 (java_type_name).get ()); + log_error (LOG_ASSEMBLY, "typemap: unable to load assembly '{}' when looking up managed type corresponding to Java type '{}'", optional_string (module->assembly_name), to_utf8 (java_type_name).get ()); return nullptr; } } @@ -707,7 +707,13 @@ EmbeddedAssemblies::typemap_java_to_managed (hash_t hash, const MonoString *java log_debug (LOG_ASSEMBLY, "typemap: java type '{}' corresponds to managed token id {} ({:x})", to_utf8 (java_type_name).get (), java_entry->type_token_id, java_entry->type_token_id); MonoClass *klass = mono_class_get (module->image, java_entry->type_token_id); if (klass == nullptr) [[unlikely]] { - log_error (LOG_ASSEMBLY, "typemap: unable to find managed type with token ID {} in assembly '{}', corresponding to Java type '{}'", java_entry->type_token_id, module->assembly_name, to_utf8 (java_type_name).get ()); + log_error ( + LOG_ASSEMBLY, + "typemap: unable to find managed type with token ID {} in assembly '{}', corresponding to Java type '{}'", + java_entry->type_token_id, + optional_string (module->assembly_name), + to_utf8 (java_type_name).get () + ); return nullptr; } @@ -718,7 +724,12 @@ EmbeddedAssemblies::typemap_java_to_managed (hash_t hash, const MonoString *java MonoReflectionType *ret = mono_type_get_object (domain, mono_class_get_type (klass)); if (ret == nullptr) { - log_warn (LOG_ASSEMBLY, "typemap: unable to instantiate managed type with token ID {} in assembly '{}', corresponding to Java type '{}'", java_entry->type_token_id, module->assembly_name, to_utf8 (java_type_name).get ()); + log_warn (LOG_ASSEMBLY, + "typemap: unable to instantiate managed type with token ID {} in assembly '{}', corresponding to Java type '{}'", + java_entry->type_token_id, + optional_string (module->assembly_name), + to_utf8 (java_type_name).get () + ); return nullptr; } @@ -783,7 +794,7 @@ EmbeddedAssemblies::typemap_managed_to_java ([[maybe_unused]] MonoType *type, Mo const TypeMapEntry *entry = typemap_managed_to_java (full_name.get ()); if (entry == nullptr) [[unlikely]] { - log_info (LOG_ASSEMBLY, "typemap: unable to find mapping to a Java type from managed type '{}'", full_name.get ()); + log_info (LOG_ASSEMBLY, "typemap: unable to find mapping to a Java type from managed type '{}'", optional_string (full_name.get ())); return nullptr; } @@ -815,7 +826,7 @@ EmbeddedAssemblies::typemap_managed_to_java ([[maybe_unused]] MonoType *type, Mo const TypeMapModuleEntry *entry = match->map != nullptr ? binary_search (token, match->map, match->entry_count) : nullptr; if (entry == nullptr) { if (match->map == nullptr) { - log_warn (LOG_ASSEMBLY, std::format ("typemap: module with MVID [{}] has no associated type map.", MonoGuidString (mvid).get ())); + log_warn (LOG_ASSEMBLY, "typemap: module with MVID [{}] has no associated type map.", MonoGuidString (mvid).get ()); return nullptr; } @@ -831,13 +842,30 @@ EmbeddedAssemblies::typemap_managed_to_java ([[maybe_unused]] MonoType *type, Mo } if (entry->java_map_index >= java_type_count) [[unlikely]] { - log_warn (LOG_ASSEMBLY, "typemap: type with token {} ({:x}) in module [{}] ({}) has invalid Java type index {}", token, token, MonoGuidString (mvid).get (), match->assembly_name, entry->java_map_index); + log_warn ( + LOG_ASSEMBLY, + "typemap: type with token {} ({:x}) in module [{}] ({}) has invalid Java type index {}", + token, + token, + MonoGuidString (mvid).get (), + optional_string (match->assembly_name), + entry->java_map_index + ); return nullptr; } TypeMapJava const& java_entry = map_java[entry->java_map_index]; if (java_entry.java_name_index >= java_type_count) [[unlikely]] { - log_warn (LOG_ASSEMBLY, "typemap: type with token {} ({:x}) in module [{}] ({}) points to invalid Java type at index {} (invalid type name index {})", token, token, MonoGuidString (mvid).get (), match->assembly_name, entry->java_map_index, java_entry.java_name_index); + log_warn ( + LOG_ASSEMBLY, + "typemap: type with token {} ({:x}) in module [{}] ({}) points to invalid Java type at index {} (invalid type name index {})", + token, + token, + MonoGuidString (mvid).get (), + optional_string (match->assembly_name), + entry->java_map_index, + java_entry.java_name_index + ); return nullptr; } const char *ret = java_type_names[java_entry.java_name_index]; @@ -852,7 +880,7 @@ EmbeddedAssemblies::typemap_managed_to_java ([[maybe_unused]] MonoType *type, Mo token, token, MonoGuidString (mvid).get (), - match->assembly_name, + optional_string (match->assembly_name), ret ); @@ -904,7 +932,7 @@ EmbeddedAssemblies::md_mmap_apk_file (int fd, uint32_t offset, size_t size, cons "Could not mmap APK fd {}: {}; File={}", fd, strerror (errno), - filename + optional_string (filename) ) ); } @@ -923,7 +951,7 @@ EmbeddedAssemblies::md_mmap_apk_file (int fd, uint32_t offset, size_t size, cons pointer_add (file_info.area, file_info.size), file_info.size, fd, - filename + optional_string (filename) ); return file_info; @@ -939,11 +967,11 @@ EmbeddedAssemblies::gather_bundled_assemblies_from_apk (const char* apk, monodro LOG_ASSEMBLY, std::format ( "ERROR: Unable to load application package {}.", - apk + optional_string (apk) ) ); } - log_debug (LOG_ASSEMBLY, "APK {} FD: {}", apk, fd); + log_debug (LOG_ASSEMBLY, "APK {} FD: {}", optional_string (apk), fd); zip_load_entries (fd, apk, should_register); } @@ -970,40 +998,90 @@ EmbeddedAssemblies::typemap_read_header ([[maybe_unused]] int dir_fd, const char struct stat sbuf; int res = fstatat (dir_fd, file_path, &sbuf, 0); if (res < 0) { - log_error (LOG_ASSEMBLY, "typemap: failed to stat {} file '{}/{}': {}", file_type, dir_path, file_path, strerror (errno)); + log_error ( + LOG_ASSEMBLY, + "typemap: failed to stat {} file '{}/{}': {}", + optional_string (file_type), + optional_string (dir_path), + optional_string (file_path), + strerror (errno) + ); return false; } file_size = static_cast(sbuf.st_size); if (file_size < sizeof (header)) { - log_error (LOG_ASSEMBLY, "typemap: {} file '{}/{}' is too small (must be at least {} bytes)", file_type, dir_path, file_path, sizeof (header)); + log_error ( + LOG_ASSEMBLY, + "typemap: {} file '{}/{}' is too small (must be at least {} bytes)", + optional_string (file_type), + optional_string (dir_path), + optional_string (file_path), + sizeof (header) + ); return false; } fd = openat (dir_fd, file_path, O_RDONLY); if (fd < 0) { - log_error (LOG_ASSEMBLY, "typemap: failed to open {} file {}/{} for reading: {}", file_type, dir_path, file_path, strerror (errno)); + log_error ( + LOG_ASSEMBLY, + "typemap: failed to open {} file {}/{} for reading: {}", + optional_string (file_type), + optional_string (dir_path), + optional_string (file_path), + strerror (errno) + ); return false; } ssize_t nread = do_read (fd, &header, sizeof (header)); if (nread <= 0) { if (nread < 0) { - log_error (LOG_ASSEMBLY, "typemap: failed to read {} file header from '{}/{}': {}", file_type, dir_path, file_path, strerror (errno)); + log_error ( + LOG_ASSEMBLY, + "typemap: failed to read {} file header from '{}/{}': {}", + optional_string (file_type), + optional_string (dir_path), + optional_string (file_path), + strerror (errno) + ); } else { - log_error (LOG_ASSEMBLY, "typemap: end of file while reading {} file header from '{}/{}'", file_type, dir_path, file_path); + log_error ( + LOG_ASSEMBLY, + "typemap: end of file while reading {} file header from '{}/{}'", + optional_string (file_type), + optional_string (dir_path), + optional_string (file_path) + ); } return false; } if (header.magic != expected_magic) { - log_error (LOG_ASSEMBLY, "typemap: invalid magic value in the {} file header from '{}/{}': expected {:x}, got {:x}", file_type, dir_path, file_path, expected_magic, header.magic); + log_error ( + LOG_ASSEMBLY, + "typemap: invalid magic value in the {} file header from '{}/{}': expected {:x}, got {:x}", + optional_string (file_type), + optional_string (dir_path), + optional_string (file_path), + expected_magic, + header.magic + ); return false; } if (header.version != MODULE_FORMAT_VERSION) { - log_error (LOG_ASSEMBLY, "typemap: incompatible {} format version. This build supports only version {}, file '{}/{}' uses version {}", file_type, MODULE_FORMAT_VERSION, dir_path, file_path, header.version); + log_error ( + LOG_ASSEMBLY, + "typemap: incompatible {} format version. This build supports only version {}, file '{}/{}' uses version {}", + optional_string (file_type), + MODULE_FORMAT_VERSION, + optional_string (dir_path), + optional_string (file_path), + header.version + ); return false; } @@ -1039,7 +1117,7 @@ EmbeddedAssemblies::typemap_load_index (TypeMapIndexHeader &header, size_t file_ std::unique_ptr EmbeddedAssemblies::typemap_load_index (int dir_fd, const char *dir_path, const char *index_path) { - log_debug (LOG_ASSEMBLY, "typemap: loading TypeMap index file '{}/{}'", dir_path, index_path); + log_debug (LOG_ASSEMBLY, "typemap: loading TypeMap index file '{}/{}'", optional_string (dir_path), optional_string (index_path)); TypeMapIndexHeader header; size_t file_size; @@ -1066,7 +1144,13 @@ EmbeddedAssemblies::typemap_load_file (BinaryTypeMapHeader &header, const char * ssize_t nread = do_read (file_fd, module.assembly_name, header.assembly_name_length); if (nread != static_cast(header.assembly_name_length)) { - log_error (LOG_ASSEMBLY, "typemap: failed to read map assembly name from '{}/{}': {}", dir_path, file_path, strerror (errno)); + log_error ( + LOG_ASSEMBLY, + "typemap: failed to read map assembly name from '{}/{}': {}", + optional_string (dir_path), + optional_string (file_path), + strerror (errno) + ); return false; } @@ -1076,13 +1160,13 @@ EmbeddedAssemblies::typemap_load_file (BinaryTypeMapHeader &header, const char * log_debug ( LOG_ASSEMBLY, "typemap: '{}/{}':: entry count == {}; Java name field width == {}; Managed name width == {}; assembly name length == {}; assembly name == {}", - dir_path, - file_path, + optional_string (dir_path), + optional_string (file_path), header.entry_count, header.java_name_width, header.managed_name_width, header.assembly_name_length, - module.assembly_name + optional_string (module.assembly_name) ); // [name][index] @@ -1096,7 +1180,7 @@ EmbeddedAssemblies::typemap_load_file (BinaryTypeMapHeader &header, const char * module.data = new uint8_t [data_size]; nread = do_read (file_fd, module.data, data_size); if (nread != static_cast(data_size)) { - log_error (LOG_ASSEMBLY, "typemap: failed to read map data from '{}/{}': {}", dir_path, file_path, strerror (errno)); + log_error (LOG_ASSEMBLY, "typemap: failed to read map data from '{}/{}': {}", optional_string (dir_path), optional_string (file_path), strerror (errno)); return false; } @@ -1140,7 +1224,7 @@ EmbeddedAssemblies::typemap_load_file (BinaryTypeMapHeader &header, const char * bool EmbeddedAssemblies::typemap_load_file (int dir_fd, const char *dir_path, const char *file_path, TypeMap &module) { - log_debug (LOG_ASSEMBLY, "typemap: loading TypeMap file '{}/{}'", dir_path, file_path); + log_debug (LOG_ASSEMBLY, "typemap: loading TypeMap file '{}/{}'", optional_string (dir_path), optional_string (file_path)); bool ret = true; BinaryTypeMapHeader header; @@ -1179,7 +1263,7 @@ EmbeddedAssemblies::register_from_apk (const char *apk_file, monodroid_should_re gather_bundled_assemblies_from_apk (apk_file, should_register); - log_info (LOG_ASSEMBLY, "Package '{}' contains {} assemblies", apk_file, number_of_found_assemblies - prev); + log_info (LOG_ASSEMBLY, "Package '{}' contains {} assemblies", optional_string (apk_file), number_of_found_assemblies - prev); return number_of_found_assemblies; } @@ -1283,10 +1367,10 @@ EmbeddedAssemblies::maybe_register_blob_from_filesystem ( force_inline size_t EmbeddedAssemblies::register_from_filesystem (const char *lib_dir_path,bool look_for_mangled_names, monodroid_should_register should_register) noexcept { - log_debug (LOG_ASSEMBLY, "Looking for assemblies in '{}'", lib_dir_path); + log_debug (LOG_ASSEMBLY, "Looking for assemblies in '{}'", optional_string (lib_dir_path)); DIR *lib_dir = opendir (lib_dir_path); // TODO: put it in a scope guard at some point if (lib_dir == nullptr) { - log_warn (LOG_ASSEMBLY, "Unable to open app library directory '{}': {}", lib_dir_path, std::strerror (errno)); + log_warn (LOG_ASSEMBLY, "Unable to open app library directory '{}': {}", optional_string (lib_dir_path), std::strerror (errno)); return 0; } @@ -1295,14 +1379,14 @@ EmbeddedAssemblies::register_from_filesystem (const char *lib_dir_path,bool look int dir_fd = dirfd (lib_dir); if (dir_fd < 0) [[unlikely]] { - log_warn (LOG_ASSEMBLY, "Unable to obtain file descriptor for directory '{}': {}", lib_dir_path, std::strerror (errno)); + log_warn (LOG_ASSEMBLY, "Unable to obtain file descriptor for directory '{}': {}", optional_string (lib_dir_path), std::strerror (errno)); closedir (lib_dir); return 0; } state.file_fd = dup (dir_fd); if (state.file_fd < 0) [[unlikely]] { - log_warn (LOG_ASSEMBLY, "Unable to duplicate file descriptor {} for directory '{}': {}", dir_fd, lib_dir_path, std::strerror (errno)); + log_warn (LOG_ASSEMBLY, "Unable to duplicate file descriptor {} for directory '{}': {}", dir_fd, optional_string (lib_dir_path), std::strerror (errno)); closedir (lib_dir); return 0; } @@ -1319,7 +1403,7 @@ EmbeddedAssemblies::register_from_filesystem (const char *lib_dir_path,bool look dirent *cur = readdir (lib_dir); if (cur == nullptr) { if (errno != 0) { - log_warn (LOG_ASSEMBLY, "Failed to open a directory entry from '{}': {}", lib_dir_path, std::strerror (errno)); + log_warn (LOG_ASSEMBLY, "Failed to open a directory entry from '{}': {}", optional_string (lib_dir_path), std::strerror (errno)); continue; // keep going, no harm } break; // No more entries, we're done @@ -1339,7 +1423,7 @@ EmbeddedAssemblies::register_from_filesystem (const char *lib_dir_path,bool look // ...and we can handle the runtime config entry if (!runtime_config_blob_found && std::strncmp (cur->d_name, SharedConstants::RUNTIME_CONFIG_BLOB_NAME.data (), SharedConstants::RUNTIME_CONFIG_BLOB_NAME.size ()) == 0) { - log_debug (LOG_ASSEMBLY, "Mapping runtime config blob from '{}'", cur->d_name); + log_debug (LOG_ASSEMBLY, "Mapping runtime config blob from '{}'", optional_string (cur->d_name)); auto file_size = Util::get_file_size_at (state.file_fd, cur->d_name); if (!file_size) { continue; diff --git a/src/native/monodroid/embedded-assemblies.hh b/src/native/monodroid/embedded-assemblies.hh index c17d957b4c2..341ecc2a086 100644 --- a/src/native/monodroid/embedded-assemblies.hh +++ b/src/native/monodroid/embedded-assemblies.hh @@ -310,7 +310,7 @@ namespace xamarin::android::internal { elf_header->e_ident[EI_MAG1] != ELFMAG1 || elf_header->e_ident[EI_MAG2] != ELFMAG2 || elf_header->e_ident[EI_MAG3] != ELFMAG3) { - log_debug (LOG_ASSEMBLY, "Not an ELF image: {}", file_name); + log_debug (LOG_ASSEMBLY, "Not an ELF image: {}", optional_string (file_name)); // Not an ELF image, just return what we mmapped before return { map_info.area, map_info.size }; } @@ -357,6 +357,11 @@ namespace xamarin::android::internal { force_inline static c_unique_ptr to_utf8 (const MonoString *s) noexcept { + if (s == nullptr) [[unlikely]] { + // We need to duplicate mono_string_to_utf8 behavior + return c_unique_ptr (strdup ("")); + } + return c_unique_ptr (mono_string_to_utf8 (const_cast(s))); } @@ -431,7 +436,7 @@ namespace xamarin::android::internal { } } } - log_debug (LOG_ASSEMBLY, "Unmangled name to '{}'", name.get ()); + log_debug (LOG_ASSEMBLY, "Unmangled name to '{}'", optional_string (name.get ())); }; private: diff --git a/src/native/monodroid/mono-image-loader.hh b/src/native/monodroid/mono-image-loader.hh index d843bf32188..48812d223b2 100644 --- a/src/native/monodroid/mono-image-loader.hh +++ b/src/native/monodroid/mono-image-loader.hh @@ -110,7 +110,7 @@ namespace xamarin::android::internal { force_inline static MonoImage* stash_and_return (MonoImage *image, MonoImageOpenStatus status, [[maybe_unused]] hash_t hash) noexcept { if (image == nullptr || status != MonoImageOpenStatus::MONO_IMAGE_OK) { - log_warn (LOG_ASSEMBLY, std::format ("Failed to open assembly image. {}", mono_image_strerror (status))); + log_warn (LOG_ASSEMBLY, "Failed to open assembly image. {}", optional_string (mono_image_strerror (status))); return nullptr; } diff --git a/src/native/monodroid/monodroid-glue.cc b/src/native/monodroid/monodroid-glue.cc index 49e614a4455..7a28622554f 100644 --- a/src/native/monodroid/monodroid-glue.cc +++ b/src/native/monodroid/monodroid-glue.cc @@ -174,12 +174,12 @@ MonodroidRuntime::open_from_update_dir (MonoAssemblyName *aname, [[maybe_unused] fullpath.append (SharedConstants::DLL_EXTENSION); } - log_debug (LOG_ASSEMBLY, "open_from_update_dir: trying to open assembly: {}", fullpath.get ()); + log_debug (LOG_ASSEMBLY, "open_from_update_dir: trying to open assembly: {}", optional_string (fullpath.get ())); if (Util::file_exists (fullpath.get ())) { MonoImageOpenStatus status{}; result = mono_assembly_open_full (fullpath.get (), &status, 0); if (result == nullptr || status != MonoImageOpenStatus::MONO_IMAGE_OK) { - log_warn (LOG_ASSEMBLY, "Failed to load managed assembly '{}'. {}", fullpath.get (), mono_image_strerror (status)); + log_warn (LOG_ASSEMBLY, "Failed to load managed assembly '{}'. {}", optional_string (fullpath.get ()), mono_image_strerror (status)); } } else { log_warn (LOG_ASSEMBLY, "open_from_update_dir: assembly file DOES NOT EXIST"sv); @@ -480,7 +480,7 @@ MonodroidRuntime::parse_runtime_args (dynamic_local_string arg (token); - log_error (LOG_DEFAULT, "Unknown runtime argument: '{}'", arg.get ()); + log_error (LOG_DEFAULT, "Unknown runtime argument: '{}'", optional_string (arg.get ())); ret = false; } } @@ -509,7 +509,7 @@ MonodroidRuntime::mono_runtime_init ([[maybe_unused]] JNIEnv *env, [[maybe_unuse cur_time = time (nullptr); if (!parse_runtime_args (runtime_args, &options)) { - log_error (LOG_DEFAULT, "Failed to parse runtime args: '{}'", runtime_args.get ()); + log_error (LOG_DEFAULT, "Failed to parse runtime args: '{}'", optional_string (runtime_args.get ())); } else if (options.debug && cur_time > options.timeout_time) { log_warn (LOG_DEBUGGER, "Not starting the debugger as the timeout value has been reached; current-time: {}; timeout: {}", cur_time, options.timeout_time); } else if (options.debug && cur_time <= options.timeout_time) { @@ -537,7 +537,7 @@ MonodroidRuntime::mono_runtime_init ([[maybe_unused]] JNIEnv *env, [[maybe_unuse // this text is used in unit tests to check the debugger started // do not change it without updating the test. - log_warn (LOG_DEBUGGER, "Trying to initialize the debugger with options: {}", debug_arg); + log_warn (LOG_DEBUGGER, "Trying to initialize the debugger with options: {}", optional_string (debug_arg)); if (options.out_port > 0) { int sock = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP); @@ -576,7 +576,7 @@ MonodroidRuntime::mono_runtime_init ([[maybe_unused]] JNIEnv *env, [[maybe_unuse LOG_DEBUGGER, std::format ( "Error accepting stdout and stderr ({}:{}): {}", - options.host, + optional_string (options.host), options.out_port, strerror (errno) ) @@ -591,7 +591,7 @@ MonodroidRuntime::mono_runtime_init ([[maybe_unused]] JNIEnv *env, [[maybe_unuse LOG_DEBUGGER, std::format ( "Error connecting stdout and stderr ({}:{}): {}", - options.host, + optional_string (options.host), options.out_port, strerror (errno) ) @@ -662,7 +662,7 @@ MonodroidRuntime::mono_runtime_init ([[maybe_unused]] JNIEnv *env, [[maybe_unuse if (AndroidSystem::monodroid_get_system_property (SharedConstants::DEBUG_MONO_RUNTIME_ARGS_PROPERTY, prop_val) > 0) { char **ptr; - log_warn (LOG_DEBUGGER, "passing '{}' as extra arguments to the runtime.", prop_val.get ()); + log_warn (LOG_DEBUGGER, "passing '{}' as extra arguments to the runtime.", optional_string (prop_val.get ())); char **args = Util::monodroid_strsplit (prop_val.get (), " ", 0); int argc = 0; @@ -731,8 +731,8 @@ MonodroidRuntime::create_domain (JNIEnv *env, jstring_array_wrapper &runtimeApks #if defined (DEBUG) log_fatal (LOG_DEFAULT, "No assemblies found in '{}' or '{}'. Assuming this is part of Fast Deployment. Exiting...", - AndroidSystem::override_dirs [0], - (AndroidSystem::override_dirs.size () > 1 && AndroidSystem::override_dirs [1] != nullptr) ? AndroidSystem::override_dirs [1] : ""sv + optional_string (AndroidSystem::override_dirs [0]), + (AndroidSystem::override_dirs.size () > 1 && AndroidSystem::override_dirs [1] != nullptr) ? optional_string (AndroidSystem::override_dirs [1]) : "" ); #else log_fatal (LOG_DEFAULT, "No assemblies (or assembly blobs) were found in the application APK file(s) or on the filesystem"sv); @@ -741,7 +741,7 @@ MonodroidRuntime::create_domain (JNIEnv *env, jstring_array_wrapper &runtimeApks Helpers::abort_application ( std::format ( "ALL entries in APK named `{}` MUST be STORED. Gradle's minification may COMPRESS such entries.", - assemblies_prefix + optional_string (assemblies_prefix) ) ); } @@ -942,7 +942,7 @@ MonodroidRuntime::init_android_runtime (JNIEnv *env, jclass runtimeClass, jobjec auto initialize = reinterpret_cast (mono_method_get_unmanaged_callers_only_ftnptr (method, &error)); if (initialize == nullptr) { - log_fatal (LOG_DEFAULT, "Failed to get pointer to Initialize. Mono error: {}", mono_error_get_message (&error)); + log_fatal (LOG_DEFAULT, "Failed to get pointer to Initialize. Mono error: {}", optional_string (mono_error_get_message (&error))); } abort_unless ( @@ -998,7 +998,7 @@ MonodroidRuntime::set_environment_variable_for_directory (const char *name, jstr if (createDirectory) { int rv = Util::create_directory (value.get_cstr (), mode); if (rv < 0 && errno != EEXIST) - log_warn (LOG_DEFAULT, "Failed to create directory for environment variable {}. {}", name, strerror (errno)); + log_warn (LOG_DEFAULT, "Failed to create directory for environment variable {}. {}", optional_string (name), strerror (errno)); } setenv (name, value.get_cstr (), 1); } @@ -1008,10 +1008,10 @@ MonodroidRuntime::create_xdg_directory (jstring_wrapper& home, size_t home_len, { static_local_string dir (home_len + relative_path.length ()); Util::path_combine (dir, home.get_cstr (), home_len, relative_path.data (), relative_path.length ()); - log_debug (LOG_DEFAULT, "Creating XDG directory: {}", dir.get ()); + log_debug (LOG_DEFAULT, "Creating XDG directory: {}", optional_string (dir.get ())); int rv = Util::create_directory (dir.get (), DEFAULT_DIRECTORY_MODE); if (rv < 0 && errno != EEXIST) - log_warn (LOG_DEFAULT, "Failed to create XDG directory {}. {}", dir.get (), strerror (errno)); + log_warn (LOG_DEFAULT, "Failed to create XDG directory {}. {}", optional_string (dir.get ()), strerror (errno)); if (!environment_variable_name.empty ()) { setenv (environment_variable_name.data (), dir.get (), 1); } @@ -1040,7 +1040,7 @@ MonodroidRuntime::set_debug_env_vars (void) noexcept return; auto log_envvar = [](const char *name, const char *v) { - log_debug (LOG_DEFAULT, "Env variable '{}' set to '{}'.", name, v); + log_debug (LOG_DEFAULT, "Env variable '{}' set to '{}'.", optional_string (name), optional_string (v)); }; string_segment arg_token; @@ -1060,7 +1060,7 @@ MonodroidRuntime::set_debug_env_vars (void) noexcept log_envvar (arg.get (), one.data ()); } else if (index == 0) { // ’=value’ - log_warn (LOG_DEFAULT, "Attempt to set environment variable without specifying name: '{}'", arg.get ()); + log_warn (LOG_DEFAULT, "Attempt to set environment variable without specifying name: '{}'", optional_string (arg.get ())); } else { // ’name=value’ arg[index] = '\0'; @@ -1140,10 +1140,10 @@ MonodroidRuntime::set_profile_options () noexcept .append (output_path.get (), output_path.length ()); } if (Util::create_directory (AndroidSystem::override_dirs[0], 0) < 0) { - log_warn (LOG_DEFAULT, "Failed to create directory '{}'. {}", AndroidSystem::override_dirs[0], std::strerror (errno)); + log_warn (LOG_DEFAULT, "Failed to create directory '{}'. {}", optional_string (AndroidSystem::override_dirs[0]), std::strerror (errno)); } - log_warn (LOG_DEFAULT, "Initializing profiler with options: {}", value.get ()); + log_warn (LOG_DEFAULT, "Initializing profiler with options: {}", optional_string (value.get ())); debug.monodroid_profiler_load (AndroidSystem::get_runtime_libdir (), value.get (), output_path.get ()); } @@ -1468,7 +1468,7 @@ MonodroidRuntime::Java_mono_android_Runtime_initInternal (JNIEnv *env, jclass kl if (runtimeNativeLibDir != nullptr) { jstr = runtimeNativeLibDir; AndroidSystem::set_runtime_libdir (strdup (jstr.get_cstr ())); - log_debug (LOG_DEFAULT, "Using runtime path: {}", AndroidSystem::get_runtime_libdir ()); + log_debug (LOG_DEFAULT, "Using runtime path: {}", optional_string (AndroidSystem::get_runtime_libdir ())); } AndroidSystem::setup_process_args (runtimeApks); diff --git a/src/native/monodroid/osbridge.cc b/src/native/monodroid/osbridge.cc index e909ab51ec2..4d03b3600bb 100644 --- a/src/native/monodroid/osbridge.cc +++ b/src/native/monodroid/osbridge.cc @@ -188,10 +188,10 @@ OSBridge::_write_stack_trace (FILE *to, char *from, LogCategories category) *end = '\0'; if ((category == LOG_GREF && gref_to_logcat) || (category == LOG_LREF && lref_to_logcat)) { - log_debug (category, "{}", m); + log_debug (category, "{}", optional_string (m)); } if (to != nullptr) { - fprintf (to, "%s\n", m); + fprintf (to, "%s\n", optional_string (m)); fflush (to); } *end = c; @@ -202,11 +202,11 @@ void OSBridge::_monodroid_gref_log (const char *message) { if (gref_to_logcat) { - log_debug (LOG_GREF, "{}", message); + log_debug (LOG_GREF, "{}", optional_string (message)); } if (!gref_log) return; - fprintf (gref_log, "%s", message); + fprintf (gref_log, "%s", optional_string (message)); fflush (gref_log); } @@ -216,6 +216,7 @@ OSBridge::_monodroid_gref_log_new (jobject curHandle, char curType, jobject newH int c = _monodroid_gref_inc (); if ((log_categories & LOG_GREF) == 0) return c; + log_info (LOG_GREF, "+g+ grefc {} gwrefc {} obj-handle {:p}/{} -> new-handle {:p}/{} from thread '{}'({})", c, @@ -224,14 +225,14 @@ OSBridge::_monodroid_gref_log_new (jobject curHandle, char curType, jobject newH curType, reinterpret_cast(newHandle), newType, - threadName, + optional_string (threadName), threadId ); if (gref_to_logcat) { if (from_writable) { _write_stack_trace (nullptr, const_cast(from), LOG_GREF); } else { - log_info (LOG_GREF, "{}", from); + log_info (LOG_GREF, "{}", optional_string (from)); } } if (!gref_log) @@ -243,7 +244,7 @@ OSBridge::_monodroid_gref_log_new (jobject curHandle, char curType, jobject newH curType, newHandle, newType, - threadName, + optional_string (threadName), threadId); if (from_writable) _write_stack_trace (gref_log, const_cast(from)); @@ -267,14 +268,14 @@ OSBridge::_monodroid_gref_log_delete (jobject handle, char type, const char *thr gc_weak_gref_count, reinterpret_cast(handle), type, - threadName, + optional_string (threadName), threadId ); if (gref_to_logcat) { if (from_writable) { _write_stack_trace (nullptr, const_cast(from), LOG_GREF); } else { - log_info (LOG_GREF, "{}", from); + log_info (LOG_GREF, "{}", optional_string (from)); } } if (!gref_log) @@ -284,12 +285,12 @@ OSBridge::_monodroid_gref_log_delete (jobject handle, char type, const char *thr gc_weak_gref_count, handle, type, - threadName, + optional_string (threadName), threadId); if (from_writable) _write_stack_trace (gref_log, const_cast(from)); else - fprintf (gref_log, "%s\n", from); + fprintf (gref_log, "%s\n", optional_string (from)); fflush (gref_log); } @@ -308,14 +309,14 @@ OSBridge::_monodroid_weak_gref_new (jobject curHandle, char curType, jobject new curType, reinterpret_cast(newHandle), newType, - threadName, + optional_string (threadName), threadId ); if (gref_to_logcat) { if (from_writable) { _write_stack_trace (nullptr, const_cast(from), LOG_GREF); } else { - log_info (LOG_GREF, "{}", from); + log_info (LOG_GREF, "{}", optional_string (from)); } } if (!gref_log) @@ -327,12 +328,12 @@ OSBridge::_monodroid_weak_gref_new (jobject curHandle, char curType, jobject new curType, newHandle, newType, - threadName, + optional_string (threadName), threadId); if (from_writable) _write_stack_trace (gref_log, const_cast(from)); else - fprintf (gref_log, "%s\n", from); + fprintf (gref_log, "%s\n", optional_string (from)); fflush (gref_log); } @@ -349,14 +350,14 @@ OSBridge::_monodroid_weak_gref_delete (jobject handle, char type, const char *th gc_weak_gref_count, reinterpret_cast(handle), type, - threadName, + optional_string (threadName), threadId ); if (gref_to_logcat) { if (from_writable) { _write_stack_trace (nullptr, const_cast(from), LOG_GREF); } else { - log_info (LOG_GREF, "{}", from); + log_info (LOG_GREF, "{}", optional_string (from)); } } if (!gref_log) @@ -366,12 +367,12 @@ OSBridge::_monodroid_weak_gref_delete (jobject handle, char type, const char *th gc_weak_gref_count, handle, type, - threadName, + optional_string (threadName), threadId); if (from_writable) _write_stack_trace (gref_log, const_cast(from)); else - fprintf (gref_log, "%s\n", from); + fprintf (gref_log, "%s\n", optional_string (from)); fflush (gref_log); } @@ -386,14 +387,14 @@ OSBridge::_monodroid_lref_log_new (int lrefc, jobject handle, char type, const c lrefc, reinterpret_cast(handle), type, - threadName, + optional_string (threadName), threadId ); if (lref_to_logcat) { if (from_writable) { _write_stack_trace (nullptr, const_cast(from), LOG_GREF); } else { - log_info (LOG_GREF, "{}", from); + log_info (LOG_GREF, "{}", optional_string (from)); } } if (!lref_log) @@ -402,12 +403,12 @@ OSBridge::_monodroid_lref_log_new (int lrefc, jobject handle, char type, const c lrefc, handle, type, - threadName, + optional_string (threadName), threadId); if (from_writable) _write_stack_trace (lref_log, const_cast(from)); else - fprintf (lref_log, "%s\n", from); + fprintf (lref_log, "%s\n", optional_string (from)); fflush (lref_log); } @@ -422,14 +423,14 @@ OSBridge::_monodroid_lref_log_delete (int lrefc, jobject handle, char type, cons lrefc, reinterpret_cast(handle), type, - threadName, + optional_string (threadName), threadId ); if (lref_to_logcat) { if (from_writable) { _write_stack_trace (nullptr, const_cast(from), LOG_GREF); } else { - log_info (LOG_GREF, "{}", from); + log_info (LOG_GREF, "{}", optional_string (from)); } } if (!lref_log) @@ -438,12 +439,12 @@ OSBridge::_monodroid_lref_log_delete (int lrefc, jobject handle, char type, cons lrefc, handle, type, - threadName, + optional_string (threadName), threadId); if (from_writable) _write_stack_trace (lref_log, const_cast(from)); else - fprintf (lref_log, "%s\n", from); + fprintf (lref_log, "%s\n", optional_string (from)); fflush (lref_log); } @@ -543,8 +544,8 @@ OSBridge::gc_bridge_class_kind (MonoClass *klass) if (i == static_cast (-NUM_GC_BRIDGE_TYPES)) { log_info (LOG_GC, "asked if a class {}.{} is a bridge before we inited java.lang.Object", - mono_class_get_namespace (klass), - mono_class_get_name (klass) + optional_string (mono_class_get_namespace (klass)), + optional_string (mono_class_get_name (klass)) ); return MonoGCBridgeObjectKind::GC_BRIDGE_TRANSPARENT_CLASS; } @@ -571,8 +572,8 @@ OSBridge::gc_is_bridge_object (MonoObject *object) MonoClass *mclass = mono_object_get_class (object); log_info (LOG_GC, "object of class {}.{} with null handle", - mono_class_get_namespace (mclass), - mono_class_get_name (mclass) + optional_string (mono_class_get_namespace (mclass)), + optional_string (mono_class_get_name (mclass)) ); #endif return 0; @@ -659,9 +660,9 @@ OSBridge::add_reference (JNIEnv *env, OSBridge::AddReferenceTarget target, OSBri *reffed_description = describe_target (reffed_target); if (success) - log_warn (LOG_GC, "Added reference for {} to {}", description, reffed_description); + log_warn (LOG_GC, "Added reference for {} to {}", optional_string (description), optional_string (reffed_description)); else - log_error (LOG_GC, "Missing monodroidAddReference method for {}", description); + log_error (LOG_GC, "Missing monodroidAddReference method for {}", optional_string (description)); free (description); free (reffed_description); @@ -899,8 +900,8 @@ OSBridge::gc_cleanup_after_java_collection (JNIEnv *env, int num_sccs, MonoGCBri klass = mono_object_get_class (obj); log_error (LOG_GC, "Missing monodroidClearReferences method for object of class {}.{}", - mono_class_get_namespace (klass), - mono_class_get_name (klass) + optional_string (mono_class_get_namespace (klass)), + optional_string (mono_class_get_name (klass)) ); } #endif @@ -965,8 +966,8 @@ OSBridge::gc_cross_references (int num_sccs, MonoGCBridgeSCC **sccs, int num_xre log_info (LOG_GC, "\tobj {:p} [{}::{}] handle {:p} key_handle {:p}", reinterpret_cast(obj), - mono_class_get_namespace (klass), - mono_class_get_name (klass), + optional_string (mono_class_get_namespace (klass)), + optional_string (mono_class_get_name (klass)), reinterpret_cast(handle), key_handle ); diff --git a/src/native/monodroid/xamarin-android-app-context.cc b/src/native/monodroid/xamarin-android-app-context.cc index 75973eb020e..9ef193ddeb7 100644 --- a/src/native/monodroid/xamarin-android-app-context.cc +++ b/src/native/monodroid/xamarin-android-app-context.cc @@ -44,8 +44,8 @@ MonodroidRuntime::get_function_pointer (uint32_t mono_image_index, uint32_t clas log_debug ( LOG_ASSEMBLY, "MM: Trying to look up pointer to method '{}' (token {:x}) in class '{}' (index {})", - get_method_name (mono_image_index, method_token), method_token, - get_class_name (class_index), class_index + optional_string (get_method_name (mono_image_index, method_token)), method_token, + optional_string (get_class_name (class_index)), class_index ); if (class_index >= marshal_methods_number_of_classes) [[unlikely]] { @@ -81,7 +81,7 @@ MonodroidRuntime::get_function_pointer (uint32_t mono_image_index, uint32_t clas log_debug ( LOG_ASSEMBLY, "Loaded pointer to method {} ({:p}) (mono_image_index == {}; class_index == {}; method_token == {:x})", - mono_method_full_name (method, true), + optional_string (mono_method_full_name (method, true)), ret, mono_image_index, class_index, @@ -93,8 +93,8 @@ MonodroidRuntime::get_function_pointer (uint32_t mono_image_index, uint32_t clas log_fatal ( LOG_DEFAULT, "Failed to obtain function pointer to method '{}' in class '{}'", - get_method_name (mono_image_index, method_token), - get_class_name (class_index) + optional_string (get_method_name (mono_image_index, method_token)), + optional_string (get_class_name (class_index)) ); log_fatal ( diff --git a/src/native/monodroid/xamarin_getifaddrs.cc b/src/native/monodroid/xamarin_getifaddrs.cc index 57c4935a7bf..23848f9910b 100644 --- a/src/native/monodroid/xamarin_getifaddrs.cc +++ b/src/native/monodroid/xamarin_getifaddrs.cc @@ -962,7 +962,7 @@ get_link_address (const struct nlmsghdr *message, struct _monodroid_ifaddrs **if log_debug (LOG_NETLINK, " address has no name/label, getting one from interface"sv); ifa->ifa_name = name ? strdup (name) : NULL; } - log_debug (LOG_NETLINK, " address label: {}", ifa->ifa_name); + log_debug (LOG_NETLINK, " address label: {}", optional_string (ifa->ifa_name)); if (calculate_address_netmask (ifa, net_address) < 0) { goto error; @@ -1017,7 +1017,7 @@ get_link_info (const struct nlmsghdr *message) } if (Util::should_log (LOG_NETLINK)) { log_debug_nocheck_fmt (LOG_NETLINK, " interface name (payload length: {}; string length: {})", RTA_PAYLOAD (attribute), strlen (ifa->ifa_name)); - log_debug_nocheck_fmt (LOG_NETLINK, " {}", ifa->ifa_name); + log_debug_nocheck_fmt (LOG_NETLINK, " {}", optional_string (ifa->ifa_name)); } break; @@ -1150,7 +1150,7 @@ print_ifla_name (int id) i++; continue; } - log_info_nocheck_fmt (LOG_NETLINK, "ifla->name: {} ({})", iflas [i].name, iflas [i].value); + log_info_nocheck_fmt (LOG_NETLINK, "ifla->name: {} ({})", optional_string (iflas [i].name), iflas [i].value); break; } } @@ -1180,7 +1180,7 @@ print_address_list (const char title[], struct _monodroid_ifaddrs *list) cur = cur->ifa_next; } - log_info_nocheck_fmt (LOG_NETLINK, "{}: {}", title, msg ? msg : "[no addresses]"sv); + log_info_nocheck_fmt (LOG_NETLINK, "{}: {}", title, optional_string (msg, "[no addresses]")); free (msg); } #endif diff --git a/src/native/pinvoke-override/pinvoke-override-api-impl.hh b/src/native/pinvoke-override/pinvoke-override-api-impl.hh index f6c402c46e7..259a0d5c879 100644 --- a/src/native/pinvoke-override/pinvoke-override-api-impl.hh +++ b/src/native/pinvoke-override/pinvoke-override-api-impl.hh @@ -23,21 +23,21 @@ namespace xamarin::android { constexpr bool PREFER_AOT_CACHE = false; lib_handle = internal::MonodroidDl::monodroid_dlopen (library_name, MONO_DL_LOCAL, nullptr, PREFER_AOT_CACHE); if (lib_handle == nullptr) { - log_warn (LOG_ASSEMBLY, "Shared library '{}' not loaded, p/invoke '{}' may fail", library_name, symbol_name); + log_warn (LOG_ASSEMBLY, "Shared library '{}' not loaded, p/invoke '{}' may fail", optional_string (library_name), optional_string (symbol_name)); return nullptr; } if (dso_handle != nullptr) { void *expected_null = nullptr; if (!__atomic_compare_exchange (dso_handle, &expected_null, &lib_handle, false /* weak */, __ATOMIC_ACQUIRE /* success_memorder */, __ATOMIC_RELAXED /* xxxfailure_memorder */)) { - log_debug (LOG_ASSEMBLY, "Library '{}' handle already cached by another thread", library_name); + log_debug (LOG_ASSEMBLY, "Library '{}' handle already cached by another thread", optional_string (library_name)); } } } void *entry_handle = internal::MonodroidDl::monodroid_dlsym (lib_handle, symbol_name, nullptr, nullptr); if (entry_handle == nullptr) { - log_warn (LOG_ASSEMBLY, "Symbol '{}' not found in shared library '{}', p/invoke may fail", symbol_name, library_name); + log_warn (LOG_ASSEMBLY, "Symbol '{}' not found in shared library '{}', p/invoke may fail", optional_string (library_name), optional_string (symbol_name)); return nullptr; } @@ -147,7 +147,7 @@ namespace xamarin::android { handle = fetch_or_create_pinvoke_map_entry (lib_name, entry_name, entrypoint_name_hash, lib_map, /* need_lock */ false); } else { if (iter->second == nullptr) [[unlikely]] { - log_warn (LOG_ASSEMBLY, "Internal error: null entry in p/invoke map for key '{}'", library_name); + log_warn (LOG_ASSEMBLY, "Internal error: null entry in p/invoke map for key '{}'", optional_string (library_name)); return nullptr; // fall back to `monodroid_dlopen` } diff --git a/src/native/pinvoke-override/precompiled.cc b/src/native/pinvoke-override/precompiled.cc index e5c54608ff3..29ac736e433 100644 --- a/src/native/pinvoke-override/precompiled.cc +++ b/src/native/pinvoke-override/precompiled.cc @@ -22,18 +22,19 @@ PinvokeOverride::monodroid_pinvoke_override (const char *library_name, const cha PinvokeEntry *entry = find_pinvoke_address (entrypoint_hash, internal_pinvokes.data (), internal_pinvokes_count); if (entry == nullptr) [[unlikely]] { - log_fatal (LOG_ASSEMBLY, "Internal p/invoke symbol '{} @ {}' (hash: {:x}) not found in compile-time map.", library_name, entrypoint_name, entrypoint_hash); + log_fatal (LOG_ASSEMBLY, "Internal p/invoke symbol '{} @ {}' (hash: {:x}) not found in compile-time map.", + optional_string (library_name), optional_string (entrypoint_name), entrypoint_hash); log_fatal (LOG_ASSEMBLY, "compile-time map contents:"sv); for (size_t i = 0uz; i < internal_pinvokes_count; i++) { PinvokeEntry const& e = internal_pinvokes[i]; - log_fatal (LOG_ASSEMBLY, "\t'{}'={:p} (hash: {:x})", e.name, e.func, e.hash); + log_fatal (LOG_ASSEMBLY, "\t'{}'={:p} (hash: {:x})", optional_string (e.name), e.func, e.hash); } Helpers::abort_application ( LOG_ASSEMBLY, std::format ( "Failure handling a p/invoke request for '{}'@'{}'", - entrypoint_name, - library_name + optional_string (entrypoint_name), + optional_string (library_name) ) ); } @@ -67,7 +68,8 @@ PinvokeOverride::monodroid_pinvoke_override (const char *library_name, const cha load_library_entry (library_name, entrypoint_name, *entry, dotnet_dso_handle); if (entry->func == nullptr) { - log_fatal (LOG_ASSEMBLY, "Failed to load symbol '{}' from shared library '{}'", entrypoint_name, library_name); + log_fatal (LOG_ASSEMBLY, "Failed to load symbol '{}' from shared library '{}'", + optional_string (entrypoint_name), optional_string (library_name)); return nullptr; // let Mono deal with the fallout } @@ -75,7 +77,8 @@ PinvokeOverride::monodroid_pinvoke_override (const char *library_name, const cha } // It's possible we don't have an entry for some `dotnet` p/invoke, fall back to the slow path below - log_debug (LOG_ASSEMBLY, "Symbol '{}' in library '{}' not found in the generated tables, falling back to slow path", entrypoint_name, library_name); + log_debug (LOG_ASSEMBLY, "Symbol '{}' in library '{}' not found in the generated tables, falling back to slow path", + optional_string (entrypoint_name), optional_string (library_name)); } return handle_other_pinvoke_request (library_name, library_name_hash, entrypoint_name, entrypoint_hash); diff --git a/src/native/runtime-base/logger.cc b/src/native/runtime-base/logger.cc index a331d7112bb..dcc93d08d7e 100644 --- a/src/native/runtime-base/logger.cc +++ b/src/native/runtime-base/logger.cc @@ -29,13 +29,11 @@ namespace { if (path && access (path, W_OK) < 0) { log_warn (category, - std::format ( - "Could not open path '{}' for logging (\"{}\"). Using '{}/{}' instead.", - path, - strerror (errno), - override_dir, - filename - ) + "Could not open path '{}' for logging (\"{}\"). Using '{}/{}' instead.", + optional_string (path), + strerror (errno), + optional_string (override_dir), + optional_string (filename) ); path = NULL; } @@ -53,7 +51,7 @@ namespace { if (f) { Util::set_world_accessable (path); } else { - log_warn (category, std::format ("Could not open path '{}' for logging: {}", path, strerror (errno))); + log_warn (category, "Could not open path '{}' for logging: {}", optional_string (path), strerror (errno)); } free (p); @@ -79,12 +77,12 @@ Logger::set_debugger_log_level (const char *level) noexcept unsigned long v = strtoul (level, nullptr, 0); if (v == std::numeric_limits::max () && errno == ERANGE) { - log_error (LOG_DEFAULT, std::format ("Invalid debugger log level value '{}', expecting a positive integer or zero", level)); + log_error (LOG_DEFAULT, "Invalid debugger log level value '{}', expecting a positive integer or zero", level); return; } if (v > std::numeric_limits::max ()) { - log_warn (LOG_DEFAULT, std::format ("Debugger log level value is higher than the maximum of {}, resetting to the maximum value.", std::numeric_limits::max ())); + log_warn (LOG_DEFAULT, "Debugger log level value is higher than the maximum of {}, resetting to the maximum value.", std::numeric_limits::max ()); v = std::numeric_limits::max (); } diff --git a/src/native/shared/helpers.hh b/src/native/shared/helpers.hh index c69d49d7ee3..62aeea9e00e 100644 --- a/src/native/shared/helpers.hh +++ b/src/native/shared/helpers.hh @@ -86,5 +86,15 @@ namespace xamarin::android { return reinterpret_cast(reinterpret_cast(ptr) + offset); } + + [[gnu::always_inline]] + static inline constexpr auto optional_string (const char* s, const char *replacement = nullptr) noexcept -> const char* + { + if (s != nullptr) [[likely]] { + return s; + } + + return replacement == nullptr ? "" : replacement; + } } #endif // __HELPERS_HH diff --git a/src/native/xamarin-debug-app-helper/debug-app-helper.cc b/src/native/xamarin-debug-app-helper/debug-app-helper.cc index ac3e9e75e81..e64c42750c8 100644 --- a/src/native/xamarin-debug-app-helper/debug-app-helper.cc +++ b/src/native/xamarin-debug-app-helper/debug-app-helper.cc @@ -48,7 +48,7 @@ Java_mono_android_DebugRuntime_init (JNIEnv *env, [[maybe_unused]] jclass klass, if (runtimeNativeLibDir != nullptr) { jstr = runtimeNativeLibDir; AndroidSystem::set_runtime_libdir (Util::strdup_new (jstr.get_cstr ())); - log_warn (LOG_DEFAULT, "Using runtime path: {}", AndroidSystem::get_runtime_libdir ()); + log_warn (LOG_DEFAULT, "Using runtime path: {}", optional_string (AndroidSystem::get_runtime_libdir ())); } const char *monosgen_path = get_libmonosgen_path (); @@ -75,7 +75,9 @@ copy_file_to_internal_location (char *to_dir, char *from_dir, char *file) log_warn (LOG_DEFAULT, "Copying file `{}` from external location `{}` to internal location `{}`", - file, from_dir, to_dir + optional_string (file), + optional_string (from_dir), + optional_string (to_dir) ); to_file = Util::path_combine (to_dir, file); @@ -84,12 +86,12 @@ copy_file_to_internal_location (char *to_dir, char *from_dir, char *file) int r = unlink (to_file); if (r < 0 && errno != ENOENT) { - log_warn (LOG_DEFAULT, "Unable to delete file `{}`: {}", to_file, strerror (errno)); + log_warn (LOG_DEFAULT, "Unable to delete file `{}`: {}", optional_string (to_file), strerror (errno)); break; } if (!Util::file_copy (to_file, from_file)) { - log_warn (LOG_DEFAULT, "Copy failed from `{}` to `{}`: {}", from_file, to_file, strerror (errno)); + log_warn (LOG_DEFAULT, "Copy failed from `{}` to `{}`: {}", optional_string (from_file), optional_string (to_file), strerror (errno)); break; } @@ -108,22 +110,22 @@ copy_native_libraries_to_internal_location () dirent *e; char *dir_path = Util::path_combine (od, "lib"); - log_warn (LOG_DEFAULT, "checking directory: `{}`", dir_path); + log_warn (LOG_DEFAULT, "checking directory: `{}`", optional_string (dir_path)); if (dir_path == nullptr || !Util::directory_exists (dir_path)) { - log_warn (LOG_DEFAULT, "directory does not exist: `{}`", dir_path); + log_warn (LOG_DEFAULT, "directory does not exist: `{}`", optional_string (dir_path)); delete[] dir_path; continue; } if ((dir = ::opendir (dir_path)) == nullptr) { - log_warn (LOG_DEFAULT, "could not open directory: `{}`", dir_path); + log_warn (LOG_DEFAULT, "could not open directory: `{}`", optional_string (dir_path)); delete[] dir_path; continue; } while ((e = readdir (dir)) != nullptr) { - log_warn (LOG_DEFAULT, "checking file: `{}`", e->d_name); + log_warn (LOG_DEFAULT, "checking file: `{}`", optional_string (e->d_name)); if (Util::monodroid_dirent_hasextension (e, ".so")) { copy_file_to_internal_location (AndroidSystem::get_primary_override_dir (), dir_path, e->d_name); } @@ -140,9 +142,9 @@ runtime_exists (const char *dir, char*& libmonoso) return false; libmonoso = Util::path_combine (dir, SharedConstants::MONO_SGEN_SO); - log_warn (LOG_DEFAULT, "Checking whether Mono runtime exists at: {}", libmonoso); + log_warn (LOG_DEFAULT, "Checking whether Mono runtime exists at: {}", optional_string (libmonoso)); if (Util::file_exists (libmonoso)) { - log_info (LOG_DEFAULT, "Mono runtime found at: {}", libmonoso); + log_info (LOG_DEFAULT, "Mono runtime found at: {}", optional_string (libmonoso)); return true; } delete[] libmonoso; @@ -194,7 +196,7 @@ get_libmonosgen_path () if (!Util::file_exists (link)) { int result = symlink (libmonoso, link); if (result != 0 && errno == EEXIST) { - log_warn (LOG_DEFAULT, "symlink exists, recreating: {} -> {}", link, libmonoso); + log_warn (LOG_DEFAULT, "symlink exists, recreating: {} -> {}", optional_string (link), optional_string (libmonoso)); unlink (link); result = symlink (libmonoso, link); } @@ -205,7 +207,7 @@ get_libmonosgen_path () libmonoso = link; } - log_warn (LOG_DEFAULT, "Trying to load sgen from: {}", libmonoso != nullptr ? libmonoso : ""sv); + log_warn (LOG_DEFAULT, "Trying to load sgen from: {}", optional_string (libmonoso)); if (libmonoso != nullptr && Util::file_exists (libmonoso)) return libmonoso; delete[] libmonoso; @@ -217,11 +219,11 @@ get_libmonosgen_path () for (const char *od : AndroidSystem::override_dirs) { if (od == nullptr) continue; - log_fatal (LOG_DEFAULT, " %s", od); + log_fatal (LOG_DEFAULT, " {}", optional_string (od)); } for (const char *app_lib_dir : AndroidSystem::app_lib_directories) { - log_fatal (LOG_DEFAULT, " %s", app_lib_dir); + log_fatal (LOG_DEFAULT, " {}", optional_string (app_lib_dir)); } Helpers::abort_application ( From 36a5945e2b4d5f2559edc2506cce805f97eb717f Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Mon, 2 Dec 2024 22:15:16 +0100 Subject: [PATCH 48/54] Beginnings of CLR hosting --- Xamarin.Android.sln | 7 + .../xaprepare/ConfigAndData/Configurables.cs | 1 + .../xaprepare/Steps/Step_GenerateFiles.cs | 18 +- src/native-clr/.gitignore | 2 + src/native-clr/CMakeLists.txt | 517 ++++++++++ src/native-clr/CMakePresets.json.in | 324 ++++++ src/native-clr/host/CMakeLists.txt | 155 +++ src/native-clr/host/host-jni.cc | 43 + src/native-clr/host/host.cc | 11 + src/native-clr/include/constants.hh | 96 ++ src/native-clr/include/host/host-jni.hh | 48 + src/native-clr/include/host/host.hh | 13 + .../include/runtime-base/android-system.hh | 39 + .../include/runtime-base/strings.hh | 920 ++++++++++++++++++ src/native-clr/include/shared/cpp-util.hh | 212 ++++ src/native-clr/include/shared/helpers.hh | 105 ++ src/native-clr/include/shared/log_level.hh | 26 + src/native-clr/include/shared/log_types.hh | 112 +++ src/native-clr/include/shared/xxhash.hh | 192 ++++ src/native-clr/include/startup/zip.hh | 31 + src/native-clr/include/xamarin-app.hh | 380 ++++++++ src/native-clr/java-interop/CMakeLists.txt | 50 + src/native-clr/libnet-android.map.txt | 12 + src/native-clr/lz4/CMakeLists.txt | 41 + src/native-clr/native-clr.csproj | 22 + src/native-clr/native-clr.targets | 144 +++ src/native-clr/runtime-base/CMakeLists.txt | 55 ++ src/native-clr/runtime-base/android-system.cc | 134 +++ src/native-clr/shared/CMakeLists.txt | 59 ++ src/native-clr/shared/helpers.cc | 46 + src/native-clr/shared/log_functions.cc | 131 +++ src/native-clr/startup/CMakeLists.txt | 52 + src/native-clr/startup/zip.cc | 3 + .../xamarin-app-stub/CMakeLists.txt | 54 + .../xamarin-app-stub/application_dso_stub.cc | 297 ++++++ 35 files changed, 4349 insertions(+), 3 deletions(-) create mode 100644 src/native-clr/.gitignore create mode 100644 src/native-clr/CMakeLists.txt create mode 100644 src/native-clr/CMakePresets.json.in create mode 100644 src/native-clr/host/CMakeLists.txt create mode 100644 src/native-clr/host/host-jni.cc create mode 100644 src/native-clr/host/host.cc create mode 100644 src/native-clr/include/constants.hh create mode 100644 src/native-clr/include/host/host-jni.hh create mode 100644 src/native-clr/include/host/host.hh create mode 100644 src/native-clr/include/runtime-base/android-system.hh create mode 100644 src/native-clr/include/runtime-base/strings.hh create mode 100644 src/native-clr/include/shared/cpp-util.hh create mode 100644 src/native-clr/include/shared/helpers.hh create mode 100644 src/native-clr/include/shared/log_level.hh create mode 100644 src/native-clr/include/shared/log_types.hh create mode 100644 src/native-clr/include/shared/xxhash.hh create mode 100644 src/native-clr/include/startup/zip.hh create mode 100644 src/native-clr/include/xamarin-app.hh create mode 100644 src/native-clr/java-interop/CMakeLists.txt create mode 100644 src/native-clr/libnet-android.map.txt create mode 100644 src/native-clr/lz4/CMakeLists.txt create mode 100644 src/native-clr/native-clr.csproj create mode 100644 src/native-clr/native-clr.targets create mode 100644 src/native-clr/runtime-base/CMakeLists.txt create mode 100644 src/native-clr/runtime-base/android-system.cc create mode 100644 src/native-clr/shared/CMakeLists.txt create mode 100644 src/native-clr/shared/helpers.cc create mode 100644 src/native-clr/shared/log_functions.cc create mode 100644 src/native-clr/startup/CMakeLists.txt create mode 100644 src/native-clr/startup/zip.cc create mode 100644 src/native-clr/xamarin-app-stub/CMakeLists.txt create mode 100644 src/native-clr/xamarin-app-stub/application_dso_stub.cc diff --git a/Xamarin.Android.sln b/Xamarin.Android.sln index f42d1822c74..e8d5317bbd0 100644 --- a/Xamarin.Android.sln +++ b/Xamarin.Android.sln @@ -125,6 +125,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Android.Sdk.Analy EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "proguard-android", "src\proguard-android\proguard-android.csproj", "{5FD0133B-69E5-4474-9B67-9FD1D0150C70}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "native-clr", "src\native-clr\native-clr.csproj", "{AD6DF548-2BC0-44E2-9ADC-28B4A23A1F5B}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|AnyCPU = Debug|AnyCPU @@ -347,6 +349,10 @@ Global {5FD0133B-69E5-4474-9B67-9FD1D0150C70}.Debug|AnyCPU.Build.0 = Debug|Any CPU {5FD0133B-69E5-4474-9B67-9FD1D0150C70}.Release|AnyCPU.ActiveCfg = Release|Any CPU {5FD0133B-69E5-4474-9B67-9FD1D0150C70}.Release|AnyCPU.Build.0 = Release|Any CPU + {AD6DF548-2BC0-44E2-9ADC-28B4A23A1F5B}.Debug|AnyCPU.ActiveCfg = Debug|Any CPU + {AD6DF548-2BC0-44E2-9ADC-28B4A23A1F5B}.Debug|AnyCPU.Build.0 = Debug|Any CPU + {AD6DF548-2BC0-44E2-9ADC-28B4A23A1F5B}.Release|AnyCPU.ActiveCfg = Release|Any CPU + {AD6DF548-2BC0-44E2-9ADC-28B4A23A1F5B}.Release|AnyCPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -406,6 +412,7 @@ Global {A39B6D7C-6616-40D6-8AE4-C6CEE93D2708} = {CAB438D8-B0F5-4AF0-BEBD-9E2ADBD7B483} {5E806C9F-1B67-4B6B-A6AB-258834250DBB} = {FFCF518F-2A4A-40A2-9174-2EE13B76C723} {5FD0133B-69E5-4474-9B67-9FD1D0150C70} = {FFCF518F-2A4A-40A2-9174-2EE13B76C723} + {AD6DF548-2BC0-44E2-9ADC-28B4A23A1F5B} = {FFCF518F-2A4A-40A2-9174-2EE13B76C723} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {53A1F287-EFB2-4D97-A4BB-4A5E145613F6} diff --git a/build-tools/xaprepare/xaprepare/ConfigAndData/Configurables.cs b/build-tools/xaprepare/xaprepare/ConfigAndData/Configurables.cs index 103d07403fc..a893fc1a96d 100644 --- a/build-tools/xaprepare/xaprepare/ConfigAndData/Configurables.cs +++ b/build-tools/xaprepare/xaprepare/ConfigAndData/Configurables.cs @@ -175,6 +175,7 @@ public static partial class Paths public static readonly string ExternalGitDepsDestDir = ExternalDir; public static readonly string ExternalXamarinAndroidToolsSln = Path.Combine (ExternalDir, "xamarin-android-tools", "Xamarin.Android.Tools.sln"); public static readonly string NativeSourcesDir = Path.Combine (BuildPaths.XamarinAndroidSourceRoot, "src", "native"); + public static readonly string NativeCLRSourcesDir = Path.Combine (BuildPaths.XamarinAndroidSourceRoot, "src", "native-clr"); // Dynamic locations used throughout the code public static string ExternalJavaInteropDir => GetCachedPath (ref externalJavaInteropDir, () => ctx.Properties.GetRequiredValue (KnownProperties.JavaInteropFullPath)); diff --git a/build-tools/xaprepare/xaprepare/Steps/Step_GenerateFiles.cs b/build-tools/xaprepare/xaprepare/Steps/Step_GenerateFiles.cs index 167c48515f1..178fffce84b 100644 --- a/build-tools/xaprepare/xaprepare/Steps/Step_GenerateFiles.cs +++ b/build-tools/xaprepare/xaprepare/Steps/Step_GenerateFiles.cs @@ -58,6 +58,7 @@ protected override async Task Execute (Context context) Get_Configuration_Generated_Props (context), Get_Cmake_XA_Build_Configuration (context), Get_Cmake_Presets (context), + Get_Cmake_Presets_CLR (context), }; } else { return new List { @@ -66,6 +67,7 @@ protected override async Task Execute (Context context) Get_Configuration_Generated_Props (context), Get_Cmake_XA_Build_Configuration (context), Get_Cmake_Presets (context), + Get_Cmake_Presets_CLR (context), Get_Ndk_projitems (context), Get_XABuildConfig_cs (context), Get_Omnisharp_Json (context), @@ -107,7 +109,7 @@ GeneratedFile Get_Cmake_XA_Build_Configuration (Context context) ); } - GeneratedFile Get_Cmake_Presets (Context context) + GeneratedFile GetCmakePresetsCommon (Context context, string sourcesDir) { const string OutputFileName = "CMakePresets.json"; @@ -126,11 +128,21 @@ GeneratedFile Get_Cmake_Presets (Context context) return new GeneratedPlaceholdersFile ( replacements, - Path.Combine (Configurables.Paths.NativeSourcesDir, $"{OutputFileName}.in"), - Path.Combine (Configurables.Paths.NativeSourcesDir, OutputFileName) + Path.Combine (sourcesDir, $"{OutputFileName}.in"), + Path.Combine (sourcesDir, OutputFileName) ); } + GeneratedFile Get_Cmake_Presets (Context context) + { + return GetCmakePresetsCommon (context, Configurables.Paths.NativeSourcesDir); + } + + GeneratedFile Get_Cmake_Presets_CLR (Context context) + { + return GetCmakePresetsCommon (context, Configurables.Paths.NativeCLRSourcesDir); + } + GeneratedFile Get_Configuration_Generated_Props (Context context) { const string OutputFileName = "Configuration.Generated.props"; diff --git a/src/native-clr/.gitignore b/src/native-clr/.gitignore new file mode 100644 index 00000000000..34d21e62347 --- /dev/null +++ b/src/native-clr/.gitignore @@ -0,0 +1,2 @@ +CMakeUserPresets.json +CMakePresets.json diff --git a/src/native-clr/CMakeLists.txt b/src/native-clr/CMakeLists.txt new file mode 100644 index 00000000000..3f2a4c627a0 --- /dev/null +++ b/src/native-clr/CMakeLists.txt @@ -0,0 +1,517 @@ +cmake_minimum_required(VERSION 3.21) + +# +# Read product version +# +file(STRINGS "../../Directory.Build.props" XA_PRODUCT_VERSION_XML REGEX "^[ \t]*(.*)") +string(REGEX REPLACE "^[ \t]*(.*)" "\\1" XA_VERSION "${XA_PRODUCT_VERSION_XML}") + +project( + android-native-bits + VERSION ${XA_VERSION} + DESCRIPTION ".NET for Android native runtime" + HOMEPAGE_URL "https://github.com/dotnet/android" + LANGUAGES CXX C ASM +) + +# +# Sanity checks +# +macro(ensure_variable_set VARNAME) + if(NOT ${VARNAME}) + message(FATAL_ERROR "Variable ${VARNAME} not set. Please set it either on command line with -D${VARNAME}=value or in the presets file") + endif() +endmacro() + +ensure_variable_set(ANDROID_ABI) +ensure_variable_set(CMAKE_ANDROID_NDK) +ensure_variable_set(CMAKE_BUILD_TYPE) +ensure_variable_set(OUTPUT_PATH) +ensure_variable_set(XA_BUILD_CONFIGURATION) +ensure_variable_set(XA_LIB_TOP_DIR) + +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${OUTPUT_PATH}/${ANDROID_RID}" CACHE PATH "" FORCE) +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${OUTPUT_PATH}/${ANDROID_RID}" CACHE PATH "" FORCE) + +set(CMAKE_CXX_STANDARD 23) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) + +set(CMAKE_C_STANDARD 11) +set(CMAKE_C_STANDARD_REQUIRED ON) +set(CMAKE_C_EXTENSIONS OFF) + +include("${CMAKE_ANDROID_NDK}/build/cmake/abis.cmake") +#include("${CMAKE_SOURCE_DIR}/cmake/ArchiveDSOStub.cmake") + +if(CMAKE_BUILD_TYPE STREQUAL Debug) + set(DEBUG_BUILD True) +else() + set(DEBUG_BUILD False) +endif() + +set(XA_NO_INLINE "$ENV{XA_NO_INLINE}") +if(XA_NO_INLINE) + set(DONT_INLINE_DEFAULT ON) +else() + set(DONT_INLINE_DEFAULT OFF) +endif() + +set(XA_NO_STRIP "$ENV{XA_NO_STRIP}") +if(XA_NO_STRIP OR DEBUG_BUILD) + set(STRIP_DEBUG_DEFAULT OFF) +endif() + +option(ENABLE_CLANG_ASAN "Enable the clang AddressSanitizer support" OFF) +option(ENABLE_CLANG_UBSAN "Enable the clang UndefinedBehaviorSanitizer support" OFF) + +if(ENABLE_CLANG_ASAN AND ENABLE_CLANG_UBSAN) + message(FATAL_ERROR "Both ASAN and UBSAN builds cannot be enabled at the same time") +endif() + +if(ENABLE_CLANG_ASAN OR ENABLE_CLANG_UBSAN) + if(BUILD_ARCHIVE_DSO_STUB) + message(FATAL_ERROR "ASAN/UBSAN builds aren't supported by the archive DSO target") + endif() + + set(STRIP_DEBUG_DEFAULT OFF) + set(ANALYZERS_ENABLED ON) +else() + if(NOT XA_NO_STRIP) + set(STRIP_DEBUG_DEFAULT ON) + endif() + set(ANALYZERS_ENABLED OFF) +endif() + +option(COMPILER_DIAG_COLOR "Show compiler diagnostics/errors in color" ON) +option(STRIP_DEBUG "Strip debugging information when linking" ${STRIP_DEBUG_DEFAULT}) +option(DISABLE_DEBUG "Disable the built-in debugging code" OFF) +option(USE_CCACHE "Use ccache, if found, to speed up recompilation" ON) +option(DONT_INLINE "Do not inline any functions which are usually inlined, to get better stack traces" ${DONT_INLINE_DEFAULT}) + +if(ENABLE_CLANG_ASAN) + set(STATIC_LIB_NAME_SUFFIX "-clr-asan") +elseif(ENABLE_CLANG_UBSAN) + set(STATIC_LIB_NAME_SUFFIX "-clr-ubsan") +else() + set(STATIC_LIB_NAME_SUFFIX "-clr") +endif() + +if(DEBUG_BUILD) + set(STATIC_LIB_NAME_SUFFIX "${STATIC_LIB_NAME_SUFFIX}-debug") +else() + set(STATIC_LIB_NAME_SUFFIX "${STATIC_LIB_NAME_SUFFIX}-release") +endif() + +if(USE_CCACHE) + if(CMAKE_CXX_COMPILER MATCHES "/ccache/") + message(STATUS "ccache: compiler already uses ccache") + else() + find_program(CCACHE ccache) + if(CCACHE) + set(CMAKE_CXX_COMPILER_LAUNCHER "${CCACHE}") + set(CMAKE_C_COMPILER_LAUNCHER "${CCACHE}") + message(STATUS "ccache: compiler will be lauched with ${CCACHE}") + endif() + endif() +endif() + +# +# Needed modules +# +# include(CheckIncludeFile) +# include(CheckCXXSymbolExists) +include(CheckCXXCompilerFlag) +include(CheckCCompilerFlag) +include(CheckLinkerFlag) + +# +# General config +# +set(XA_BUILD_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../bin/Build${XA_BUILD_CONFIGURATION}") +include("${XA_BUILD_DIR}/xa_build_configuration.cmake") + +# +# Paths +# +if(ANDROID_ABI MATCHES "^arm64-v8a") + set(NET_RUNTIME_DIR "${NETCORE_APP_RUNTIME_DIR_ARM64}") + set(TOOLCHAIN_TRIPLE "${NDK_ABI_arm64-v8a_TRIPLE}") +elseif(ANDROID_ABI MATCHES "^armeabi-v7a") + set(NET_RUNTIME_DIR "${NETCORE_APP_RUNTIME_DIR_ARM}") + set(TOOLCHAIN_TRIPLE "${NDK_ABI_armeabi-v7a_TRIPLE}") +elseif(ANDROID_ABI MATCHES "^x86_64") + set(NET_RUNTIME_DIR "${NETCORE_APP_RUNTIME_DIR_X86_64}") + set(TOOLCHAIN_TRIPLE "${NDK_ABI_x86_64_TRIPLE}") +elseif(ANDROID_ABI MATCHES "^x86") + set(NET_RUNTIME_DIR "${NETCORE_APP_RUNTIME_DIR_X86}") + set(TOOLCHAIN_TRIPLE "${NDK_ABI_x86_TRIPLE}") +else() + message(FATAL "${ANDROID_ABI} is not supported for .NET 6+ builds") +endif() + + +file(REAL_PATH "../../" REPO_ROOT_DIR) +set(EXTERNAL_DIR "${REPO_ROOT_DIR}/external") +set(JAVA_INTEROP_SRC_PATH "${EXTERNAL_DIR}/Java.Interop/src/java-interop") +#set(LIBUNWIND_SOURCE_DIR "${EXTERNAL_DIR}/libunwind") +#set(ROBIN_MAP_DIR "${EXTERNAL_DIR}/robin-map") + +# +# Include directories +# +set(SYSROOT_CXX_INCLUDE_DIR ${CMAKE_SYSROOT}/usr/include/c++/v1) +set(MONO_RUNTIME_INCLUDE_DIR ${NET_RUNTIME_DIR}/native/include/mono-2.0) +set(JAVA_INTEROP_INCLUDE_DIR ${JAVA_INTEROP_SRC_PATH}) +set(XA_RUNTIME_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include) +set(CONSTEXPR_XXH3_DIR ${EXTERNAL_DIR}/constexpr-xxh3) + +macro(xa_add_include_directories TARGET) + target_include_directories( + ${TARGET} + PRIVATE + ${XA_RUNTIME_INCLUDE_DIR} + ${EXTERNAL_DIR} + ${CONSTEXPR_XXH3_DIR} + ) +endmacro() + +# +# Compiler defines +# +macro(xa_add_compile_definitions TARGET) + target_compile_definitions( + ${TARGET} + PRIVATE + XA_VERSION="${XA_VERSION}" + _REENTRANT + PLATFORM_ANDROID + ) + + if(ANDROID_ABI MATCHES "^(arm64-v8a|x86_64)") + target_compile_definitions( + ${TARGET} + PRIVATE + ANDROID64 + ) + endif() +endmacro() + +if(NOT BUILD_ARCHIVE_DSO_STUB) + if(DEBUG_BUILD AND NOT DISABLE_DEBUG) + add_compile_definitions(DEBUG) + endif() + + if(NOT DEBUG_BUILD) + add_compile_definitions(RELEASE NDEBUG) + endif() +endif() + +# +# Compiler argument macros +# +macro(_compiler_has_arg _lang _arg) + string(REGEX REPLACE "-|,|=" "_" _arg_name ${_arg}) + string(TOUPPER "${_lang}" _lang_upper) + + cmake_language(CALL check_${_lang}_compiler_flag "${_arg}" HAS_${_arg_name}_${_lang_upper}) + if(HAS_${_arg_name}_${_lang_upper}) + set(COMPILER_ARG_FOUND True) + else() + set(COMPILER_ARG_FOUND False) + endif() +endmacro() + +macro(cxx_compiler_has_arg _arg) + _compiler_has_arg(cxx ${_arg}) +endmacro() + +macro(c_compiler_has_arg _arg) + _compiler_has_arg(c ${_arg}) +endmacro() + +macro(_linker_has_arg _lang _arg) + string(REGEX REPLACE "-|,|=" "_" _arg_name ${_arg}) + string(TOUPPER "${_lang}" _lang_upper) + + check_linker_flag(${_lang} "${_arg}" HAS_${_arg_name}_LINKER_${_lang_upper}) + if(HAS_${_arg_name}_LINKER_${_lang_upper}) + set(LINKER_ARG_FOUND True) + else() + set(LINKER_ARG_FOUND False) + endif() +endmacro() + +macro(cxx_linker_has_arg _arg) + _linker_has_arg(CXX ${_arg}) +endmacro() + +macro(c_linker_has_arg _arg) + _linker_has_arg(C ${_arg}) +endmacro() + +macro(xa_check_c_args VARNAME _CHECK_ARGS) + set(_CHECKED_ARGS "") + + foreach(arg ${_CHECK_ARGS}) + c_compiler_has_arg(${arg}) + if(COMPILER_ARG_FOUND) + list(APPEND _CHECKED_ARGS "${arg}") + endif() + endforeach() + + set(${VARNAME} "${_CHECKED_ARGS}") +endmacro() + +macro(xa_check_cxx_args VARNAME _CHECK_ARGS) + set(_CHECKED_ARGS "") + + foreach(arg ${_CHECK_ARGS}) + cxx_compiler_has_arg(${arg}) + if(COMPILER_ARG_FOUND) + list(APPEND _CHECKED_ARGS "${arg}") + endif() + endforeach() + + set(${VARNAME} "${_CHECKED_ARGS}") +endmacro() + +macro(xa_check_c_linker_args VARNAME _CHECK_ARGS) + set(_CHECKED_ARGS "") + + foreach(arg ${_CHECK_ARGS}) + c_linker_has_arg(${arg}) + if(LINKER_ARG_FOUND) + list(APPEND _CHECKED_ARGS "${arg}") + endif() + endforeach() + + set(${VARNAME} "${_CHECKED_ARGS}") +endmacro() + +macro(xa_check_cxx_linker_args VARNAME _CHECK_ARGS) + set(_CHECKED_ARGS "") + + foreach(arg ${_CHECK_ARGS}) + cxx_linker_has_arg(${arg}) + if(LINKER_ARG_FOUND) + list(APPEND _CHECKED_ARGS "${arg}") + endif() + endforeach() + + set(${VARNAME} "${_CHECKED_ARGS}") +endmacro() + +set(CLANG_CHECK_SOURCES "") +macro(add_clang_check_sources SOURCES) + foreach(_source ${SOURCES}) + cmake_path(IS_RELATIVE _source _relative_path) + if(${_relative_path}) + list(APPEND _LOCAL_CLANG_CHECK_SOURCES_ ${CMAKE_CURRENT_SOURCE_DIR}/${_source}) + else() + list(APPEND _LOCAL_CLANG_CHECK_SOURCES_ ${_source}) + endif() + endforeach() + set(CLANG_CHECK_SOURCES "${_LOCAL_CLANG_CHECK_SOURCES_};${CLANG_CHECK_SOURCES}" PARENT_SCOPE) +endmacro() + +# +# Compiler args +# +set(CMAKE_CXX_VISIBILITY_PRESET "hidden") +set(CMAKE_C_VISIBILITY_PRESET "hidden") + +# +# Common flags are used when building all external +# and our own code +# +set(POTENTIAL_COMMON_COMPILER_ARGS + -fstack-protector-strong + -fstrict-return + -flto=thin + -fno-strict-aliasing + -fno-function-sections + -fno-data-sections + -funswitch-loops + -Wa,-noexecstack + -fPIC + -O2 +) + +if(NOT BUILD_ARCHIVE_DSO_STUB) + list(APPEND POTENTIAL_COMMON_COMPILER_ARGS + -g + ) +endif() + +set(POTENTIAL_COMMON_LINKER_ARGS + -fstack-protector-strong + -flto=thin + LINKER:-fstrict-return + LINKER:-z,now + LINKER:-z,relro + LINKER:-z,noexecstack + LINKER:--no-undefined + LINKER:--export-dynamic +) + +# Add some options to increase security. They may mildly affect performance but they won't be big, because the features are +# assisted by the hardware. +if((CMAKE_ANDROID_ARCH_ABI STREQUAL "x86") OR (CMAKE_ANDROID_ARCH_ABI STREQUAL "x86_64")) + # -fcf-protection=full: Enable control flow protection to counter Return Oriented Programming (ROP) and Jump Oriented Programming (JOP) attacks on many x86 architectures + list(APPEND POTENTIAL_COMMON_COMPILER_ARGS + -fcf-protection=full + ) +endif() + +if(CMAKE_ANDROID_ARCH_ABI STREQUAL "arm64-v8a") + # -mbranch-protection=standard: Enable branch protection to counter Return Oriented Programming (ROP) and Jump Oriented Programming (JOP) attacks on AArch64 + # In clang -mbranch-protection=standard is equivalent to -mbranch-protection=bti+pac-ret and invokes the AArch64 Branch Target Identification (BTI) and Pointer Authentication using key A (pac-ret) + list(APPEND POTENTIAL_COMMON_COMPILER_ARGS + -mbranch-protection=standard + ) +endif() + +if(COMPILER_DIAG_COLOR) + list(APPEND POTENTIAL_COMMON_COMPILER_ARGS + -fdiagnostics-color=always + -fcolor-diagnostics + ) +endif() + +if(STRIP_DEBUG) + list(APPEND POTENTIAL_COMMON_LINKER_ARGS LINKER:-S) +else() + # When not stripping symbols, we likely want to have precise stack traces, so + # we won't omit frame pointers + list(APPEND POTENTIAL_COMMON_COMPILER_ARGS + -fno-omit-frame-pointer + -fno-limit-debug-info + ) +endif() + +# +# Flags to use only when building our code +# +set(POTENTIAL_XA_COMMON_COMPILER_ARGS + -Wall + -Wconversion + -Wdeprecated + -Wduplicated-branches + -Wduplicated-cond + -Werror=format-security + -Werror=return-type + -Wextra + -Wformat-security + -Wformat=2 + -Wno-format-nonliteral + -Wno-vla-cxx-extension + -Wimplicit-fallthrough + -Wmisleading-indentation + -Wnull-dereference + -Wpointer-arith + -Wshadow + -Wsign-compare + -Wtrampolines + -Wuninitialized + -fstrict-flex-arrays=3 +) + +if (ENABLE_CLANG_ASAN OR ENABLE_CLANG_UBSAN) + list(APPEND POTENTIAL_XA_COMMON_COMPILER_ARGS + -fno-omit-frame-pointer + -fno-optimize-sibling-calls + ) +endif() + +set(POTENTIAL_XA_DSO_LINKER_ARGS + -fpic + -fstack-clash-protection +) + +unset(SANITIZER_FLAGS) +if (ENABLE_CLANG_ASAN) + set(SANITIZER_FLAGS -fsanitize=address) + set(CHECKED_BUILD_INFIX "-checked+asan") +elseif(ENABLE_CLANG_UBSAN) + set(SANITIZER_FLAGS -fsanitize=undefined) + set(CHECKED_BUILD_INFIX "-checked+ubsan") +endif() + +if(SANITIZER_FLAGS) + message(STATUS) + message(STATUS "Got sanitizer: ${SANITIZER_FLAGS}") + message(STATUS) + + list(APPEND POTENTIAL_XA_COMMON_COMPILER_ARGS ${SANITIZER_FLAGS}) + list(APPEND POTENTIAL_XA_COMMON_LINKER_ARGS ${SANITIZER_FLAGS}) + list(APPEND CMAKE_REQUIRED_LINK_OPTIONS ${SANITIZER_FLAGS}) +endif() + +message(STATUS) +message(STATUS "Checking support for common compiler and linker args") +message(STATUS) +xa_check_cxx_args(COMMON_CXX_ARGS "${POTENTIAL_COMMON_COMPILER_ARGS}") +xa_check_c_args(COMMON_C_ARGS "${POTENTIAL_COMMON_COMPILER_ARGS}") +xa_check_cxx_linker_args(COMMON_CXX_LINKER_ARGS "${POTENTIAL_COMMON_LINKER_ARGS}") +xa_check_c_linker_args(COMMON_C_LINKER_ARGS "${POTENTIAL_COMMON_LINKER_ARGS}") + +message(STATUS) +message(STATUS "Checking support for XA common compiler and linker args") +message(STATUS) +xa_check_cxx_args(XA_COMMON_CXX_ARGS "${POTENTIAL_XA_COMMON_COMPILER_ARGS}") +xa_check_c_args(XA_COMMON_C_ARGS "${POTENTIAL_XA_COMMON_COMPILER_ARGS}") +xa_check_cxx_linker_args(XA_COMMON_CXX_LINKER_ARGS "${POTENTIAL_XA_COMMON_LINKER_ARGS}") +xa_check_c_linker_args(XA_COMMON_C_LINKER_ARGS "${POTENTIAL_XA_COMMON_LINKER_ARGS}") +xa_check_c_linker_args(XA_C_DSO_LINKER_ARGS "${POTENTIAL_XA_DSO_LINKER_ARGS}") +xa_check_cxx_linker_args(XA_CXX_DSO_LINKER_ARGS "${POTENTIAL_XA_DSO_LINKER_ARGS}") + +if(NOT BUILD_ARCHIVE_DSO_STUB) + add_compile_options("$<$:${COMMON_CXX_ARGS}>") + add_compile_options("$<$:${COMMON_C_ARGS}>") + + add_link_options("$<$:${COMMON_CXX_LINKER_ARGS}>") + add_link_options("$<$:${COMMON_C_LINKER_ARGS}>") +endif() + +# +# Helper macros +# +macro(set_static_library_suffix TARGET_NAME) + if(STATIC_LIB_NAME_SUFFIX) + set_target_properties( + ${TARGET_NAME} + PROPERTIES + SUFFIX "${STATIC_LIB_NAME_SUFFIX}.a" + ) + endif() +endmacro() + +if(BUILD_ARCHIVE_DSO_STUB) + add_subdirectory(archive-dso-stub) +else() +# add_subdirectory(libunwind) + add_subdirectory(lz4) +# add_subdirectory(libstub) + add_subdirectory(shared) + add_subdirectory(java-interop) + add_subdirectory(xamarin-app-stub) + add_subdirectory(runtime-base) +# add_subdirectory(tracing) +# add_subdirectory(pinvoke-override) + add_subdirectory(startup) + add_subdirectory(host) + +# if(DEBUG_BUILD) +# add_subdirectory(xamarin-debug-app-helper) +# endif() + +# add_subdirectory(monodroid) + + add_custom_target(run_static_analysis + COMMAND ${ANDROID_TOOLCHAIN_ROOT}/bin/clang-check -analyze -p="${CMAKE_CURRENT_BINARY_DIR}" ${CLANG_CHECK_SOURCES} > ${CMAKE_SOURCE_DIR}/static-analysis.${ANDROID_ABI}.${CMAKE_BUILD_TYPE}.txt 2>&1 + COMMAND_EXPAND_LISTS + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" + USES_TERMINAL + ) +endif() diff --git a/src/native-clr/CMakePresets.json.in b/src/native-clr/CMakePresets.json.in new file mode 100644 index 00000000000..33c910f6845 --- /dev/null +++ b/src/native-clr/CMakePresets.json.in @@ -0,0 +1,324 @@ +{ + "version": 3, + "cmakeMinimumRequired": { + "major": 3, + "minor": 21, + "patch": 0 + }, + + "configurePresets": [ + { + "name": "common", + "hidden": true, + "generator": "Ninja", + "debug": { + "output": true + }, + "toolchainFile": "@AndroidNdkDirectory@/build/cmake/android.toolchain.cmake", + "cacheVariables": { + "ANDROID_NDK": "@AndroidNdkDirectory@", + "ANDROID_TOOLCHAIN": "clang", + "ANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES": "ON", + "CMAKE_EXPORT_COMPILE_COMMANDS": "ON", + "CMAKE_MAKE_PROGRAM": "@NinjaPath@", + "OUTPUT_PATH": "@OutputPath@", + "XA_LIB_TOP_DIR": "@MicrosoftAndroidSdkOutDir@", + "XA_BUILD_CONFIGURATION": "@XA_BUILD_CONFIGURATION@" + } + }, + + { + "name": "common-debug", + "hidden": true, + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug" + } + }, + + { + "name": "common-release", + "hidden": true, + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Release" + } + }, + + { + "name": "default-common", + "hidden": true, + "inherits": "common", + "cacheVariables": { + "ANDROID_STL": "c++_static", + "ANDROID_CPP_FEATURES": "no-rtti exceptions" + } + }, + + { + "name": "analyzers-common", + "hidden": true, + "inherits": "common", + "cacheVariables": { + "ANDROID_STL": "c++_static", + "ANDROID_CPP_FEATURES": "rtti exceptions" + } + }, + + { + "name": "default-debug", + "hidden": true, + "inherits": ["default-common", "common-debug"] + }, + + { + "name": "default-release", + "hidden": true, + "inherits": ["default-common", "common-release"] + }, + + { + "name": "analyzers-debug", + "hidden": true, + "inherits": ["analyzers-common", "common-debug"] + }, + + { + "name": "analyzers-release", + "hidden": true, + "inherits": ["analyzers-common", "common-release"] + }, + + { + "name": "common-armeabi-v7a", + "hidden": true, + "cacheVariables": { + "ANDROID_ABI": "armeabi-v7a", + "ANDROID_NATIVE_API_LEVEL": "@NDK_ARMEABI_V7_API_NET@", + "ANDROID_PLATFORM": "android-@NDK_ARMEABI_V7_API_NET@", + "ANDROID_RID": "android-arm" + } + }, + + { + "name": "common-arm64-v8a", + "hidden": true, + "cacheVariables": { + "ANDROID_ABI": "arm64-v8a", + "ANDROID_NATIVE_API_LEVEL": "@NDK_ARM64_V8A_API_NET@", + "ANDROID_PLATFORM": "android-@NDK_ARM64_V8A_API_NET@", + "ANDROID_RID": "android-arm64" + } + }, + + { + "name": "common-x86", + "hidden": true, + "cacheVariables": { + "ANDROID_ABI": "x86", + "ANDROID_NATIVE_API_LEVEL": "@NDK_X86_API_NET@", + "ANDROID_PLATFORM": "android-@NDK_X86_API_NET@", + "ANDROID_RID": "android-x86" + } + }, + + { + "name": "common-x86_64", + "hidden": true, + "cacheVariables": { + "ANDROID_ABI": "x86_64", + "ANDROID_NATIVE_API_LEVEL": "@NDK_X86_64_API_NET@", + "ANDROID_PLATFORM": "android-@NDK_X86_64_API_NET@", + "ANDROID_RID": "android-x64" + } + }, + + { + "name": "asan-common", + "hidden": true, + "cacheVariables": { + "ENABLE_CLANG_ASAN": "ON" + } + }, + + { + "name": "ubsan-common", + "hidden": true, + "cacheVariables": { + "ENABLE_CLANG_UBSAN": "ON" + } + }, + + { + "name": "default-debug-armeabi-v7a", + "inherits": ["default-common", "common-debug", "common-armeabi-v7a"] + }, + + { + "name": "default-release-armeabi-v7a", + "inherits": ["default-common", "common-release", "common-armeabi-v7a"] + }, + + { + "name": "analyzers-debug-armeabi-v7a", + "hidden": true, + "inherits": ["analyzers-common", "common-debug", "common-armeabi-v7a"] + }, + + { + "name": "analyzers-release-armeabi-v7a", + "hidden": true, + "inherits": ["analyzers-common", "common-release", "common-armeabi-v7a"] + }, + + { + "name": "asan-release-armeabi-v7a", + "inherits": ["analyzers-release-armeabi-v7a", "asan-common"] + }, + + { + "name": "asan-debug-armeabi-v7a", + "inherits": ["analyzers-debug-armeabi-v7a", "asan-common"] + }, + + { + "name": "ubsan-release-armeabi-v7a", + "inherits": ["analyzers-release-armeabi-v7a", "ubsan-common"] + }, + + { + "name": "ubsan-debug-armeabi-v7a", + "inherits": ["analyzers-debug-armeabi-v7a", "ubsan-common"] + }, + + + + { + "name": "default-debug-arm64-v8a", + "inherits": ["default-common", "common-debug", "common-arm64-v8a"] + }, + + { + "name": "default-release-arm64-v8a", + "inherits": ["default-common", "common-release", "common-arm64-v8a"] + }, + + { + "name": "analyzers-debug-arm64-v8a", + "hidden": true, + "inherits": ["analyzers-common", "common-debug", "common-arm64-v8a"] + }, + + { + "name": "analyzers-release-arm64-v8a", + "hidden": true, + "inherits": ["analyzers-common", "common-release", "common-arm64-v8a"] + }, + + { + "name": "asan-release-arm64-v8a", + "inherits": ["analyzers-release-arm64-v8a", "asan-common"] + }, + + { + "name": "asan-debug-arm64-v8a", + "inherits": ["analyzers-debug-arm64-v8a", "asan-common"] + }, + + { + "name": "ubsan-release-arm64-v8a", + "inherits": ["analyzers-release-arm64-v8a", "ubsan-common"] + }, + + { + "name": "ubsan-debug-arm64-v8a", + "inherits": ["analyzers-debug-arm64-v8a", "ubsan-common"] + }, + + + + { + "name": "default-debug-x86", + "inherits": ["default-common", "common-debug", "common-x86"] + }, + + { + "name": "default-release-x86", + "inherits": ["default-common", "common-release", "common-x86"] + }, + + { + "name": "analyzers-debug-x86", + "hidden": true, + "inherits": ["analyzers-common", "common-debug", "common-x86"] + }, + + { + "name": "analyzers-release-x86", + "hidden": true, + "inherits": ["analyzers-common", "common-release", "common-x86"] + }, + + { + "name": "asan-release-x86", + "inherits": ["analyzers-release-x86", "asan-common"] + }, + + { + "name": "asan-debug-x86", + "inherits": ["analyzers-debug-x86", "asan-common"] + }, + + { + "name": "ubsan-release-x86", + "inherits": ["analyzers-release-x86", "ubsan-common"] + }, + + { + "name": "ubsan-debug-x86", + "inherits": ["analyzers-debug-x86", "ubsan-common"] + }, + + + + { + "name": "default-debug-x86_64", + "inherits": ["default-common", "common-debug", "common-x86_64"] + }, + + { + "name": "default-release-x86_64", + "inherits": ["default-common", "common-release", "common-x86_64"] + }, + + { + "name": "analyzers-debug-x86_64", + "hidden": true, + "inherits": ["analyzers-common", "common-debug", "common-x86_64"] + }, + + { + "name": "analyzers-release-x86_64", + "hidden": true, + "inherits": ["analyzers-common", "common-release", "common-x86_64"] + }, + + { + "name": "asan-release-x86_64", + "inherits": ["analyzers-release-x86_64", "asan-common"] + }, + + { + "name": "asan-debug-x86_64", + "inherits": ["analyzers-debug-x86_64", "asan-common"] + }, + + { + "name": "ubsan-release-x86_64", + "inherits": ["analyzers-release-x86_64", "ubsan-common"] + }, + + { + "name": "ubsan-debug-x86_64", + "inherits": ["analyzers-debug-x86_64", "ubsan-common"] + } + ] +} diff --git a/src/native-clr/host/CMakeLists.txt b/src/native-clr/host/CMakeLists.txt new file mode 100644 index 00000000000..b60cbc3b3ec --- /dev/null +++ b/src/native-clr/host/CMakeLists.txt @@ -0,0 +1,155 @@ +# Needed modules + +include(CheckIncludeFile) +include(CheckCXXSymbolExists) + +set(BUILD_STATIC_LIBRARY OFF) + +if(DEBUG_BUILD) + # Convince NDK to really optimize our Debug builds. Without this, NDK's cmake toolchain definition + # will force a -O0 on us and our "debug" build is not really for debugging of our native code but + # rather for "debug" builds of user apps - it has extra code but it has to be as fast as possible. + set(XA_COMPILER_FLAGS_DEBUG "-fno-limit-debug-info -O2") + set(CMAKE_C_FLAGS_DEBUG ${XA_COMPILER_FLAGS_DEBUG}) + set(CMAKE_CXX_FLAGS_DEBUG ${XA_COMPILER_FLAGS_DEBUG}) +elseif(NOT ANALYZERS_ENABLED) + set(BUILD_STATIC_LIBRARY OFF) # Turn off for now, until we implement dynamic runtime linking at app build time +endif() + +# Library directories +set(XA_LIBRARY_OUTPUT_DIRECTORY "${XA_LIB_TOP_DIR}/lib/${ANDROID_RID}") +set(XA_LIBRARY_STUBS_OUTPUT_DIRECTORY "${XA_LIB_TOP_DIR}/libstubs/${ANDROID_RID}") + +# Header checks + +# Sources +string(TOLOWER ${CMAKE_BUILD_TYPE} XAMARIN_NET_ANDROID_SUFFIX) +set(XAMARIN_NET_ANDROID_LIB "net-android${CHECKED_BUILD_INFIX}.${XAMARIN_NET_ANDROID_SUFFIX}") +set(XAMARIN_NET_ANDROID_STATIC_LIB "${XAMARIN_NET_ANDROID_LIB}-static") + +set(XAMARIN_MONODROID_SOURCES + host.cc + host-jni.cc +) + +list(APPEND LOCAL_CLANG_CHECK_SOURCES + ${XAMARIN_MONODROID_SOURCES} +) + +add_clang_check_sources("${LOCAL_CLANG_CHECK_SOURCES}") + +# Build +add_library( + ${XAMARIN_NET_ANDROID_LIB} + SHARED ${XAMARIN_MONODROID_SOURCES} +) + +if(BUILD_STATIC_LIBRARY) + add_library( + ${XAMARIN_NET_ANDROID_STATIC_LIB} + STATIC + ${XAMARIN_MONODROID_SOURCES} + ) + set_static_library_suffix(${XAMARIN_NET_ANDROID_STATIC_LIB}) +endif() + +macro(lib_target_options TARGET_NAME) + target_compile_definitions( + ${TARGET_NAME} + PRIVATE + HAVE_CONFIG_H + HAVE_LZ4 + JI_DLL_EXPORT + JI_NO_VISIBILITY + ) + + if(DONT_INLINE) + target_compile_definitions( + ${TARGET_NAME} + PRIVATE + NO_INLINE + ) + endif() + + if(DEBUG_BUILD AND NOT DISABLE_DEBUG) + target_compile_definitions( + ${TARGET_NAME} + PRIVATE + DEBUG + ) + endif() + + if (ENABLE_TIMING) + target_compile_definitions( + ${TARGET_NAME} + PRIVATE + MONODROID_TIMING + ) + endif() + + target_compile_options( + ${TARGET_NAME} + PRIVATE + ${XA_DEFAULT_SYMBOL_VISIBILITY} + ${XA_COMMON_CXX_ARGS} + ) + + target_include_directories( + ${TARGET_NAME} BEFORE + PRIVATE + ${CMAKE_CURRENT_BINARY_DIR}/include + ${EXTERNAL_DIR} + ${ROBIN_MAP_DIR}/include + ) + + target_include_directories( + ${TARGET_NAME} + SYSTEM PRIVATE + ${SYSROOT_CXX_INCLUDE_DIR} + ${MONO_RUNTIME_INCLUDE_DIR} + ${NATIVE_TRACING_INCLUDE_DIRS} + ${LIBUNWIND_INCLUDE_DIRS} + ) + + target_link_directories( + ${TARGET_NAME} + PRIVATE + ${NET_RUNTIME_DIR}/native + ) + + target_link_options( + ${TARGET_NAME} + PRIVATE + ${XA_DEFAULT_SYMBOL_VISIBILITY} + ${XA_COMMON_CXX_LINKER_ARGS} + ${XA_CXX_DSO_LINKER_ARGS} + ) + + target_link_libraries( + ${TARGET_NAME} + ${LINK_LIBS} + xa::xamarin-app-clr + ${SHARED_LIB_NAME} + xa::runtime-base-clr + xa::java-interop-clr +# xa::pinvoke-override-precompiled + xa::lz4-clr + -llog + ) +endmacro () + +lib_target_options(${XAMARIN_NET_ANDROID_LIB}) +xa_add_compile_definitions(${XAMARIN_NET_ANDROID_LIB}) +xa_add_include_directories(${XAMARIN_NET_ANDROID_LIB}) + +target_link_options(${XAMARIN_NET_ANDROID_LIB} + PRIVATE + -Wl,--version-script,${CMAKE_SOURCE_DIR}/libnet-android.map.txt + -Wl,--no-undefined-version +) + +if(BUILD_STATIC_LIBRARY) + lib_target_options(${XAMARIN_NET_ANDROID_STATIC_LIB}) + xa_add_compile_definitions(${XAMARIN_NET_ANDROID_STATIC_LIB}) + xa_add_include_directories(${XAMARIN_NET_ANDROID_STATIC_LIB}) +endif() diff --git a/src/native-clr/host/host-jni.cc b/src/native-clr/host/host-jni.cc new file mode 100644 index 00000000000..3e9af6e868a --- /dev/null +++ b/src/native-clr/host/host-jni.cc @@ -0,0 +1,43 @@ +#include +#include + +using namespace xamarin::android; + +JNIEXPORT jint JNICALL +JNI_OnLoad (JavaVM *vm, void *reserved) +{ + return Host::Java_JNI_OnLoad (vm, reserved); +} + +JNIEXPORT void +JNICALL Java_mono_android_Runtime_dumpTimingData ([[maybe_unused]] JNIEnv *env, [[maybe_unused]] jclass klass) +{ + // if (internal_timing == nullptr) { + // return; + // } + + // internal_timing->dump (); +} + +JNIEXPORT void +JNICALL Java_mono_android_Runtime_register (JNIEnv *env, [[maybe_unused]] jclass klass, jstring managedType, jclass nativeClass, jstring methods) +{ +} + +JNIEXPORT void JNICALL +Java_mono_android_Runtime_init (JNIEnv *env, jclass klass, jstring lang, jobjectArray runtimeApksJava, + jstring runtimeNativeLibDir, jobjectArray appDirs, jint localDateTimeOffset, jobject loader, + jobjectArray assembliesJava, jboolean isEmulator, + jboolean haveSplitApks) +{ +} + +JNIEXPORT void +JNICALL Java_mono_android_Runtime_propagateUncaughtException (JNIEnv *env, [[maybe_unused]] jclass klass, jobject javaThread, jthrowable javaException) +{ +} + +JNIEXPORT void +JNICALL Java_mono_android_Runtime_notifyTimeZoneChanged ([[maybe_unused]] JNIEnv *env, [[maybe_unused]] jclass klass) +{ +} diff --git a/src/native-clr/host/host.cc b/src/native-clr/host/host.cc new file mode 100644 index 00000000000..735ae4dfa60 --- /dev/null +++ b/src/native-clr/host/host.cc @@ -0,0 +1,11 @@ +#include +#include +#include + +using namespace xamarin::android; + +auto Host::Java_JNI_OnLoad (JavaVM *vm, [[maybe_unused]] void *reserved) noexcept -> jint +{ + AndroidSystem::init_max_gref_count (); + return JNI_VERSION_1_6; +} diff --git a/src/native-clr/include/constants.hh b/src/native-clr/include/constants.hh new file mode 100644 index 00000000000..e850723ec00 --- /dev/null +++ b/src/native-clr/include/constants.hh @@ -0,0 +1,96 @@ +#pragma once + +#include + +#include + +#include "shared/cpp-util.hh" + +namespace xamarin::android { + class Constants + { +#if INTPTR_MAX == INT64_MAX + static inline constexpr std::string_view BITNESS { "64bit" }; +#else + static inline constexpr std::string_view BITNESS { "32bit" }; +#endif + + public: + static constexpr std::string_view MANGLED_ASSEMBLY_NAME_EXT { ".so" }; + + private: + static constexpr std::string_view RUNTIME_CONFIG_BLOB_BASE_NAME { "libarc.bin" }; + static constexpr size_t runtime_config_blob_name_size = calc_size (RUNTIME_CONFIG_BLOB_BASE_NAME, MANGLED_ASSEMBLY_NAME_EXT); + static constexpr auto RUNTIME_CONFIG_BLOB_NAME_ARRAY = concat_string_views (RUNTIME_CONFIG_BLOB_BASE_NAME, MANGLED_ASSEMBLY_NAME_EXT); + + public: + // .data() must be used otherwise string_view length will include the trailing \0 in the array + static constexpr std::string_view RUNTIME_CONFIG_BLOB_NAME { RUNTIME_CONFIG_BLOB_NAME_ARRAY.data () }; + static constexpr std::string_view OVERRIDE_DIRECTORY_NAME { ".__override__" }; + + /* Android property containing connection information, set by XS */ + static inline constexpr std::string_view DEBUG_MONO_CONNECT_PROPERTY { "debug.mono.connect" }; + static inline constexpr std::string_view DEBUG_MONO_DEBUG_PROPERTY { "debug.mono.debug" }; + static inline constexpr std::string_view DEBUG_MONO_ENV_PROPERTY { "debug.mono.env" }; + static inline constexpr std::string_view DEBUG_MONO_EXTRA_PROPERTY { "debug.mono.extra" }; + static inline constexpr std::string_view DEBUG_MONO_GC_PROPERTY { "debug.mono.gc" }; + static inline constexpr std::string_view DEBUG_MONO_GDB_PROPERTY { "debug.mono.gdb" }; + static inline constexpr std::string_view DEBUG_MONO_LOG_PROPERTY { "debug.mono.log" }; + static inline constexpr std::string_view DEBUG_MONO_MAX_GREFC { "debug.mono.max_grefc" }; + static inline constexpr std::string_view DEBUG_MONO_PROFILE_PROPERTY { "debug.mono.profile" }; + static inline constexpr std::string_view DEBUG_MONO_RUNTIME_ARGS_PROPERTY { "debug.mono.runtime_args" }; + static inline constexpr std::string_view DEBUG_MONO_SOFT_BREAKPOINTS { "debug.mono.soft_breakpoints" }; + static inline constexpr std::string_view DEBUG_MONO_TRACE_PROPERTY { "debug.mono.trace" }; + static inline constexpr std::string_view DEBUG_MONO_WREF_PROPERTY { "debug.mono.wref" }; + + static constexpr std::string_view LOG_CATEGORY_NAME_NONE { "*none*" }; + static constexpr std::string_view LOG_CATEGORY_NAME_MONODROID { "monodroid" }; + static constexpr std::string_view LOG_CATEGORY_NAME_MONODROID_ASSEMBLY { "monodroid-assembly" }; + static constexpr std::string_view LOG_CATEGORY_NAME_MONODROID_DEBUG { "monodroid-debug" }; + static constexpr std::string_view LOG_CATEGORY_NAME_MONODROID_GC { "monodroid-gc" }; + static constexpr std::string_view LOG_CATEGORY_NAME_MONODROID_GREF { "monodroid-gref" }; + static constexpr std::string_view LOG_CATEGORY_NAME_MONODROID_LREF { "monodroid-lref" }; + static constexpr std::string_view LOG_CATEGORY_NAME_MONODROID_TIMING { "monodroid-timing" }; + static constexpr std::string_view LOG_CATEGORY_NAME_MONODROID_BUNDLE { "monodroid-bundle" }; + static constexpr std::string_view LOG_CATEGORY_NAME_MONODROID_NETWORK { "monodroid-network" }; + static constexpr std::string_view LOG_CATEGORY_NAME_MONODROID_NETLINK { "monodroid-netlink" }; + static constexpr std::string_view LOG_CATEGORY_NAME_ERROR { "*error*" }; + +#if defined(__arm__) + static constexpr std::string_view android_abi { "armeabi_v7a" }; + static constexpr std::string_view android_lib_abi { "armeabi-v7a" }; + static constexpr std::string_view runtime_identifier { "android-arm" }; +#elif defined(__aarch64__) + static constexpr std::string_view android_abi { "arm64_v8a" }; + static constexpr std::string_view android_lib_abi { "arm64-v8a" }; + static constexpr std::string_view runtime_identifier { "android-arm64" }; +#elif defined(__x86_64__) + static constexpr std::string_view android_abi { "x86_64" }; + static constexpr std::string_view android_lib_abi { "x86_64" }; + static constexpr std::string_view runtime_identifier { "android-x64" }; +#elif defined(__i386__) + static constexpr std::string_view android_abi { "x86" }; + static constexpr std::string_view android_lib_abi { "x86" }; + static constexpr std::string_view runtime_identifier { "android-x86" }; +#endif + + static constexpr std::string_view split_config_prefix { "/split_config." }; + static constexpr std::string_view split_config_extension { ".apk" }; + + static constexpr size_t split_config_abi_apk_name_size = calc_size (split_config_prefix, android_abi, split_config_extension); + static constexpr auto split_config_abi_apk_name = concat_string_views (split_config_prefix, android_abi, split_config_extension); + + // + // Indexes must match these of trhe `appDirs` array in src/java-runtime/mono/android/MonoPackageManager.java + // + static constexpr size_t APP_DIRS_FILES_DIR_INDEX = 0uz; + static constexpr size_t APP_DIRS_CACHE_DIR_INDEX = 1uz; + static constexpr size_t APP_DIRS_DATA_DIR_INDEX = 2uz; + + static inline constexpr size_t PROPERTY_VALUE_BUFFER_LEN = PROP_VALUE_MAX + 1uz; + + // 64-bit unsigned or 64-bit signed with sign + static constexpr size_t MAX_INTEGER_DIGIT_COUNT_BASE10 = 21uz; + static constexpr size_t INTEGER_BASE10_BUFFER_SIZE = MAX_INTEGER_DIGIT_COUNT_BASE10 + 1uz; + }; +} diff --git a/src/native-clr/include/host/host-jni.hh b/src/native-clr/include/host/host-jni.hh new file mode 100644 index 00000000000..2104c2b1846 --- /dev/null +++ b/src/native-clr/include/host/host-jni.hh @@ -0,0 +1,48 @@ +#pragma once + +#include + +extern "C" { + /* + * Class: mono_android_Runtime + * Method: initInternal + * Signature: (Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;ILjava/lang/ClassLoader;[Ljava/lang/String;IZZ)V + */ + JNIEXPORT void JNICALL Java_mono_android_Runtime_initInternal(JNIEnv *, jclass, jstring, jobjectArray, jstring, jobjectArray, jint, jobject, jobjectArray, jboolean, jboolean); + + /* + * Class: mono_android_Runtime + * Method: dumpTimingData + * Signature: ()V + */ + JNIEXPORT void JNICALL Java_mono_android_Runtime_dumpTimingData (JNIEnv *, jclass); + + /* + * Class: mono_android_Runtime + * Method: init + * Signature: (Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;ILjava/lang/ClassLoader;[Ljava/lang/String;IZZ)V + */ + JNIEXPORT void JNICALL Java_mono_android_Runtime_init (JNIEnv *, jclass, jstring, jobjectArray, jstring, jobjectArray, jint, jobject, jobjectArray, jboolean, jboolean); + + /* + * Class: mono_android_Runtime + * Method: notifyTimeZoneChanged + * Signature: ()V + */ + JNIEXPORT void JNICALL Java_mono_android_Runtime_notifyTimeZoneChanged (JNIEnv *, jclass); + + /* + * Class: mono_android_Runtime + * Method: propagateUncaughtException + * Signature: (Ljava/lang/Thread;Ljava/lang/Throwable;)V + */ + JNIEXPORT void JNICALL Java_mono_android_Runtime_propagateUncaughtException (JNIEnv *, jclass, jobject, jthrowable); + + /* + * Class: mono_android_Runtime + * Method: register + * Signature: (Ljava/lang/String;Ljava/lang/Class;Ljava/lang/String;)V + */ + JNIEXPORT void JNICALL Java_mono_android_Runtime_register (JNIEnv *, jclass, jstring, jclass, jstring); + +} diff --git a/src/native-clr/include/host/host.hh b/src/native-clr/include/host/host.hh new file mode 100644 index 00000000000..03e4186ebae --- /dev/null +++ b/src/native-clr/include/host/host.hh @@ -0,0 +1,13 @@ +#pragma once + +#include + +#include "../shared/log_types.hh" + +namespace xamarin::android { + class Host + { + public: + static auto Java_JNI_OnLoad (JavaVM *vm, void *reserved) noexcept -> jint; + }; +} diff --git a/src/native-clr/include/runtime-base/android-system.hh b/src/native-clr/include/runtime-base/android-system.hh new file mode 100644 index 00000000000..ad9975f9fc6 --- /dev/null +++ b/src/native-clr/include/runtime-base/android-system.hh @@ -0,0 +1,39 @@ +#pragma once + +#include + +#include "../constants.hh" +#include "../shared/log_types.hh" +#include "strings.hh" + +namespace xamarin::android { + class AndroidSystem + { + public: + static auto get_max_gref_count () noexcept -> long + { + return max_gref_count; + } + + static void init_max_gref_count () noexcept + { + max_gref_count = get_max_gref_count_from_system (); + } + + static void set_running_in_emulator (bool yesno) noexcept + { + running_in_emulator = yesno; + } + + static auto monodroid_get_system_property (std::string_view const& name, dynamic_local_string &value) noexcept -> int; + + private: + static auto lookup_system_property (std::string_view const &name, size_t &value_len) noexcept -> const char*; + static auto monodroid__system_property_get (std::string_view const&, char *sp_value, size_t sp_value_len) noexcept -> int; + static auto get_max_gref_count_from_system () noexcept -> long; + + private: + static inline long max_gref_count = 0; + static inline bool running_in_emulator = false; + }; +} diff --git a/src/native-clr/include/runtime-base/strings.hh b/src/native-clr/include/runtime-base/strings.hh new file mode 100644 index 00000000000..c3326e91cc1 --- /dev/null +++ b/src/native-clr/include/runtime-base/strings.hh @@ -0,0 +1,920 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#include "../shared/helpers.hh" +#include "../constants.hh" + +namespace xamarin::android { + static constexpr size_t SENSIBLE_TYPE_NAME_LENGTH = 128uz; + static constexpr size_t SENSIBLE_PATH_MAX = 256uz; + +#if DEBUG + static constexpr bool BoundsCheck = true; +#else + static constexpr bool BoundsCheck = false; +#endif + + class string_segment + { + public: + [[gnu::always_inline]] + auto initialized () const noexcept -> bool + { + return !_fresh; + } + + [[gnu::always_inline]] + auto start () const noexcept -> const char* + { + return _start; + } + + [[gnu::always_inline]] + auto length () const noexcept -> size_t + { + return _length; + } + + [[gnu::always_inline]] + auto empty () const noexcept -> bool + { + return length () == 0; + } + + [[gnu::always_inline]] + auto equal (const char *s) const noexcept -> bool + { + if (s == nullptr) { + return false; + } + + return equal (s, strlen (s)); + } + + [[gnu::always_inline]] + auto equal (const char *s, size_t s_length) const noexcept -> bool + { + if (s == nullptr) { + return false; + } + + if (length () != s_length) { + return false; + } + + if (!can_access (s_length)) [[unlikely]] { + return false; + } + + if (length () == 0) { + return true; + } + + return memcmp (_start, s, length ()) == 0; + } + + template [[gnu::always_inline]] + auto equal (const char (&s)[Size]) noexcept -> bool + { + return equal (s, Size - 1); + } + + [[gnu::always_inline]] + auto equal (std::string_view const& s) noexcept -> bool + { + return equal (s.data (), s.length ()); + } + + [[gnu::always_inline]] + auto starts_with_c (const char *s) const noexcept -> bool + { + if (s == nullptr) { + return false; + } + + return starts_with (s, strlen (s)); + } + + [[gnu::always_inline]] + auto starts_with (const char *s, size_t s_length) const noexcept -> bool + { + if (s == nullptr || !can_access (s_length)) { + return false; + } + + if (length () < s_length) { + return false; + } + + return memcmp (start (), s, s_length) == 0; + } + + template [[gnu::always_inline]] + auto starts_with (const char (&s)[Size]) const noexcept -> bool + { + return starts_with (s, Size - 1); + } + + [[gnu::always_inline]] + auto starts_with (std::string_view const& s) const noexcept -> bool + { + return starts_with (s.data (), s.length ()); + } + + [[gnu::always_inline]] + auto has_at (const char ch, size_t index) const noexcept -> bool + { + if (!can_access (index)) { + return false; + } + + return start ()[index] == ch; + } + + [[gnu::always_inline]] + auto find (const char ch, size_t start_index) const noexcept -> ssize_t + { + if (!can_access (start_index)) { + return -1; + } + + while (start_index <= length ()) { + if (start ()[start_index] == ch) { + return static_cast(start_index); + } + start_index++; + } + + return -1; + } + + template [[gnu::always_inline]] + auto to_integer (T &val, size_t start_index = 0uz, int base = 10) const noexcept -> bool + { + static_assert (std::is_integral_v); + constexpr T min = std::numeric_limits::min (); + constexpr T max = std::numeric_limits::max (); + using integer = typename std::conditional, int64_t, uint64_t>::type; + + if (length () == 0uz) { + return false; + } + + if (!can_access (start_index)) { + log_error (LOG_DEFAULT, "Cannot convert string to integer, index {} is out of range", start_index); + return false; + } + + // FIXME: this is less than ideal... we shouldn't need another buffer here + size_t slen = length () - start_index; + char s[slen + 1]; + + memcpy (s, start () + start_index, slen); + s[slen] = '\0'; + + integer ret; + char *endp; + bool out_of_range; + errno = 0; + if constexpr (std::is_signed_v) { + ret = strtoll (s, &endp, base); + out_of_range = ret < min || ret > max; + } else { + ret = strtoull (s, &endp, base); + out_of_range = ret > max; + } + + if (out_of_range || errno == ERANGE) { + log_error (LOG_DEFAULT, "Value {} is out of range of this type ({}..{})", reinterpret_cast(s), static_cast(min), static_cast(max)); + return false; + } + + if (endp == s) { + log_error (LOG_DEFAULT, "Value {} does not represent a base {} integer", reinterpret_cast(s), base); + return false; + } + + if (*endp != '\0') { + log_error (LOG_DEFAULT, "Value {} has non-numeric characters at the end", reinterpret_cast(s)); + return false; + } + + val = static_cast(ret); + return true; + } + + private: + [[gnu::always_inline]] + auto can_access (size_t index) const noexcept -> bool + { + if (!initialized () || start () == nullptr) [[unlikely]] { + return false; + } + + if (index > length ()) { + return false; + } + + return true; + } + + protected: + size_t _last_index = 0uz; + bool _fresh = true; + const char *_start = nullptr; + size_t _length = 0uz; + + template friend class string_base; + }; + + template + class local_storage + { + protected: + using LocalStoreArray = std::array; + + public: + static constexpr bool has_resize = HasResize; + + public: + explicit local_storage (size_t size) noexcept + { + static_assert (MaxStackSize > 0, "MaxStackSize must be more than 0"); + init_store (size < MaxStackSize ? MaxStackSize : size); + } + + virtual ~local_storage () + { + free_store (); + } + + auto get () noexcept -> T* + { + return allocated_store == nullptr ? local_store.data () : allocated_store; + } + + auto get () const noexcept -> const T* + { + return allocated_store == nullptr ? local_store.data () : allocated_store; + } + + auto size () const noexcept -> size_t + { + return store_size; + } + + protected: + [[gnu::always_inline]] + void init_store (size_t new_size) noexcept + { + if (new_size > MaxStackSize) { + allocated_store = new T[new_size]; + } else { + allocated_store = nullptr; + } + store_size = new_size; + } + + [[gnu::always_inline]] + void free_store () noexcept + { + if (allocated_store == nullptr) { + return; + } + + delete[] allocated_store; + } + + [[gnu::always_inline]] + auto get_local_store () noexcept -> LocalStoreArray& + { + return local_store; + } + + [[gnu::always_inline]] + auto get_allocated_store () noexcept -> T* + { + return allocated_store; + } + + private: + size_t store_size; + LocalStoreArray local_store; + T* allocated_store; + }; + + // This class is meant to provide a *very* thin veneer (by design) over space allocated for *local* buffers - that + // is one which are not meant to survive the exit of the function they are created in. The idea is that the caller + // knows the size of the buffer they need and they want to put the buffer on stack, if it doesn't exceed a certain + // value, or dynamically allocate memory if more is needed. Even though the class could be used on its own, it's + // really meant to be a base for more specialized buffers. There are not many safeguards, by design - the code is + // meant to be performant. This is the reason why the size is static throughout the life of the object, so that we + // can perform as few checks as possible. + + template using static_local_storage_base = local_storage; + + template + class static_local_storage final : public static_local_storage_base + { + using base = static_local_storage_base; + + public: + explicit static_local_storage (size_t initial_size) noexcept + : base (initial_size) + {} + }; + + template using dynamic_local_storage_base = local_storage; + + template + class dynamic_local_storage final : public dynamic_local_storage_base + { + using base = dynamic_local_storage_base; + + public: + explicit dynamic_local_storage (size_t initial_size = 0uz) noexcept + : base (initial_size) + {} + + // + // If `new_size` is smaller than the current size and the dynamic store is allocated, data WILL NOT be + // preserved. + // + // If `new_size` is bigger than the current size bigger than MaxStackSize, data will be copied to the new + // dynamically allocated store + // + // If `new_size` is smaller or equal to `MaxStackSize`, no changes are made unless dynamic store was allocated, + // in which case it will be freed + // + void resize (size_t new_size) noexcept + { + size_t old_size = base::size (); + + if (new_size == old_size) { + return; + } + + if (new_size <= MaxStackSize) { + new_size = MaxStackSize; + base::free_store (); + return; + } + + if (new_size < old_size) { + base::free_store (); + base::init_store (new_size); + return; + } + + T* old_allocated_store = base::get_allocated_store (); + base::init_store (new_size); + + T* new_allocated_store = base::get_allocated_store (); + if (old_allocated_store != nullptr) { + std::memcpy (new_allocated_store, old_allocated_store, old_size); + delete[] old_allocated_store; + return; + } + + std::memcpy (new_allocated_store, base::get_local_store ().data (), MaxStackSize); + } + }; + + template + class string_base + { + protected: + static constexpr TChar NUL = '\0'; + static constexpr TChar ZERO = '0'; + + public: + explicit string_base (size_t initial_size = 0uz) + : buffer (initial_size) + { + // Currently we care only about `char`, maybe in the future we'll add support for `wchar` (if needed) + static_assert (std::is_same_v, "TChar must be an 8-bit character type"); + + clear (); + } + + explicit string_base (const string_segment &token) + : string_base (token.initialized () ? token.length () : 0) + { + if (token.initialized ()) { + assign (token.start (), token.length ()); + } + } + + [[gnu::always_inline]] + auto length () const noexcept -> size_t + { + return idx; + } + + [[gnu::always_inline]] + auto empty () const noexcept -> bool + { + return length () == 0; + } + + [[gnu::always_inline]] + void set_length (size_t new_length) noexcept + { + if (new_length >= buffer.size ()) { + return; + } + + idx = new_length; + terminate (); + } + + [[gnu::always_inline]] + void clear () noexcept + { + set_length (0); + buffer.get ()[0] = NUL; + } + + [[gnu::always_inline]] + void terminate () noexcept + { + buffer.get ()[idx] = NUL; + } + + [[gnu::always_inline]] + auto replace (const TChar c1, const TChar c2) noexcept -> string_base& + { + if (empty ()) { + return *this; + } + + for (size_t i = 0uz; i < length (); i++) { + if (buffer.get ()[i] == c1) { + buffer.get ()[i] = c2; + } + } + + return *this; + } + + [[gnu::always_inline]] + auto append (const TChar* s, size_t length) noexcept -> string_base& + { + if (s == nullptr || length == 0uz) { + return *this; + } + + resize_for_extra (length); + if constexpr (BoundsCheck) { + ensure_have_extra (length); + } + + std::memcpy (buffer.get () + idx, s, length); + idx += length; + buffer.get ()[idx] = NUL; + + return *this; + } + + template + [[gnu::always_inline]] + auto append (string_base const& str) noexcept -> string_base& + { + return append (str.get (), str.length ()); + } + + [[gnu::always_inline]] + auto append (std::string_view const& sv) noexcept -> string_base& + { + return append (sv.data (), sv.length ()); + } + + template [[gnu::always_inline]] + auto append (const char (&s)[Size]) noexcept -> string_base& + { + return append (s, Size - 1); + } + + [[gnu::always_inline]] + auto append_c (const char *s) noexcept -> string_base& + { + if (s == nullptr) + return *this; + + return append (s, strlen (s)); + } + + [[gnu::always_inline]] + auto append (int16_t i) noexcept -> string_base& + { + resize_for_extra (Constants::MAX_INTEGER_DIGIT_COUNT_BASE10); + append_integer (buffer.get (), i); + return *this; + } + + [[gnu::always_inline]] + auto append (uint16_t i) noexcept -> string_base& + { + resize_for_extra (Constants::MAX_INTEGER_DIGIT_COUNT_BASE10); + append_integer (i); + return *this; + } + + [[gnu::always_inline]] + auto append (int32_t i) noexcept -> string_base& + { + resize_for_extra (Constants::MAX_INTEGER_DIGIT_COUNT_BASE10); + append_integer (i); + return *this; + } + + [[gnu::always_inline]] + auto append (uint32_t i) noexcept -> string_base& + { + resize_for_extra (Constants::MAX_INTEGER_DIGIT_COUNT_BASE10); + append_integer (i); + return *this; + } + + [[gnu::always_inline]] + auto append (int64_t i) noexcept -> string_base& + { + resize_for_extra (Constants::MAX_INTEGER_DIGIT_COUNT_BASE10); + append_integer (i); + return *this; + } + + [[gnu::always_inline]] + auto append (uint64_t i) noexcept -> string_base& + { + resize_for_extra (Constants::MAX_INTEGER_DIGIT_COUNT_BASE10); + append_integer (i); + return *this; + } + + [[gnu::always_inline]] + auto assign (const TChar* s, size_t length) noexcept -> string_base& + { + idx = 0; + return append (s, length); + } + + [[gnu::always_inline]] + auto assign_c (const TChar* s) noexcept -> string_base& + { + if (s == nullptr) { + return *this; + } + + return assign (s, strlen (s)); + } + + [[gnu::always_inline]] + auto assign (std::string_view const& sv) noexcept -> string_base& + { + return assign (sv.data (), sv.size ()); + } + + template [[gnu::always_inline]] + auto assign (const char (&s)[Size]) noexcept -> string_base& + { + return assign (s, Size - 1); + } + + template + [[gnu::always_inline]] + auto assign (string_base const& str) noexcept -> string_base& + { + return assign (str.get (), str.length ()); + } + + [[gnu::always_inline]] + auto assign (const TChar* s, size_t offset, size_t count) noexcept -> string_base& + { + if (s == nullptr) { + return *this; + } + + if constexpr (BoundsCheck) { + size_t slen = strlen (s); + if (offset + count > slen) { + Helpers::abort_application ("Attempt to assign data from a string exceeds the source string length"); + } + } + + return assign (s + offset, count); + } + + [[gnu::always_inline]] + auto next_token (size_t start_index, const TChar separator, string_segment& token) const noexcept -> bool + { + size_t index; + if (token._fresh) { + token._fresh = false; + token._last_index = start_index; + index = start_index; + } else { + index = token._last_index + 1; + } + + token._start = nullptr; + token._length = 0; + if (token._last_index + 1 >= buffer.size ()) { + return false; + } + + const TChar *start = buffer.get () + index; + const TChar *p = start; + while (*p != NUL) { + if (*p == separator) { + break; + } + p++; + index++; + } + + token._last_index = *p == NUL ? buffer.size () : index; + token._start = start; + token._length = static_cast(p - start); + + return true; + } + + [[gnu::always_inline]] + auto next_token (const char separator, string_segment& token) const noexcept -> bool + { + return next_token (0, separator, token); + } + + [[gnu::always_inline]] + auto index_of (const TChar ch) const noexcept -> ssize_t + { + const TChar *p = buffer.get (); + while (p != nullptr && *p != NUL) { + if (*p == ch) { + return static_cast(p - buffer.get ()); + } + p++; + } + + return -1; + } + + [[gnu::always_inline]] + auto starts_with (const TChar *s, size_t s_length) const noexcept -> bool + { + if (s == nullptr || s_length == 0 || s_length > buffer.size ()) { + return false; + } + + return memcmp (buffer.get (), s, s_length) == 0; + } + + [[gnu::always_inline]] + auto starts_with_c (const char* s) noexcept -> bool + { + if (s == nullptr) { + return false; + } + + return starts_with (s, strlen (s)); + } + + template [[gnu::always_inline]] + auto starts_with (const char (&s)[Size]) noexcept -> bool + { + return starts_with (s, Size - 1); + } + + [[gnu::always_inline]] + auto starts_with (std::string_view const& s) noexcept -> bool + { + return starts_with (s.data (), s.length ()); + } + + [[gnu::always_inline]] + void set_length_after_direct_write (size_t new_length) noexcept + { + set_length (new_length); + terminate (); + } + + [[gnu::always_inline]] + void set_at (size_t index, const TChar ch) noexcept + { + ensure_valid_index (index); + TChar *p = buffer + index; + if (*p == NUL) { + return; + } + + *p = ch; + } + + [[gnu::always_inline]] + auto get_at (size_t index) const noexcept -> const TChar + { + ensure_valid_index (index); + return *(buffer.get () + index); + } + + [[gnu::always_inline]] + auto get_at (size_t index) noexcept -> TChar& + { + ensure_valid_index (index); + return *(buffer.get () + index); + } + + [[gnu::always_inline]] + auto get () const noexcept -> const TChar* + { + return buffer.get (); + } + + [[gnu::always_inline]] + auto get () noexcept -> TChar* + { + return buffer.get (); + } + + [[gnu::always_inline]] + auto size () const noexcept -> size_t + { + return buffer.size (); + } + + [[gnu::always_inline]] + auto operator[] (size_t index) const noexcept -> char + { + return get_at (index); + } + + [[gnu::always_inline]] + auto operator[] (size_t index) noexcept -> char& + { + return get_at (index); + } + + protected: + template [[gnu::always_inline]] + void append_integer (Integer i) noexcept + { + static_assert (std::is_integral_v); + + resize_for_extra (Constants::MAX_INTEGER_DIGIT_COUNT_BASE10); + if constexpr (BoundsCheck) { + ensure_have_extra (Constants::MAX_INTEGER_DIGIT_COUNT_BASE10); + } + + if (i == 0) { + constexpr char zero[] = "0"; + constexpr size_t zero_len = sizeof(zero) - 1uz; + + append (zero, zero_len); + return; + } + + TChar temp_buf[Constants::MAX_INTEGER_DIGIT_COUNT_BASE10 + 1uz]; + TChar *p = temp_buf + Constants::MAX_INTEGER_DIGIT_COUNT_BASE10; + *p = NUL; + TChar *end = p; + + uint32_t x; + if constexpr (sizeof(Integer) > 4uz) { + uint64_t y; + + if constexpr (std::is_signed_v) { + y = static_cast(i > 0 ? i : -i); + } else { + y = static_cast(i); + } + while (y > std::numeric_limits::max ()) { + *--p = (y % 10) + ZERO; + y /= 10; + } + x = static_cast(y); + } else { + if constexpr (std::is_signed_v) { + x = static_cast(i > 0 ? i : -i); + } else { + x = static_cast(i); + } + } + + while (x > 0) { + *--p = (x % 10) + ZERO; + x /= 10; + } + + if constexpr (std::is_signed_v) { + if (i < 0) + *--p = '-'; + } + + append (p, static_cast(end - p)); + } + + [[gnu::always_inline]] + void ensure_valid_index (size_t access_index) const noexcept + { + if (access_index < idx && access_index < buffer.size ()) [[likely]] { + return; + } + + char *message = nullptr; + int n = asprintf (&message, "Index %zu is out of range (0 - %zu)", access_index, idx); + Helpers::abort_application (n == -1 ? "Index out of range" : message); + } + + [[gnu::always_inline]] + void ensure_have_extra (size_t length) noexcept + { + size_t needed_space = Helpers::add_with_overflow_check (length, idx + 1); + if (needed_space > buffer.size ()) { + char *message = nullptr; + int n = asprintf ( + &message, + "Attempt to store too much data in a buffer (capacity: %zu; exceeded by: %zu)", + buffer.size (), + needed_space - buffer.size () + ); + Helpers::abort_application (n == -1 ? "Attempt to store too much data in a buffer" : message); + } + } + + [[gnu::always_inline]] + void resize_for_extra (size_t needed_space) noexcept + { + if constexpr (TStorage::has_resize) { + size_t required_space = Helpers::add_with_overflow_check (needed_space, idx + 1uz); + size_t current_size = buffer.size (); + if (required_space > current_size) { + size_t new_size = Helpers::add_with_overflow_check (current_size, (current_size / 2uz)); + new_size = Helpers::add_with_overflow_check (new_size, required_space); + buffer.resize (new_size); + } + } + } + + private: + size_t idx; + TStorage buffer; + }; + + template + class static_local_string : public string_base, TChar> + { + using base = string_base, TChar>; + + public: + explicit static_local_string (size_t initial_size = 0uz) noexcept + : base (initial_size) + {} + + explicit static_local_string (const string_segment &token) noexcept + : base (token) + {} + + template + explicit static_local_string (const char (&str)[N]) + : base (N) + { + append (str); + } + }; + + template + class dynamic_local_string : public string_base, TChar> + { + using base = string_base, TChar>; + + public: + explicit dynamic_local_string (size_t initial_size = 0uz) + : base (initial_size) + {} + + explicit dynamic_local_string (const string_segment &token) noexcept + : base (token) + {} + + template + explicit dynamic_local_string (const char (&str)[N]) + : base (N) + { + base::append (str); + } + + explicit dynamic_local_string (std::string_view const& str) + : base (str.length ()) + { + base::append (str); + } + }; +} diff --git a/src/native-clr/include/shared/cpp-util.hh b/src/native-clr/include/shared/cpp-util.hh new file mode 100644 index 00000000000..2121305dd94 --- /dev/null +++ b/src/native-clr/include/shared/cpp-util.hh @@ -0,0 +1,212 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "helpers.hh" + +namespace xamarin::android::detail { + [[gnu::always_inline, gnu::flatten]] + static inline const char* + _format_message (const char *format, ...) noexcept + { + va_list ap; + va_start (ap, format); + + char *message; + int ret = vasprintf (&message, format, ap); + + va_end (ap); + return ret == -1 ? "Out of memory" : message; + } +} + +template F> +[[gnu::always_inline, gnu::flatten]] +static inline void +abort_unless (bool condition, F&& get_message, std::source_location sloc = std::source_location::current ()) noexcept +{ + static_assert (std::is_same::type, const char*>::value, "get_message must return 'const char*'"); + + if (condition) [[likely]] { + return; + } + + xamarin::android::Helpers::abort_application (std::invoke (get_message), true /* log_location */, sloc); +} + +[[gnu::always_inline, gnu::flatten]] +static inline void +abort_unless (bool condition, const char *message, std::source_location sloc = std::source_location::current ()) noexcept +{ + if (condition) [[likely]] { + return; + } + xamarin::android::Helpers::abort_application (message, true /* log_location */, sloc); +} + +template +[[gnu::always_inline, gnu::flatten]] +static inline void +abort_if_invalid_pointer_argument (T *ptr, const char *ptr_name, std::source_location sloc = std::source_location::current ()) noexcept +{ + abort_unless ( + ptr != nullptr, + [&ptr_name] { return xamarin::android::detail::_format_message ("Parameter '%s' must be a valid pointer", ptr_name); }, + sloc + ); +} + +[[gnu::always_inline, gnu::flatten]] +static inline void +abort_if_negative_integer_argument (int arg, const char *arg_name, std::source_location sloc = std::source_location::current ()) noexcept +{ + abort_unless ( + arg > 0, + [&arg_name] { return xamarin::android::detail::_format_message ("Parameter '%s' must be a valid pointer", arg_name); }, + sloc + ); +} + +// Helper to use in "printf debugging". Normally not used in code anywhere. No code should be shipped with any +// of the calls present. +[[gnu::always_inline]] +inline void pd_log_location (std::source_location sloc = std::source_location::current ()) noexcept +{ + log_info_nocheck (LOG_DEFAULT, "loc: {}:{} ('{}')", sloc.file_name (), sloc.line (), sloc.function_name ()); +} + +namespace xamarin::android +{ + template + struct CDeleter final + { + using UnderlyingType = std::remove_cv_t; + + void operator() (T* p) + { + UnderlyingType *ptr; + + if constexpr (std::is_const_v) { + ptr = const_cast*> (p); + } else { + ptr = p; + } + + std::free (reinterpret_cast(ptr)); + } + }; + + template + using c_unique_ptr = std::unique_ptr>; + + template + using char_array = std::array; + + template + constexpr auto concat_const (const char (&...parts)[Length]) + { + // `parts` being constant string arrays, Length for each of them includes the trailing NUL byte, thus the + // `sizeof... (Length)` part which subtracts the number of template parameters - the amount of NUL bytes so that + // we don't waste space. + constexpr size_t total_length = (... + Length) - sizeof... (Length); + char_array ret; // lgtm [cpp/paddingbyteinformationdisclosure] the buffer is filled in the loop below + ret[total_length] = 0; + + size_t i = 0uz; + for (char const* from : {parts...}) { + for (; *from != '\0'; i++) { + ret[i] = *from++; + } + } + + return ret; + }; + + template + concept StringViewPart = std::is_same_v; + + template + consteval auto concat_string_views (T const&... parts) + { + std::array ret; // lgtm [cpp/paddingbyteinformationdisclosure] the buffer is filled in the loop below + ret[TotalLength] = 0; + + size_t i = 0; + for (std::string_view const& sv : {parts...}) { + for (const char ch : sv) { + ret[i] = ch; + i++; + } + } + + return ret; + } + + consteval size_t calc_size (std::string_view const& sv1) noexcept + { + return sv1.size (); + } + + template + consteval size_t calc_size (std::string_view const& sv1, T const&... other_svs) noexcept + { + return sv1.size () + calc_size (other_svs...); + } + + template , int> = 0> + constexpr TEnum operator & (TEnum l, TEnum r) noexcept + { + using etype = std::underlying_type_t; + return static_cast(static_cast(l) & static_cast(r)); + } + + template , int> = 0> + constexpr TEnum& operator &= (TEnum& l, TEnum r) noexcept + { + return l = (l & r); + } + + template , int> = 0> + constexpr TEnum operator | (TEnum l, TEnum r) noexcept + { + using etype = std::underlying_type_t; + return static_cast(static_cast(l) | static_cast(r)); + } + + template , int> = 0> + constexpr TEnum& operator |= (TEnum& l, TEnum r) noexcept + { + return l = (l | r); + } + + template , int> = 0> + constexpr TEnum operator ~ (TEnum r) noexcept + { + using etype = std::underlying_type_t; + return static_cast (~static_cast(r)); + } + + template , int> = 0> + constexpr TEnum operator ^ (TEnum l, TEnum r) noexcept + { + using etype = std::underlying_type_t; + return static_cast(static_cast(l) ^ static_cast(r)); + } + + template , int> = 0> + constexpr TEnum& operator ^= (TEnum& l, TEnum r) noexcept + { + return l = (l ^ r); + } +} diff --git a/src/native-clr/include/shared/helpers.hh b/src/native-clr/include/shared/helpers.hh new file mode 100644 index 00000000000..22e29b40f25 --- /dev/null +++ b/src/native-clr/include/shared/helpers.hh @@ -0,0 +1,105 @@ +#pragma once + +#include +#include +#include +#include + +#include + +using namespace std::string_view_literals; + +namespace xamarin::android +{ + namespace detail { + template + concept TPointer = requires { std::is_pointer_v; }; + } + + class [[gnu::visibility("hidden")]] Helpers + { + public: + template + [[gnu::always_inline]] + static auto add_with_overflow_check (P1 a, P2 b, std::source_location sloc = std::source_location::current ()) noexcept -> Ret + { + constexpr bool DoNotLogLocation = false; + Ret ret; + + if (__builtin_add_overflow (a, b, &ret)) [[unlikely]] { + // It will leak memory, but it's fine, we're exiting the app anyway + char *message = nullptr; + int n = asprintf (&message, "Integer overflow on addition at %s:%u", sloc.file_name (), sloc.line ()); + abort_application (n == -1 ? "Integer overflow on addition" : message, DoNotLogLocation, sloc); + } + + return ret; + } + + template + [[gnu::always_inline]] + static auto multiply_with_overflow_check (P1 a, P2 b, std::source_location sloc = std::source_location::current ()) noexcept -> Ret + { + constexpr bool DoNotLogLocation = false; + Ret ret; + + if (__builtin_mul_overflow (a, b, &ret)) [[unlikely]] { + // It will leak memory, but it's fine, we're exiting the app anyway + char *message = nullptr; + int n = asprintf (&message, "Integer overflow on multiplication at %s:%u", sloc.file_name (), sloc.line ()); + abort_application (n == -1 ? "Integer overflow on multiplication" : message, DoNotLogLocation, sloc); + } + + return ret; + } + + [[noreturn]] + static void abort_application (LogCategories category, const char *message, bool log_location = true, std::source_location sloc = std::source_location::current ()) noexcept; + + [[noreturn]] + static void abort_application (LogCategories category, std::string const& message, bool log_location = true, std::source_location sloc = std::source_location::current ()) noexcept + { + abort_application (category, message.c_str (), log_location, sloc); + } + + [[noreturn]] + static void abort_application (LogCategories category, std::string_view const& message, bool log_location = true, std::source_location sloc = std::source_location::current ()) noexcept + { + abort_application (category, message.data (), log_location, sloc); + } + + [[noreturn]] + static void abort_application (const char *message, bool log_location = true, std::source_location sloc = std::source_location::current ()) noexcept + { + abort_application (LOG_DEFAULT, message, log_location, sloc); + } + + [[noreturn]] + static void abort_application (std::string const& message, bool log_location = true, std::source_location sloc = std::source_location::current ()) noexcept + { + abort_application (LOG_DEFAULT, message.c_str (), log_location, sloc); + } + + [[noreturn]] + static void abort_application (std::string_view const& message, bool log_location = true, std::source_location sloc = std::source_location::current ()) noexcept + { + abort_application (LOG_DEFAULT, message.data (), log_location, sloc); + } + }; + + template [[gnu::always_inline]] + static inline constexpr auto pointer_add (TPtr ptr, size_t offset) noexcept -> TRet + { + return reinterpret_cast(reinterpret_cast(ptr) + offset); + } + + [[gnu::always_inline]] + static inline constexpr auto optional_string (const char* s, const char *replacement = nullptr) noexcept -> const char* + { + if (s != nullptr) [[likely]] { + return s; + } + + return replacement == nullptr ? "" : replacement; + } +} diff --git a/src/native-clr/include/shared/log_level.hh b/src/native-clr/include/shared/log_level.hh new file mode 100644 index 00000000000..fc7a7566910 --- /dev/null +++ b/src/native-clr/include/shared/log_level.hh @@ -0,0 +1,26 @@ +#pragma once + +#include + +namespace xamarin::android { + enum class LogTimingCategories : uint32_t + { + Default = 0, + Bare = 1 << 0, + FastBare = 1 << 1, + }; + + // Keep in sync with LogLevel defined in JNIEnv.cs + enum class LogLevel : unsigned int + { + Unknown = 0x00, + Default = 0x01, + Verbose = 0x02, + Debug = 0x03, + Info = 0x04, + Warn = 0x05, + Error = 0x06, + Fatal = 0x07, + Silent = 0x08 + }; +} diff --git a/src/native-clr/include/shared/log_types.hh b/src/native-clr/include/shared/log_types.hh new file mode 100644 index 00000000000..66b1cae5097 --- /dev/null +++ b/src/native-clr/include/shared/log_types.hh @@ -0,0 +1,112 @@ +#pragma once + +#include +#include +#include +#include + +#include "java-interop-logger.h" +#include "log_level.hh" + +// We redeclare macros here +#if defined(log_debug) +#undef log_debug +#endif + +#if defined(log_info) +#undef log_info +#endif + +#define DO_LOG_FMT(_level, _category_, _fmt_, ...) \ + do { \ + if ((log_categories & ((_category_))) != 0) { \ + ::log_ ## _level ## _nocheck_fmt ((_category_), _fmt_ __VA_OPT__(,) __VA_ARGS__); \ + } \ + } while (0) + +// +// For std::format spec, see https://en.cppreference.com/w/cpp/utility/format/spec +// + +// NOTE: _fmt_ takes arguments in the std::format style not the POSIX printf style +#define log_debug(_category_, _fmt_, ...) DO_LOG_FMT (debug, (_category_), (_fmt_) __VA_OPT__(,) __VA_ARGS__) + +// NOTE: _fmt_ takes arguments in the std::format style not the POSIX printf style +#define log_info(_category_, _fmt_, ...) DO_LOG_FMT (info, (_category_), (_fmt_) __VA_OPT__(,) __VA_ARGS__) + +// NOTE: _fmt_ takes arguments in the std::format style not the POSIX printf style +#define log_warn(_category_, _fmt_, ...) log_warn_fmt ((_category_), (_fmt_) __VA_OPT__(,) __VA_ARGS__) + +// NOTE: _fmt_ takes arguments in the std::format style not the POSIX printf style +#define log_error(_category_, _fmt_, ...) log_error_fmt ((_category_), (_fmt_) __VA_OPT__(,) __VA_ARGS__) + +// NOTE: _fmt_ takes arguments in the std::format style not the POSIX printf style +#define log_fatal(_category_, _fmt_, ...) log_fatal_fmt ((_category_), (_fmt_) __VA_OPT__(,) __VA_ARGS__) + +namespace xamarin::android { + // A slightly faster alternative to other log functions as it doesn't parse the message + // for format placeholders nor it uses variable arguments + void log_write (LogCategories category, LogLevel level, const char *message) noexcept; +} + +template [[gnu::always_inline]] +static inline constexpr void log_debug_nocheck_fmt (LogCategories category, std::format_string fmt, Args&& ...args) +{ + log_write (category, xamarin::android::LogLevel::Debug, std::format (fmt, std::forward(args)...).c_str ()); +} + +[[gnu::always_inline]] +static inline constexpr void log_debug_nocheck (LogCategories category, std::string_view const& message) noexcept +{ + log_write (category, xamarin::android::LogLevel::Debug, message.data ()); +} + +template [[gnu::always_inline]] +static inline constexpr void log_info_nocheck_fmt (LogCategories category, std::format_string fmt, Args&& ...args) +{ + log_write (category, xamarin::android::LogLevel::Info, std::format (fmt, std::forward(args)...).c_str ()); +} + +[[gnu::always_inline]] +static inline constexpr void log_info_nocheck (LogCategories category, std::string_view const& message) noexcept +{ + log_write (category, xamarin::android::LogLevel::Info, message.data ()); +} + +template [[gnu::always_inline]] +static inline constexpr void log_warn_fmt (LogCategories category, std::format_string fmt, Args&& ...args) noexcept +{ + log_write (category, xamarin::android::LogLevel::Warn, std::format (fmt, std::forward(args)...).c_str ()); +} + +[[gnu::always_inline]] +static inline constexpr void log_warn_fmt (LogCategories category, std::string_view const& message) noexcept +{ + log_write (category, xamarin::android::LogLevel::Warn, message.data ()); +} + +template [[gnu::always_inline]] +static inline constexpr void log_error_fmt (LogCategories category, std::format_string fmt, Args&& ...args) noexcept +{ + log_write (category, xamarin::android::LogLevel::Error, std::format (fmt, std::forward(args)...).c_str ()); +} + +[[gnu::always_inline]] +static inline constexpr void log_error_fmt (LogCategories category, std::string_view const& message) noexcept +{ + log_write (category, xamarin::android::LogLevel::Error, message.data ()); +} + +template [[gnu::always_inline]] +static inline constexpr void log_fatal_fmt (LogCategories category, std::format_string fmt, Args&& ...args) noexcept +{ + log_write (category, xamarin::android::LogLevel::Fatal, std::format (fmt, std::forward(args)...).c_str ()); +} + +[[gnu::always_inline]] +static inline constexpr void log_fatal_fmt (LogCategories category, std::string_view const& message) noexcept +{ + log_write (category, xamarin::android::LogLevel::Fatal, message.data ()); +} + +extern unsigned int log_categories; diff --git a/src/native-clr/include/shared/xxhash.hh b/src/native-clr/include/shared/xxhash.hh new file mode 100644 index 00000000000..b66c2ce309a --- /dev/null +++ b/src/native-clr/include/shared/xxhash.hh @@ -0,0 +1,192 @@ +#pragma once + +#if INTPTR_MAX == INT64_MAX +#define XXH_NO_STREAM +#define XXH_INLINE_ALL +#define XXH_NAMESPACE xaInternal_ +#include +#include +#endif + +// +// Based on original code at https://github.com/ekpyron/xxhashct +// +// Original code license: +// + +/** +* MIT License +* +* Copyright (c) 2021 Zachary Arnaise +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +*/ + +#include +#include + +namespace xamarin::android +{ + class xxhash32 final + { + static constexpr uint32_t PRIME1 = 0x9E3779B1U; + static constexpr uint32_t PRIME2 = 0x85EBCA77U; + static constexpr uint32_t PRIME3 = 0xC2B2AE3DU; + static constexpr uint32_t PRIME4 = 0x27D4EB2FU; + static constexpr uint32_t PRIME5 = 0x165667B1U; + + public: + // We don't use any special seed in XA, the template parameter is just to keep the algorithm more easily + // understood and to run compile-time algorithm correctness tests + template + [[gnu::always_inline]] + static constexpr auto hash (const char *input, size_t len) noexcept -> uint32_t + { + return finalize ( + (len >= 16 ? h16bytes (input, len) : Seed + PRIME5) + static_cast(len), + (input) + (len & ~0xFU), + len & 0xF + ); + } + + template + [[gnu::always_inline]] + static constexpr auto hash (const char (&input)[Size]) noexcept -> uint32_t + { + return hash (input, Size - 1); + } + + template + [[gnu::always_inline]] + static constexpr auto hash (std::string_view const& input) noexcept -> uint32_t + { + return hash (input.data (), input.length ()); + } + + private: + // 32-bit rotate left. + template [[gnu::always_inline]] + static constexpr auto rotl (uint32_t x) noexcept -> uint32_t + { + return ((x << Bits) | (x >> (32 - Bits))); + } + + // Normal stripe processing routine. + [[gnu::always_inline]] + static constexpr auto round (uint32_t acc, const uint32_t input) noexcept -> uint32_t + { + return rotl<13> (acc + (input * PRIME2)) * PRIME1; + } + + template [[gnu::always_inline]] + static constexpr auto avalanche_step (const uint32_t h) noexcept -> uint32_t + { + return (h ^ (h >> RShift)) * Prime; + } + + // Mixes all bits to finalize the hash. + [[gnu::always_inline]] + static constexpr auto avalanche (const uint32_t h) noexcept -> uint32_t + { + return + avalanche_step<16, 1> ( + avalanche_step<13, PRIME3> ( + avalanche_step <15, PRIME2> (h) + ) + ); + } + + // little-endian version: all our target platforms are little-endian + [[gnu::always_inline]] + static constexpr auto endian32 (const char *v) noexcept -> uint32_t + { + return + static_cast(static_cast(v[0])) | + (static_cast(static_cast(v[1])) << 8) | + (static_cast(static_cast(v[2])) << 16) | + (static_cast(static_cast(v[3])) << 24); + } + + [[gnu::always_inline]] + static constexpr auto fetch32 (const char *p, const uint32_t v) noexcept -> uint32_t + { + return round (v, endian32 (p)); + } + + // Processes the last 0-15 bytes of p. + [[gnu::always_inline]] + static constexpr auto finalize (const uint32_t h, const char *p, size_t len) noexcept -> uint32_t + { + return + (len >= 4) ? finalize (rotl<17> (h + (endian32 (p) * PRIME3)) * PRIME4, p + 4, len - 4) : + (len > 0) ? finalize (rotl<11> (h + (static_cast(*p) * PRIME5)) * PRIME1, p + 1, len - 1) : + avalanche (h); + } + + [[gnu::always_inline]] + static constexpr auto h16bytes (const char *p, size_t len, const uint32_t v1, const uint32_t v2, const uint32_t v3, const uint32_t v4) noexcept -> uint32_t + { + return + (len >= 16) ? h16bytes (p + 16, len - 16, fetch32 (p, v1), fetch32 (p+4, v2), fetch32 (p+8, v3), fetch32 (p+12, v4)) : + rotl<1> (v1) + rotl<7> (v2) + rotl<12> (v3) + rotl<18> (v4); + } + + // We don't use any special seed in XA, the template parameter is just to keep the algorithm more easily + // understood + template + [[gnu::always_inline]] + static constexpr auto h16bytes (const char *p, size_t len) noexcept -> uint32_t + { + return h16bytes(p, len, Seed + PRIME1 + PRIME2, Seed + PRIME2, Seed, Seed - PRIME1); + } + }; + +#if INTPTR_MAX == INT64_MAX + class xxhash64 final + { + public: + [[gnu::always_inline]] + static auto hash (const char *p, size_t len) noexcept -> XXH64_hash_t + { + return XXH3_64bits (static_cast(p), len); + } + + [[gnu::always_inline]] + static consteval auto hash (std::string_view const& input) noexcept -> XXH64_hash_t + { + return constexpr_xxh3::XXH3_64bits_const (input.data (), input.length ()); + } + + // The C XXH64_64bits function from xxhash.h is not `constexpr` or `consteval`, so we cannot call it here. + // At the same time, at build time performance is not that important, so we call the "unoptmized" `consteval` + // C++ implementation here + template [[gnu::always_inline]] + static consteval auto hash (const char (&input)[Size]) noexcept -> XXH64_hash_t + { + return constexpr_xxh3::XXH3_64bits_const (input); + } + }; + + using hash_t = XXH64_hash_t; + using xxhash = xxhash64; +#else + using hash_t = uint32_t; + using xxhash = xxhash32; +#endif +} diff --git a/src/native-clr/include/startup/zip.hh b/src/native-clr/include/startup/zip.hh new file mode 100644 index 00000000000..96afac707bd --- /dev/null +++ b/src/native-clr/include/startup/zip.hh @@ -0,0 +1,31 @@ +#pragma once + +#include + +#include + +#include +#include + +namespace xamarin::android { + class Zip + { + private: + static inline constexpr off_t ZIP_EOCD_LEN = 22; + static inline constexpr off_t ZIP_CENTRAL_LEN = 46; + static inline constexpr off_t ZIP_LOCAL_LEN = 30; + + static inline constexpr std::string_view ZIP_CENTRAL_MAGIC { "PK\1\2" }; + static inline constexpr std::string_view ZIP_LOCAL_MAGIC { "PK\3\4" }; + static inline constexpr std::string_view ZIP_EOCD_MAGIC { "PK\5\6" }; + + static constexpr std::string_view zip_path_separator { "/" }; + static constexpr std::string_view apk_lib_dir_name { "lib" }; + + static constexpr size_t assemblies_prefix_size = calc_size(apk_lib_dir_name, zip_path_separator, Constants::android_lib_abi, zip_path_separator); + static constexpr auto assemblies_prefix_array = concat_string_views (apk_lib_dir_name, zip_path_separator, Constants::android_lib_abi, zip_path_separator); + + // .data() must be used otherwise string_view length will include the trailing \0 in the array + static constexpr std::string_view assemblies_prefix { assemblies_prefix_array.data () }; + }; +} diff --git a/src/native-clr/include/xamarin-app.hh b/src/native-clr/include/xamarin-app.hh new file mode 100644 index 00000000000..bcf6287c233 --- /dev/null +++ b/src/native-clr/include/xamarin-app.hh @@ -0,0 +1,380 @@ +// Dear Emacs, this is a -*- C++ -*- header +#pragma once + +#include + +#include + +#include "shared/xxhash.hh" + +static constexpr uint64_t FORMAT_TAG = 0x00035E6972616D58; // 'Xmari^XY' where XY is the format version +static constexpr uint32_t COMPRESSED_DATA_MAGIC = 0x5A4C4158; // 'XALZ', little-endian +static constexpr uint32_t ASSEMBLY_STORE_MAGIC = 0x41424158; // 'XABA', little-endian + +// The highest bit of assembly store version is a 64-bit ABI flag +#if INTPTR_MAX == INT64_MAX +static constexpr uint32_t ASSEMBLY_STORE_64BIT_FLAG = 0x80000000; +#else +static constexpr uint32_t ASSEMBLY_STORE_64BIT_FLAG = 0x00000000; +#endif + +// The second-to-last byte denotes the actual ABI +#if defined(__aarch64__) +static constexpr uint32_t ASSEMBLY_STORE_ABI = 0x00010000; +#elif defined(__arm__) +static constexpr uint32_t ASSEMBLY_STORE_ABI = 0x00020000; +#elif defined(__x86_64__) +static constexpr uint32_t ASSEMBLY_STORE_ABI = 0x00030000; +#elif defined(__i386__) +static constexpr uint32_t ASSEMBLY_STORE_ABI = 0x00040000; +#endif + +// Increase whenever an incompatible change is made to the assembly store format +static constexpr uint32_t ASSEMBLY_STORE_FORMAT_VERSION = 2 | ASSEMBLY_STORE_64BIT_FLAG | ASSEMBLY_STORE_ABI; + +static constexpr uint32_t MODULE_MAGIC_NAMES = 0x53544158; // 'XATS', little-endian +static constexpr uint32_t MODULE_INDEX_MAGIC = 0x49544158; // 'XATI', little-endian +static constexpr uint8_t MODULE_FORMAT_VERSION = 2; // Keep in sync with the value in src/Xamarin.Android.Build.Tasks/Utilities/TypeMapGenerator.cs + +#if defined (DEBUG) +struct BinaryTypeMapHeader +{ + uint32_t magic; + uint32_t version; + uint32_t entry_count; + uint32_t java_name_width; + uint32_t managed_name_width; + uint32_t assembly_name_length; +}; + +struct TypeMapIndexHeader +{ + uint32_t magic; + uint32_t version; + uint32_t entry_count; + uint32_t module_file_name_width; +}; + +struct TypeMapEntry +{ + const char *from; + const char *to; +}; + +// MUST match src/Xamarin.Android.Build.Tasks/Utilities/TypeMappingDebugNativeAssemblyGenerator.cs +struct TypeMap +{ + uint32_t entry_count; + char *assembly_name; + uint8_t *data; + const TypeMapEntry *java_to_managed; + const TypeMapEntry *managed_to_java; +}; +#else +struct TypeMapModuleEntry +{ + uint32_t type_token_id; + uint32_t java_map_index; +}; + +struct TypeMapModule +{ + uint8_t module_uuid[16]; + uint32_t entry_count; + uint32_t duplicate_count; + TypeMapModuleEntry const *map; + TypeMapModuleEntry const *duplicate_map; + char const *assembly_name; + uint8_t *image; + uint32_t java_name_width; + uint8_t *java_map; +}; + +struct TypeMapJava +{ + uint32_t module_index; + uint32_t type_token_id; + uint32_t java_name_index; +}; +#endif + +struct CompressedAssemblyHeader +{ + uint32_t magic; // COMPRESSED_DATA_MAGIC + uint32_t descriptor_index; + uint32_t uncompressed_length; +}; + +struct CompressedAssemblyDescriptor +{ + uint32_t uncompressed_file_size; + bool loaded; + uint8_t *data; +}; + +struct CompressedAssemblies +{ + uint32_t count; + CompressedAssemblyDescriptor *descriptors; +}; + +struct XamarinAndroidBundledAssembly +{ + int32_t file_fd; + char *file_name; + uint32_t data_offset; + uint32_t data_size; + uint8_t *data; + uint32_t name_length; + char *name; +}; + +// +// Assembly store format +// +// Each target ABI/architecture has a single assembly store file, composed of the following parts: +// +// [HEADER] +// [INDEX] +// [ASSEMBLY_DESCRIPTORS] +// [ASSEMBLY DATA] +// +// Formats of the sections above are as follows: +// +// HEADER (fixed size) +// [MAGIC] uint; value: 0x41424158 +// [FORMAT_VERSION] uint; store format version number +// [ENTRY_COUNT] uint; number of entries in the store +// [INDEX_ENTRY_COUNT] uint; number of entries in the index +// [INDEX_SIZE] uint; index size in bytes +// +// INDEX (variable size, HEADER.ENTRY_COUNT*2 entries, for assembly names with and without the extension) +// [NAME_HASH] uint on 32-bit platforms, ulong on 64-bit platforms; xxhash of the assembly name +// [DESCRIPTOR_INDEX] uint; index into in-store assembly descriptor array +// +// ASSEMBLY_DESCRIPTORS (variable size, HEADER.ENTRY_COUNT entries), each entry formatted as follows: +// [MAPPING_INDEX] uint; index into a runtime array where assembly data pointers are stored +// [DATA_OFFSET] uint; offset from the beginning of the store to the start of assembly data +// [DATA_SIZE] uint; size of the stored assembly data +// [DEBUG_DATA_OFFSET] uint; offset from the beginning of the store to the start of assembly PDB data, 0 if absent +// [DEBUG_DATA_SIZE] uint; size of the stored assembly PDB data, 0 if absent +// [CONFIG_DATA_OFFSET] uint; offset from the beginning of the store to the start of assembly .config contents, 0 if absent +// [CONFIG_DATA_SIZE] uint; size of the stored assembly .config contents, 0 if absent +// +// ASSEMBLY_NAMES (variable size, HEADER.ENTRY_COUNT entries), each entry formatted as follows: +// [NAME_LENGTH] uint: length of assembly name +// [NAME] byte: UTF-8 bytes of assembly name, without the NUL terminator +// + +// +// The structures which are found in the store files must be packed to avoid problems when calculating offsets (runtime +// size of a structure can be different than the real data size) +// +struct [[gnu::packed]] AssemblyStoreHeader final +{ + uint32_t magic; + uint32_t version; + uint32_t entry_count; + uint32_t index_entry_count; + uint32_t index_size; // index size in bytes +}; + +struct [[gnu::packed]] AssemblyStoreIndexEntry final +{ + xamarin::android::hash_t name_hash; + uint32_t descriptor_index; +}; + +struct [[gnu::packed]] AssemblyStoreEntryDescriptor final +{ + uint32_t mapping_index; + + uint32_t data_offset; + uint32_t data_size; + + uint32_t debug_data_offset; + uint32_t debug_data_size; + + uint32_t config_data_offset; + uint32_t config_data_size; +}; + +struct AssemblyStoreRuntimeData final +{ + uint8_t *data_start; + uint32_t assembly_count; + uint32_t index_entry_count; + AssemblyStoreEntryDescriptor *assemblies; +}; + +struct AssemblyStoreSingleAssemblyRuntimeData final +{ + uint8_t *image_data; + uint8_t *debug_info_data; + uint8_t *config_data; + AssemblyStoreEntryDescriptor *descriptor; +}; + +// Keep in strict sync with: +// src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfig.cs +// src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/EnvironmentHelper.cs +struct ApplicationConfig +{ + bool uses_assembly_preload; + bool jni_add_native_method_registration_attribute_present; + bool have_runtime_config_blob; + bool marshal_methods_enabled; + bool ignore_split_configs; + uint32_t package_naming_policy; + uint32_t environment_variable_count; + uint32_t system_property_count; + uint32_t number_of_assemblies_in_apk; + uint32_t bundled_assembly_name_width; + uint32_t number_of_dso_cache_entries; + uint32_t number_of_aot_cache_entries; + uint32_t number_of_shared_libraries; + uint32_t android_runtime_jnienv_class_token; + uint32_t jnienv_initialize_method_token; + uint32_t jnienv_registerjninatives_method_token; + uint32_t jni_remapping_replacement_type_count; + uint32_t jni_remapping_replacement_method_index_entry_count; + const char *android_package_name; +}; + +struct DSOApkEntry +{ + uint64_t name_hash; + uint32_t offset; // offset into the APK + int32_t fd; // apk file descriptor +}; + +struct DSOCacheEntry +{ + uint64_t hash; + uint64_t real_name_hash; + bool ignore; + const char *name; + void *handle; +}; + +struct JniRemappingString +{ + const uint32_t length; + const char *str; +}; + +struct JniRemappingReplacementMethod +{ + const char *target_type; + const char *target_name; + // const char *target_signature; + // const int32_t param_count; + const bool is_static; +}; + +struct JniRemappingIndexMethodEntry +{ + const JniRemappingString name; + const JniRemappingString signature; + const JniRemappingReplacementMethod replacement; +}; + +struct JniRemappingIndexTypeEntry +{ + const JniRemappingString name; + const uint32_t method_count; + const JniRemappingIndexMethodEntry *methods; +}; + +struct JniRemappingTypeReplacementEntry +{ + const JniRemappingString name; + const char *replacement; +}; + +extern "C" { + [[gnu::visibility("default")]] extern const JniRemappingIndexTypeEntry jni_remapping_method_replacement_index[]; + [[gnu::visibility("default")]] extern const JniRemappingTypeReplacementEntry jni_remapping_type_replacements[]; + + [[gnu::visibility("default")]] extern const uint64_t format_tag; + +#if defined (DEBUG) + [[gnu::visibility("default")]] extern const TypeMap type_map; // MUST match src/Xamarin.Android.Build.Tasks/Utilities/TypeMappingDebugNativeAssemblyGenerator.cs +#else + [[gnu::visibility("default")]] extern const uint32_t map_module_count; + [[gnu::visibility("default")]] extern const uint32_t java_type_count; + [[gnu::visibility("default")]] extern const char* const java_type_names[]; + [[gnu::visibility("default")]] extern TypeMapModule map_modules[]; + [[gnu::visibility("default")]] extern const TypeMapJava map_java[]; + [[gnu::visibility("default")]] extern const xamarin::android::hash_t map_java_hashes[]; +#endif + + [[gnu::visibility("default")]] extern CompressedAssemblies compressed_assemblies; + [[gnu::visibility("default")]] extern const ApplicationConfig application_config; + [[gnu::visibility("default")]] extern const char* const app_environment_variables[]; + [[gnu::visibility("default")]] extern const char* const app_system_properties[]; + + [[gnu::visibility("default")]] extern const char* const mono_aot_mode_name; + + [[gnu::visibility("default")]] extern XamarinAndroidBundledAssembly bundled_assemblies[]; + [[gnu::visibility("default")]] extern AssemblyStoreSingleAssemblyRuntimeData assembly_store_bundled_assemblies[]; + [[gnu::visibility("default")]] extern AssemblyStoreRuntimeData assembly_store; + + [[gnu::visibility("default")]] extern DSOCacheEntry dso_cache[]; + [[gnu::visibility("default")]] extern DSOCacheEntry aot_dso_cache[]; + [[gnu::visibility("default")]] extern DSOApkEntry dso_apk_entries[]; +} + +// +// Support for marshal methods +// +#if defined (RELEASE) +struct MarshalMethodsManagedClass +{ + const uint32_t token; + void *klass; +}; + +// Number of assembly name forms for which we generate hashes (essentially file name mutations. For instance +// `HelloWorld.dll`, `HelloWorld`, `en-US/HelloWorld` etc). This is multiplied by the number of assemblies in the apk to +// obtain number of entries in the `assembly_image_cache_hashes` and `assembly_image_cache_indices` entries +constexpr uint32_t number_of_assembly_name_forms_in_image_cache = 3; + +// These 3 arrays constitute the cache used to store pointers to loaded managed assemblies. +// Three arrays are used so that we can have multiple hashes pointing to the same MonoImage*. +// +// This is done by the `assembly_image_cache_hashes` containing hashes for all mutations of some +// assembly's name (e.g. with culture prefix, without extension etc) and position of that hash in +// `assembly_image_cache_hashes` is an index into `assembly_image_cache_indices` which, in turn, +// stores final index into the `assembly_image_cache` array. +// +[[gnu::visibility("default")]] extern void* assembly_image_cache[]; +[[gnu::visibility("default")]] extern const uint32_t assembly_image_cache_indices[]; +[[gnu::visibility("default")]] extern const xamarin::android::hash_t assembly_image_cache_hashes[]; + +// Number of unique classes which contain native callbacks we bind +[[gnu::visibility("default")]] extern uint32_t marshal_methods_number_of_classes; +[[gnu::visibility("default")]] extern MarshalMethodsManagedClass marshal_methods_class_cache[]; + +// +// These tables store names of classes and managed callback methods used in the generated marshal methods +// code. They are used just for error reporting. +// +// Class names are found at the same indexes as their corresponding entries in the `marshal_methods_class_cache` array +// above. Method names are stored as token:name pairs and the array must end with an "invalid" terminator entry (token +// == 0; name == nullptr) +// +struct MarshalMethodName +{ + // combination of assembly index (high 32 bits) and method token (low 32 bits) + const uint64_t id; + const char *name; +}; + +[[gnu::visibility("default")]] extern const char* const mm_class_names[]; +[[gnu::visibility("default")]] extern 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); + +[[gnu::visibility("default")]] extern void xamarin_app_init (JNIEnv *env, get_function_pointer_fn fn) noexcept; +#endif // def RELEASE diff --git a/src/native-clr/java-interop/CMakeLists.txt b/src/native-clr/java-interop/CMakeLists.txt new file mode 100644 index 00000000000..702401df40c --- /dev/null +++ b/src/native-clr/java-interop/CMakeLists.txt @@ -0,0 +1,50 @@ +set(LIB_NAME xa-java-interop-clr) +set(LIB_ALIAS xa::java-interop-clr) + +set(JAVA_INTEROP_SOURCES + ${JAVA_INTEROP_SRC_PATH}/java-interop-dlfcn.cc + ${JAVA_INTEROP_SRC_PATH}/java-interop-mono.cc + ${JAVA_INTEROP_SRC_PATH}/java-interop-util.cc + ${JAVA_INTEROP_SRC_PATH}/java-interop-util.cc + ${JAVA_INTEROP_SRC_PATH}/java-interop.cc +) +add_clang_check_sources("${JAVA_INTEROP_SOURCES}") + +add_library( + ${LIB_NAME} + STATIC + ${JAVA_INTEROP_SOURCES} +) + +add_library(${LIB_ALIAS} ALIAS ${LIB_NAME}) + +set_static_library_suffix(${LIB_NAME}) + +target_include_directories( + ${LIB_NAME} + PUBLIC + "$" +) + +target_include_directories( + ${LIB_NAME} + SYSTEM PRIVATE + ${SYSROOT_CXX_INCLUDE_DIR} + ${MONO_RUNTIME_INCLUDE_DIR} +) + +target_compile_options( + ${LIB_NAME} + PRIVATE + ${XA_COMMON_CXX_ARGS} +) + +if(DEBUG_BUILD) + set_target_properties( + ${LIB_NAME} + PROPERTIES + ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" + ) +endif() + +xa_add_compile_definitions(${LIB_NAME}) diff --git a/src/native-clr/libnet-android.map.txt b/src/native-clr/libnet-android.map.txt new file mode 100644 index 00000000000..f7e3c7c9fdf --- /dev/null +++ b/src/native-clr/libnet-android.map.txt @@ -0,0 +1,12 @@ +LIBNET_ANDROID { + global: + JNI_OnLoad; + Java_mono_android_Runtime_dumpTimingData; + Java_mono_android_Runtime_init; + Java_mono_android_Runtime_notifyTimeZoneChanged; + Java_mono_android_Runtime_propagateUncaughtException; + Java_mono_android_Runtime_register; + + local: + *; +}; diff --git a/src/native-clr/lz4/CMakeLists.txt b/src/native-clr/lz4/CMakeLists.txt new file mode 100644 index 00000000000..16a35099fd5 --- /dev/null +++ b/src/native-clr/lz4/CMakeLists.txt @@ -0,0 +1,41 @@ +set(LIB_NAME xa-lz4-clr) +set(LIB_ALIAS xa::lz4-clr) + +set(LZ4_SRC_DIR "${EXTERNAL_DIR}/lz4/lib") +set(LZ4_INCLUDE_DIR ${LZ4_SRC_DIR}) + +set(LZ4_SOURCES + ${LZ4_SRC_DIR}/lz4.c +) + +add_library( + ${LIB_NAME} + STATIC + ${LZ4_SOURCES} +) + +add_library(${LIB_ALIAS} ALIAS ${LIB_NAME}) + +target_compile_definitions( + ${LIB_NAME} + PRIVATE + # Ugly, but this is the only way to change LZ4 symbols visibility without modifying lz4.h + "LZ4LIB_VISIBILITY=__attribute__ ((visibility (\"hidden\")))" + XXH_NAMESPACE=LZ4_ +) + +target_include_directories( + ${LIB_NAME} + PUBLIC + "$" +) + +if(DEBUG_BUILD) + set_target_properties( + ${LIB_NAME} + PROPERTIES + ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" + ) +endif() + +xa_add_compile_definitions(${LIB_NAME}) diff --git a/src/native-clr/native-clr.csproj b/src/native-clr/native-clr.csproj new file mode 100644 index 00000000000..43244cd9e8c --- /dev/null +++ b/src/native-clr/native-clr.csproj @@ -0,0 +1,22 @@ + + + + netstandard2.0 + Debug + AnyCPU + Exe + false + + + + + + $(MicrosoftAndroidSdkOutDir)lib\ + + + + + + + + diff --git a/src/native-clr/native-clr.targets b/src/native-clr/native-clr.targets new file mode 100644 index 00000000000..dba9f075f5b --- /dev/null +++ b/src/native-clr/native-clr.targets @@ -0,0 +1,144 @@ + + + + + + + + + + + + + <_ConfigureRuntimesInputs Include="CMakeLists.txt" /> + <_ConfigureRuntimesInputs Include="java-interop\CMakeLists.txt" /> + <_ConfigureRuntimesInputs Include="lz4\CMakeLists.txt" /> + <_ConfigureRuntimesInputs Include="..\..\build-tools\scripts\Ndk.targets" /> + <_ConfigureRuntimesOutputs Include="@(AndroidSupportedTargetJitAbi->'$(IntermediateOutputPath)\%(AndroidRID)-clr-Debug\CMakeCache.txt')" /> + <_ConfigureRuntimesOutputs Include="@(AndroidSupportedTargetJitAbi->'$(IntermediateOutputPath)\%(AndroidRID)-clr-Release\CMakeCache.txt')" /> + <_OutputDirsToCreate Include="$(IntermediateOutputPath)%(AndroidSupportedTargetJitAbi.AndroidRID)-clr-Debug" /> + <_OutputDirsToCreate Include="$(IntermediateOutputPath)%(AndroidSupportedTargetJitAbi.AndroidRID)-clr-Release" /> + + + + + + <_NoInline Condition=" '$(DoNotInlineMonodroid)' == 'true' ">-DDONT_INLINE=ON + <_NoStrip Condition=" '$(DoNotStripMonodroid)' == 'true' ">-DSTRIP_DEBUG=OFF + + <_CmakeAndroidFlags>$(_NoInline) $(_NoStrip) "$(MSBuildThisFileDirectory)" + + + + <_ConfigureRuntimeCommands Include="@(AndroidSupportedTargetJitAbi)"> + $(CmakePath) + --preset default-debug-%(AndroidSupportedTargetJitAbi.Identity) $(_CmakeAndroidFlags) + $(IntermediateOutputPath)%(AndroidSupportedTargetJitAbi.AndroidRID)-clr-Debug + + + <_ConfigureRuntimeCommands Include="@(AndroidSupportedTargetJitAbi)"> + $(CmakePath) + --preset default-release-%(AndroidSupportedTargetJitAbi.Identity) $(_CmakeAndroidFlags) + $(IntermediateOutputPath)%(AndroidSupportedTargetJitAbi.AndroidRID)-clr-Release + + + + + + + + + + + + <_MonoDroidSources Include="$(JavaInteropFullPath)\src\java-interop\*.cc;$(JavaInteropFullPath)\src\java-interop\*.h" /> + <_MonoDroidSources Include="$(LZ4SourceFullPath)\lib\lz4.c;$(LZ4SourceFullPath)\lib\lz4.h" /> + + + + + + <_BuildAndroidRuntimesInputs Include="@(AndroidSupportedTargetJitAbi->'$(IntermediateOutputPath)\%(AndroidRID)-clr-Debug\CMakeCache.txt')" /> + <_BuildAndroidRuntimesInputs Include="@(AndroidSupportedTargetJitAbi->'$(IntermediateOutputPath)\%(AndroidRID)-clr-Release\CMakeCache.txt')" /> + <_BuildAndroidRuntimesInputs Include="@(_MonoDroidSources)" /> + <_BuildAndroidRuntimesInputs Include="..\..\build-tools\scripts\Ndk.targets" /> + <_BuildAndroidRuntimesOutputs Include="@(AndroidSupportedTargetJitAbi->'$(OutputPath)\%(AndroidRID)\libnet-android.debug.so')" /> + <_BuildAndroidRuntimesOutputs Include="@(AndroidSupportedTargetJitAbi->'$(OutputPath)\%(AndroidRID)\libnet-android.release.so')" /> + <_BuildAndroidRuntimesOutputs Include="@(AndroidSupportedTargetJitAbi->'$(OutputPath)\%(AndroidRID)\Debug\libxamarin-app-clr.so')" /> + <_BuildAndroidRuntimesOutputs Include="@(AndroidSupportedTargetJitAbi->'$(OutputPath)\%(AndroidRID)\Release\libxamarin-app-clr.so')" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_ArmRuntimePackFiles Include="$(OutputPath)\android-arm\*.*" /> + <_Arm64RuntimePackFiles Include="$(OutputPath)\android-arm64\*.*" /> + <_x86RuntimePackFiles Include="$(OutputPath)\android-x86\*.*" /> + <_x64RuntimePackFiles Include="$(OutputPath)\android-x64\*.*" /> + + + + + + + + diff --git a/src/native-clr/runtime-base/CMakeLists.txt b/src/native-clr/runtime-base/CMakeLists.txt new file mode 100644 index 00000000000..7e42498b5e4 --- /dev/null +++ b/src/native-clr/runtime-base/CMakeLists.txt @@ -0,0 +1,55 @@ +set(LIB_NAME runtime-base-clr) +set(LIB_ALIAS xa::runtime-base-clr) + +set(XA_RUNTIME_BASE_SOURCES + android-system.cc +) +add_clang_check_sources("${XA_RUNTIME_BASE_SOURCES}") + +list(APPEND POTENTIAL_LOCAL_COMPILER_ARGS + -ffunction-sections + -fdata-sections +) + +xa_check_c_args(RUNTIME_BASE_CXX_ARGS "${POTENTIAL_LOCAL_COMPILER_ARGS}") + +add_library( + ${LIB_NAME} + STATIC + ${XA_RUNTIME_BASE_SOURCES} +) + +add_library(${LIB_ALIAS} ALIAS ${LIB_NAME}) + +set_static_library_suffix(${LIB_NAME}) + +target_compile_options( + ${LIB_NAME} + PRIVATE + ${XA_COMMON_CXX_ARGS} + ${RUNTIME_BASE_CXX_ARGS} +) + +target_include_directories( + ${LIB_NAME} + SYSTEM PRIVATE + ${SYSROOT_CXX_INCLUDE_DIR} +) + +target_link_libraries( + ${LIB_NAME} + PRIVATE + xa::shared-clr + xa::xamarin-app-clr +) + +if(DEBUG_BUILD) + set_target_properties( + ${LIB_NAME} + PROPERTIES + ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" + ) +endif() + +xa_add_compile_definitions(${LIB_NAME}) +xa_add_include_directories(${LIB_NAME}) diff --git a/src/native-clr/runtime-base/android-system.cc b/src/native-clr/runtime-base/android-system.cc new file mode 100644 index 00000000000..fcf6a82b640 --- /dev/null +++ b/src/native-clr/runtime-base/android-system.cc @@ -0,0 +1,134 @@ +#include + +#include +#include +#include +#include + +using namespace xamarin::android; + +auto +AndroidSystem::lookup_system_property (std::string_view const& name, size_t &value_len) noexcept -> const char* +{ + value_len = 0; +#if defined (DEBUG) + BundledProperty *p = lookup_system_property (name); + if (p != nullptr) { + value_len = p->value_len; + return p->name; + } +#endif // DEBUG || !ANDROID + + if (application_config.system_property_count == 0) { + return nullptr; + } + + if (application_config.system_property_count % 2 != 0) { + log_warn (LOG_DEFAULT, "Corrupted environment variable array: does not contain an even number of entries ({})", application_config.system_property_count); + return nullptr; + } + + const char *prop_name; + const char *prop_value; + for (size_t i = 0uz; i < application_config.system_property_count; i += 2uz) { + prop_name = app_system_properties[i]; + if (prop_name == nullptr || *prop_name == '\0') { + continue; + } + + if (strcmp (prop_name, name.data ()) == 0) { + prop_value = app_system_properties [i + 1uz]; + if (prop_value == nullptr || *prop_value == '\0') { + value_len = 0uz; + return ""; + } + + value_len = strlen (prop_value); + return prop_value; + } + } + + return nullptr; +} + +auto +AndroidSystem::monodroid__system_property_get (std::string_view const& name, char *sp_value, size_t sp_value_len) noexcept -> int +{ + if (name.empty () || sp_value == nullptr) { + return -1; + } + + char *buf = nullptr; + if (sp_value_len < Constants::PROPERTY_VALUE_BUFFER_LEN) { + size_t alloc_size = Helpers::add_with_overflow_check (Constants::PROPERTY_VALUE_BUFFER_LEN, 1uz); + log_warn (LOG_DEFAULT, "Buffer to store system property may be too small, will copy only {} bytes", sp_value_len); + buf = new char [alloc_size]; + } + + int len = __system_property_get (name.data (), buf ? buf : sp_value); + if (buf != nullptr) { + strncpy (sp_value, buf, sp_value_len); + sp_value [sp_value_len] = '\0'; + delete[] buf; + } + + return len; +} + +auto AndroidSystem::monodroid_get_system_property (std::string_view const& name, dynamic_local_string &value) noexcept -> int +{ + int len = monodroid__system_property_get (name, value.get (), value.size ()); + if (len > 0) { + // Clumsy, but if we want direct writes to be fast, this is the price we pay + value.set_length_after_direct_write (static_cast(len)); + return len; + } + + size_t plen; + const char *v = lookup_system_property (name, plen); + if (v == nullptr) + return len; + + value.assign (v, plen); + return Helpers::add_with_overflow_check (plen, 0); +} + +auto +AndroidSystem::get_max_gref_count_from_system () noexcept -> long +{ + long max; + + if (running_in_emulator) { + max = 2000; + } else { + max = 51200; + } + + dynamic_local_string override; + if (monodroid_get_system_property (Constants::DEBUG_MONO_MAX_GREFC, override) > 0) { + char *e; + max = strtol (override.get (), &e, 10); + switch (*e) { + case 'k': + e++; + max *= 1000; + break; + case 'm': + e++; + max *= 1000000; + break; + } + + if (max < 0) { + max = std::numeric_limits::max (); + } + + if (*e) { + log_warn (LOG_GC, "Unsupported '{}' value '{}'.", Constants::DEBUG_MONO_MAX_GREFC.data (), override.get ()); + } + + log_warn (LOG_GC, "Overriding max JNI Global Reference count to {}", max); + } + + return max; +} diff --git a/src/native-clr/shared/CMakeLists.txt b/src/native-clr/shared/CMakeLists.txt new file mode 100644 index 00000000000..9c176e6ac65 --- /dev/null +++ b/src/native-clr/shared/CMakeLists.txt @@ -0,0 +1,59 @@ +set(LIB_NAME xa-shared-bits-clr) +set(LIB_ALIAS xa::shared-clr) + +set(XA_SHARED_SOURCES + helpers.cc + log_functions.cc +) +add_clang_check_sources("${XA_SHARED_SOURCES};") + +add_library( + ${LIB_NAME} + STATIC + ${XA_SHARED_SOURCES} + ${XA_SHARED_CXX_ABI_SOURCES} +) +add_library(${LIB_ALIAS} ALIAS ${LIB_NAME}) + +set_static_library_suffix(${LIB_NAME}) + +macro(lib_target_options TARGET_NAME) + target_include_directories( + ${TARGET_NAME} + PUBLIC + "$" + "$" + ) + + target_link_libraries( + ${TARGET_NAME} + PUBLIC + xa::java-interop-clr + -llog + ) + + target_include_directories( + ${TARGET_NAME} + SYSTEM PRIVATE + ${SYSROOT_CXX_INCLUDE_DIR} + ) + + target_compile_options( + ${TARGET_NAME} + PRIVATE + ${XA_COMMON_CXX_ARGS} + ) + + if(DEBUG_BUILD) + set_target_properties( + ${TARGET_NAME} + PROPERTIES + ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" + ) + endif() + + xa_add_compile_definitions(${TARGET_NAME}) + xa_add_include_directories(${TARGET_NAME}) +endmacro() + +lib_target_options(${LIB_NAME}) diff --git a/src/native-clr/shared/helpers.cc b/src/native-clr/shared/helpers.cc new file mode 100644 index 00000000000..59697e7d257 --- /dev/null +++ b/src/native-clr/shared/helpers.cc @@ -0,0 +1,46 @@ +#include +#include +#include + +#include +#include + +using namespace xamarin::android; + +[[noreturn]] void +Helpers::abort_application (LogCategories category, const char *message, bool log_location, std::source_location sloc) noexcept +{ + // Log it, but also... + log_fatal (category, "{}", message); + + // ...let android include it in the tombstone, debuggerd output, stack trace etc + android_set_abort_message (message); + + if (log_location) { + // We don't want to log the full path, just the file name. libc++ uses full file path here. + const char *file_name = sloc.file_name (); + const char *last_path_sep = strrchr (file_name, '/'); + + if (last_path_sep == nullptr) [[unlikely]] { + // In case we were built on Windows + last_path_sep = strrchr (file_name, '\\'); + } + + if (last_path_sep != nullptr) [[likely]] { + last_path_sep++; + if (*last_path_sep != '\0') [[unlikely]] { + file_name = last_path_sep; + } + } + + log_fatal ( + category, + "Abort at {}:{}:{} ('%s')", + file_name, + sloc.line (), + sloc.column (), + sloc.function_name () + ); + } + std::abort (); +} diff --git a/src/native-clr/shared/log_functions.cc b/src/native-clr/shared/log_functions.cc new file mode 100644 index 00000000000..acd5e705c06 --- /dev/null +++ b/src/native-clr/shared/log_functions.cc @@ -0,0 +1,131 @@ +#include +#include +#include +#include + +#include + +#include "java-interop-logger.h" +#include +#include + +using namespace xamarin::android; + +namespace { + // Must match the same ordering as LogCategories + constexpr std::array log_names = { + Constants::LOG_CATEGORY_NAME_NONE, + Constants::LOG_CATEGORY_NAME_MONODROID, + Constants::LOG_CATEGORY_NAME_MONODROID_ASSEMBLY, + Constants::LOG_CATEGORY_NAME_MONODROID_DEBUG, + Constants::LOG_CATEGORY_NAME_MONODROID_GC, + Constants::LOG_CATEGORY_NAME_MONODROID_GREF, + Constants::LOG_CATEGORY_NAME_MONODROID_LREF, + Constants::LOG_CATEGORY_NAME_MONODROID_TIMING, + Constants::LOG_CATEGORY_NAME_MONODROID_BUNDLE, + Constants::LOG_CATEGORY_NAME_MONODROID_NETWORK, + Constants::LOG_CATEGORY_NAME_MONODROID_NETLINK, + Constants::LOG_CATEGORY_NAME_ERROR, + }; + + [[gnu::always_inline]] + constexpr auto category_name (int value) noexcept -> const char* + { + if (value == 0) { + return log_names[0].data (); + } + + // ffs(value) returns index of lowest bit set in `value` + return log_names [static_cast(ffs (value))].data (); + } + + constexpr android_LogPriority DEFAULT_PRIORITY = ANDROID_LOG_INFO; + + // relies on the fact that the LogLevel enum has sequential values + constexpr android_LogPriority loglevel_map[] = { + DEFAULT_PRIORITY, // Unknown + DEFAULT_PRIORITY, // Default + ANDROID_LOG_VERBOSE, // Verbose + ANDROID_LOG_DEBUG, // Debug + ANDROID_LOG_INFO, // Info + ANDROID_LOG_WARN, // Warn + ANDROID_LOG_ERROR, // Error + ANDROID_LOG_FATAL, // Fatal + ANDROID_LOG_SILENT, // Silent + }; + + constexpr size_t loglevel_map_max_index = (sizeof(loglevel_map) / sizeof(android_LogPriority)) - 1; +} + +unsigned int log_categories = LOG_NONE; + +#undef DO_LOG +#define DO_LOG(_level_,_category_,_format_,_args_) \ + va_start ((_args_), (_format_)); \ + __android_log_vprint ((_level_), category_name((_category_)), (_format_), (_args_)); \ + va_end ((_args_)); + +void +log_error (LogCategories category, const char *format, ...) +{ + va_list args; + + DO_LOG (ANDROID_LOG_ERROR, category, format, args); +} + +void +log_fatal (LogCategories category, const char *format, ...) +{ + va_list args; + + DO_LOG (ANDROID_LOG_FATAL, category, format, args); +} + +void +log_info_nocheck (LogCategories category, const char *format, ...) +{ + va_list args; + + if ((log_categories & category) != category) { + return; + } + + DO_LOG (ANDROID_LOG_INFO, category, format, args); +} + +void +log_warn (LogCategories category, const char *format, ...) +{ + va_list args; + + DO_LOG (ANDROID_LOG_WARN, category, format, args); +} + +void +log_debug_nocheck (LogCategories category, const char *format, ...) +{ + va_list args; + + if ((log_categories & category) != category) { + return; + } + + DO_LOG (ANDROID_LOG_DEBUG, category, format, args); +} + +namespace xamarin::android { + void + log_write (LogCategories category, LogLevel level, const char *message) noexcept + { + size_t map_index = static_cast(level); + android_LogPriority priority; + + if (map_index > loglevel_map_max_index) { + priority = DEFAULT_PRIORITY; + } else { + priority = loglevel_map[map_index]; + } + + __android_log_write (priority, category_name (category), message); + } +} diff --git a/src/native-clr/startup/CMakeLists.txt b/src/native-clr/startup/CMakeLists.txt new file mode 100644 index 00000000000..773eda8cf3a --- /dev/null +++ b/src/native-clr/startup/CMakeLists.txt @@ -0,0 +1,52 @@ +set(LIB_NAME xamarin-startup-clr) +set(LIB_ALIAS xa::xamarin-startup-clr) + +set(XAMARIN_STARTUP_SOURCES + zip.cc +) +add_clang_check_sources("${XAMARIN_STARTUP_SOURCES}") + +add_library( + ${LIB_NAME} + SHARED + ${XAMARIN_STARTUP_SOURCES} +) + +add_library(${LIB_ALIAS} ALIAS ${LIB_NAME}) + +target_include_directories( + ${LIB_NAME} + SYSTEM PRIVATE + ${SYSROOT_CXX_INCLUDE_DIR} +) + +target_compile_options( + ${LIB_NAME} + PRIVATE + ${XA_COMMON_CXX_ARGS} + # Avoid the 'warning: dynamic exception specifications are deprecated' warning from libc++ headers + -Wno-deprecated-dynamic-exception-spec +) + +target_link_directories( + ${LIB_NAME} + PRIVATE + ${NET_RUNTIME_DIR}/native-clr +) + +target_link_options( + ${LIB_NAME} + PRIVATE + ${XA_COMMON_CXX_LINKER_ARGS} + ${XA_CXX_DSO_LINKER_ARGS} +) + +target_link_libraries( + ${LIB_NAME} + PRIVATE + xa::shared-clr + -llog +) + +xa_add_compile_definitions(${LIB_NAME}) +xa_add_include_directories(${LIB_NAME}) diff --git a/src/native-clr/startup/zip.cc b/src/native-clr/startup/zip.cc new file mode 100644 index 00000000000..cef57b26618 --- /dev/null +++ b/src/native-clr/startup/zip.cc @@ -0,0 +1,3 @@ +#include + +using namespace xamarin::android; diff --git a/src/native-clr/xamarin-app-stub/CMakeLists.txt b/src/native-clr/xamarin-app-stub/CMakeLists.txt new file mode 100644 index 00000000000..d23328f9ce7 --- /dev/null +++ b/src/native-clr/xamarin-app-stub/CMakeLists.txt @@ -0,0 +1,54 @@ +set(LIB_NAME xamarin-app-clr) +set(LIB_ALIAS xa::xamarin-app-clr) + +set(XAMARIN_APP_SOURCES + application_dso_stub.cc +) + +add_library( + ${LIB_NAME} + SHARED + ${XAMARIN_APP_SOURCES} +) + +add_library(${LIB_ALIAS} ALIAS ${LIB_NAME}) + +target_include_directories( + ${LIB_NAME} + SYSTEM PRIVATE + ${SYSROOT_CXX_INCLUDE_DIR} +) + +target_compile_options( + ${LIB_NAME} + PRIVATE + ${XA_COMMON_CXX_ARGS} +) + +target_link_options( + ${LIB_NAME} + PRIVATE + ${XA_COMMON_CXX_LINKER_ARGS} + ${XA_CXX_DSO_LINKER_ARGS} +) + +target_link_libraries( + ${LIB_NAME} + PRIVATE + ${SHARED_LIB_NAME} +) + +if(DEBUG_BUILD) + set(LIB_SUBDIR "Debug") +else() + set(LIB_SUBDIR "Release") +endif() + +set_target_properties( + ${LIB_NAME} + PROPERTIES + LIBRARY_OUTPUT_DIRECTORY "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${LIB_SUBDIR}" +) + +xa_add_compile_definitions(${LIB_NAME}) +xa_add_include_directories(${LIB_NAME}) diff --git a/src/native-clr/xamarin-app-stub/application_dso_stub.cc b/src/native-clr/xamarin-app-stub/application_dso_stub.cc new file mode 100644 index 00000000000..e9a8bf35235 --- /dev/null +++ b/src/native-clr/xamarin-app-stub/application_dso_stub.cc @@ -0,0 +1,297 @@ +#include +#include + +#include +#include + +// This file MUST have "valid" values everywhere - the DSO it is compiled into is loaded by the +// designer on desktop. +const uint64_t format_tag = FORMAT_TAG; + +#if defined (DEBUG) +static TypeMapEntry java_to_managed[] = {}; + +static TypeMapEntry managed_to_java[] = {}; + +// MUST match src/Xamarin.Android.Build.Tasks/Utilities/TypeMappingDebugNativeAssemblyGenerator.cs +const TypeMap type_map = { + 0, + nullptr, + nullptr, + java_to_managed, + managed_to_java +}; +#else +const uint32_t map_module_count = 0; +const uint32_t java_type_count = 0; +const char* const java_type_names[] = {}; + +TypeMapModule map_modules[] = {}; +const TypeMapJava map_java[] = {}; +const xamarin::android::hash_t map_java_hashes[] = {}; +#endif + +CompressedAssemblies compressed_assemblies = { + .count = 0, + .descriptors = nullptr, +}; + +// +// Config settings below **must** be valid for Desktop builds as the default `libxamarin-app.{dll,dylib,so}` is used by +// the Designer +// +constexpr char android_package_name[] = "com.xamarin.test"; +const ApplicationConfig application_config = { + .uses_assembly_preload = false, + .jni_add_native_method_registration_attribute_present = false, + .have_runtime_config_blob = false, + .marshal_methods_enabled = false, + .ignore_split_configs = false, + .package_naming_policy = 0, + .environment_variable_count = 0, + .system_property_count = 0, + .number_of_assemblies_in_apk = 2, + .bundled_assembly_name_width = 0, + .number_of_dso_cache_entries = 2, + .number_of_shared_libraries = 2, + .android_runtime_jnienv_class_token = 1, + .jnienv_initialize_method_token = 2, + .jnienv_registerjninatives_method_token = 3, + .jni_remapping_replacement_type_count = 2, + .jni_remapping_replacement_method_index_entry_count = 2, + .android_package_name = android_package_name, +}; + +const char* const app_environment_variables[] = {}; +const char* const app_system_properties[] = {}; + +static constexpr size_t AssemblyNameWidth = 128uz; + +static char first_assembly_name[AssemblyNameWidth]; +static char second_assembly_name[AssemblyNameWidth]; + +XamarinAndroidBundledAssembly bundled_assemblies[] = { + { + .file_fd = -1, + .file_name = nullptr, + .data_offset = 0, + .data_size = 0, + .data = nullptr, + .name_length = 0, + .name = first_assembly_name, + }, + + { + .file_fd = -1, + .file_name = nullptr, + .data_offset = 0, + .data_size = 0, + .data = nullptr, + .name_length = 0, + .name = second_assembly_name, + }, +}; + +AssemblyStoreSingleAssemblyRuntimeData assembly_store_bundled_assemblies[] = { + { + .image_data = nullptr, + .debug_info_data = nullptr, + .config_data = nullptr, + .descriptor = nullptr, + }, + + { + .image_data = nullptr, + .debug_info_data = nullptr, + .config_data = nullptr, + .descriptor = nullptr, + }, +}; + +AssemblyStoreRuntimeData assembly_store = { + .data_start = nullptr, + .assembly_count = 0, + .index_entry_count = 0, + .assemblies = nullptr, +}; + +constexpr char fake_dso_name[] = "libaot-Some.Assembly.dll.so"; +constexpr char fake_dso_name2[] = "libaot-Another.Assembly.dll.so"; + +DSOCacheEntry dso_cache[] = { + { + .hash = xamarin::android::xxhash::hash (fake_dso_name, sizeof(fake_dso_name) - 1), + .real_name_hash = xamarin::android::xxhash::hash (fake_dso_name, sizeof(fake_dso_name) - 1), + .ignore = true, + .name = fake_dso_name, + .handle = nullptr, + }, + + { + .hash = xamarin::android::xxhash::hash (fake_dso_name2, sizeof(fake_dso_name2) - 1), + .real_name_hash = xamarin::android::xxhash::hash (fake_dso_name2, sizeof(fake_dso_name2) - 1), + .ignore = true, + .name = fake_dso_name2, + .handle = nullptr, + }, +}; + +DSOCacheEntry aot_dso_cache[] = { + { + .hash = xamarin::android::xxhash::hash (fake_dso_name, sizeof(fake_dso_name) - 1), + .real_name_hash = xamarin::android::xxhash::hash (fake_dso_name, sizeof(fake_dso_name) - 1), + .ignore = true, + .name = fake_dso_name, + .handle = nullptr, + }, + + { + .hash = xamarin::android::xxhash::hash (fake_dso_name2, sizeof(fake_dso_name2) - 1), + .real_name_hash = xamarin::android::xxhash::hash (fake_dso_name2, sizeof(fake_dso_name2) - 1), + .ignore = true, + .name = fake_dso_name2, + .handle = nullptr, + }, +}; + +DSOApkEntry dso_apk_entries[2] {}; + +// +// Support for marshal methods +// +#if defined (RELEASE) +void* assembly_image_cache[] = { + nullptr, + nullptr, + +}; + +// Each element contains an index into `assembly_image_cache` +const uint32_t assembly_image_cache_indices[] = { + 0, + 1, + 1, + 1, +}; + +// hashes point to indices in `assembly_image_cache_indices` +const xamarin::android::hash_t assembly_image_cache_hashes[] = { + 0, + 1, + 2, + 3, +}; + +uint32_t marshal_methods_number_of_classes = 2; +MarshalMethodsManagedClass marshal_methods_class_cache[] = { + { + .token = 0, + .klass = nullptr, + }, + + { + .token = 0, + .klass = nullptr, + }, +}; + +const char* const mm_class_names[2] = { + "one", + "two", +}; + +const MarshalMethodName mm_method_names[] = { + { + .id = 1, + .name = "one", + }, + + { + .id = 2, + .name = "two", + }, +}; + +void xamarin_app_init ([[maybe_unused]] JNIEnv *env, [[maybe_unused]] get_function_pointer_fn fn) noexcept +{ + // Dummy +} +#endif // def RELEASE + +static const JniRemappingIndexMethodEntry some_java_type_one_methods[] = { + { + .name = { + .length = 15, + .str = "old_method_name", + }, + + .signature = { + .length = 0, + .str = nullptr, + }, + + .replacement = { + .target_type = "some/java/target_type_one", + .target_name = "new_method_name", + .is_static = false, + } + }, +}; + +static const JniRemappingIndexMethodEntry some_java_type_two_methods[] = { + { + .name = { + .length = 15, + .str = "old_method_name", + }, + + .signature = { + .length = 28, + .str = "(IILandroid/content/Intent;)", + }, + + .replacement = { + .target_type = "some/java/target_type_two", + .target_name = "new_method_name", + .is_static = true, + } + }, +}; + +const JniRemappingIndexTypeEntry jni_remapping_method_replacement_index[] = { + { + .name = { + .length = 18, + .str = "some/java/type_one", + }, + .method_count = 1, + .methods = some_java_type_one_methods, + }, + + { + .name = { + .length = 18, + .str = "some/java/type_two", + }, + .method_count = 1, + .methods = some_java_type_two_methods, + }, +}; + +const JniRemappingTypeReplacementEntry jni_remapping_type_replacements[] = { + { + .name = { + .length = 14, + .str = "some/java/type", + }, + .replacement = "another/java/type", + }, + + { + .name = { + .length = 20, + .str = "some/other/java/type", + }, + .replacement = "another/replacement/java/type", + }, +}; From 8d3c5bae5890954cb02755e2c9361d90c416bb2c Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Tue, 3 Dec 2024 13:38:51 +0100 Subject: [PATCH 49/54] Address feedback --- src/native/shared/cpp-util.hh | 63 +++++++++++++++++++++++++++++++++-- 1 file changed, 61 insertions(+), 2 deletions(-) diff --git a/src/native/shared/cpp-util.hh b/src/native/shared/cpp-util.hh index 3951b81f474..6e77d98f5f7 100644 --- a/src/native/shared/cpp-util.hh +++ b/src/native/shared/cpp-util.hh @@ -7,9 +7,12 @@ #include #include #include +#include #include +#include #include #include +#include #include #include @@ -30,6 +33,50 @@ namespace xamarin::android::detail { va_end (ap); return ret == -1 ? "Out of memory" : message; } + + [[gnu::always_inline]] + static inline std::string get_function_name (const char *signature) + { + using std::operator""sv; + + std::string_view sig { signature }; + if (sig.length () == 0) { + return ""; + } + + auto splitSignature = sig | std::views::split ("::"sv) | std::ranges::to> (); + + std::string ret; + if (splitSignature.size () > 1) { + ret.append (splitSignature [splitSignature.size () - 2]); + ret.append ("::"sv); + } + std::string_view func_name { splitSignature[splitSignature.size () - 1] }; + std::string_view::size_type args_pos = func_name.find ('('); + std::string_view::size_type name_start_pos = func_name.find (' '); + + if (name_start_pos == std::string_view::npos) { + name_start_pos = 0; + } else { + name_start_pos++; // point to after the space which separates return type from name + if (name_start_pos >= func_name.length ()) [[unlikely]] { + name_start_pos = 0; + } + } + + if (args_pos == std::string_view::npos) { + ret.append (func_name.substr (name_start_pos)); + } else { + // If there's a snafu with positions, start from 0 + if (name_start_pos >= args_pos || name_start_pos > func_name.length ()) [[unlikely]] { + name_start_pos = 0; + } + + ret.append (func_name.substr (name_start_pos, args_pos - name_start_pos)); + } + + return ret; + } } template F> @@ -63,7 +110,13 @@ abort_if_invalid_pointer_argument (T *ptr, const char *ptr_name, std::source_loc { abort_unless ( ptr != nullptr, - [&ptr_name] { return xamarin::android::detail::_format_message ("Parameter '%s' must be a valid pointer", ptr_name); }, + [&ptr_name, &sloc] { + return xamarin::android::detail::_format_message ( + "%s: parameter '%s' must be a valid pointer", + xamarin::android::detail::get_function_name (sloc.function_name ()).c_str (), + ptr_name + ); + }, sloc ); } @@ -74,7 +127,13 @@ abort_if_negative_integer_argument (int arg, const char *arg_name, std::source_l { abort_unless ( arg > 0, - [&arg_name] { return xamarin::android::detail::_format_message ("Parameter '%s' must be a valid pointer", arg_name); }, + [&arg_name, &sloc] { + return xamarin::android::detail::_format_message ( + "%s: parameter '%s' must be a valid pointer", + xamarin::android::detail::get_function_name (sloc.function_name ()).c_str (), + arg_name + ); + }, sloc ); } From 20fc6e7cfebd02d82639bac9920317e7dee900fc Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Tue, 3 Dec 2024 19:47:42 +0100 Subject: [PATCH 50/54] First packaging steps + Java startup code changes --- .../Microsoft.Android.Runtime.proj | 6 +- .../installers/create-installers.targets | 4 + ...oft.Android.Sdk.AssemblyResolution.targets | 4 + .../Tasks/ProcessNativeLibraries.cs | 15 ++- .../Xamarin.Android.Common.targets | 9 +- src/java-runtime/java-runtime.targets | 23 +++- .../java/mono/android/MonoPackageManager.java | 2 +- .../mono/android/clr/MonoPackageManager.java | 123 ++++++++++++++++++ src/native-clr/host/host-jni.cc | 8 +- src/native-clr/include/host/host-jni.hh | 4 +- src/native-clr/java-interop/CMakeLists.txt | 2 +- src/native-clr/libnet-android.map.txt | 2 +- src/native-clr/runtime-base/CMakeLists.txt | 10 +- src/native-clr/runtime-base/android-system.cc | 14 +- src/native-clr/shared/CMakeLists.txt | 11 +- src/native-clr/startup/CMakeLists.txt | 5 +- 16 files changed, 191 insertions(+), 51 deletions(-) create mode 100644 src/java-runtime/java/mono/android/clr/MonoPackageManager.java diff --git a/build-tools/create-packs/Microsoft.Android.Runtime.proj b/build-tools/create-packs/Microsoft.Android.Runtime.proj index 99969ba29f6..43b89066856 100644 --- a/build-tools/create-packs/Microsoft.Android.Runtime.proj +++ b/build-tools/create-packs/Microsoft.Android.Runtime.proj @@ -39,8 +39,10 @@ projects that use the Microsoft.Android framework in .NET 6+. <_AndroidRuntimePackAssemblies Include="$(_MonoAndroidNETDefaultOutDir)Mono.Android.Runtime.dll" /> <_AndroidRuntimePackAssemblies Include="$(_MonoAndroidNETOutputRoot)$(AndroidLatestStableApiLevel)\Mono.Android.Export.dll" /> - <_AndroidRuntimePackAssets Include="$(MicrosoftAndroidSdkOutDir)lib\$(AndroidRID)\libmono-android.debug.so" /> - <_AndroidRuntimePackAssets Include="$(MicrosoftAndroidSdkOutDir)lib\$(AndroidRID)\libmono-android.release.so" /> + <_AndroidRuntimePackAssets Condition=" Exists('$(MicrosoftAndroidSdkOutDir)lib\$(AndroidRID)\libmono-android.debug.so') " Include="$(MicrosoftAndroidSdkOutDir)lib\$(AndroidRID)\libmono-android.debug.so" /> + <_AndroidRuntimePackAssets Condition=" Exists('$(MicrosoftAndroidSdkOutDir)lib\$(AndroidRID)\libmono-android.release.so') " Include="$(MicrosoftAndroidSdkOutDir)lib\$(AndroidRID)\libmono-android.release.so" /> + <_AndroidRuntimePackAssets Condition=" Exists('$(MicrosoftAndroidSdkOutDir)lib\$(AndroidRID)\libnet-android.debug.so') " Include="$(MicrosoftAndroidSdkOutDir)lib\$(AndroidRID)\libnet-android.debug.so" /> + <_AndroidRuntimePackAssets Condition=" Exists('$(MicrosoftAndroidSdkOutDir)lib\$(AndroidRID)\libnet-android.release.so') " Include="$(MicrosoftAndroidSdkOutDir)lib\$(AndroidRID)\libnet-android.release.so" /> <_AndroidRuntimePackAssets Include="$(MicrosoftAndroidSdkOutDir)lib\$(AndroidRID)\libxamarin-debug-app-helper.so" /> <_AndroidRuntimePackAssets Include="$(MicrosoftAndroidSdkOutDir)lib\$(AndroidRID)\libxamarin-native-tracing.so" /> <_AndroidRuntimePackAssets Include="$(MicrosoftAndroidSdkOutDir)lib\$(AndroidRID)\libunwind_xamarin.a" /> diff --git a/build-tools/installers/create-installers.targets b/build-tools/installers/create-installers.targets index 0a63d3bfcf0..272ff354bd5 100644 --- a/build-tools/installers/create-installers.targets +++ b/build-tools/installers/create-installers.targets @@ -137,6 +137,10 @@ <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)java_runtime_fastdev_net6.jar" ExcludeFromLegacy="true" /> <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)java_runtime_net6.dex" ExcludeFromLegacy="true" /> <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)java_runtime_fastdev_net6.dex" ExcludeFromLegacy="true" /> + <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)java_runtime_clr.jar" ExcludeFromLegacy="true" /> + <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)java_runtime_fastdev_clr.jar" ExcludeFromLegacy="true" /> + <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)java_runtime_clr.dex" ExcludeFromLegacy="true" /> + <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)java_runtime_fastdev_clr.dex" ExcludeFromLegacy="true" /> <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)manifestmerger.jar" /> <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)proguard-android.txt" /> <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)protobuf-net.dll" /> diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyResolution.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyResolution.targets index 10382ed3cc4..3b9038a84d5 100644 --- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyResolution.targets +++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyResolution.targets @@ -232,6 +232,10 @@ _ResolveAssemblies MSBuild target. <_ExcludedNativeLibraries Condition=" '$(_AndroidIncludeSystemGlobalizationNative)' != 'true' " Include="libSystem.Globalization.Native" /> <_ExcludedNativeLibraries Condition=" '$(_AndroidEnableNativeStackTracing)' != 'true' " Include="libxamarin-native-tracing" /> + <_ExcludedNativeLibraries Condition=" '$(_AndroidUseCLR)' != 'True' " Include="libnet-android.debug" /> + <_ExcludedNativeLibraries Condition=" '$(_AndroidUseCLR)' != 'True' " Include="libnet-android.release" /> + <_ExcludedNativeLibraries Condition=" '$(_AndroidUseCLR)' == 'True' " Include="libmono-android.debug" /> + <_ExcludedNativeLibraries Condition=" '$(_AndroidUseCLR)' == 'True' " Include="libmono-android.release" /> - + <_RuntimeJar>$(MSBuildThisFileDirectory)\java_runtime_net6.jar <_RuntimeDex>$(MSBuildThisFileDirectory)\java_runtime_net6.dex + + + <_RuntimeJar>$(MSBuildThisFileDirectory)\java_runtime_clr.jar + <_RuntimeDex>$(MSBuildThisFileDirectory)\java_runtime_clr.dex + diff --git a/src/java-runtime/java-runtime.targets b/src/java-runtime/java-runtime.targets index 38eb73117d9..2cdec89f63c 100644 --- a/src/java-runtime/java-runtime.targets +++ b/src/java-runtime/java-runtime.targets @@ -7,14 +7,14 @@ $(OutputPath)java_runtime.dex $(IntermediateOutputPath)release $(IntermediateOutputPath)release.txt - ..\..\src-ThirdParty\bazel\java\mono\android\debug\MultiDexLoader.java;java\mono\android\debug\BuildConfig.java;java\mono\android\debug-net6\BuildConfig.java;java\mono\android\release-net6\BuildConfig.java + ..\..\src-ThirdParty\bazel\java\mono\android\debug\MultiDexLoader.java;java\mono\android\debug\BuildConfig.java;java\mono\android\debug-net6\BuildConfig.java;java\mono\android\release-net6\BuildConfig.java;java\mono\android\clr\MonoPackageManager.java <_RuntimeOutput Include="$(OutputPath)java_runtime_fastdev.jar"> $(OutputPath)java_runtime_fastdev.jar $(OutputPath)java_runtime_fastdev.dex $(IntermediateOutputPath)fastdev $(IntermediateOutputPath)fastdev.txt - ..\..\src-ThirdParty\bazel\java\mono\android\release\MultiDexLoader.java;java\mono\android\release\BuildConfig.java;java\mono\android\release-net6\BuildConfig.java;java\mono\android\debug-net6\BuildConfig.java + ..\..\src-ThirdParty\bazel\java\mono\android\release\MultiDexLoader.java;java\mono\android\release\BuildConfig.java;java\mono\android\release-net6\BuildConfig.java;java\mono\android\debug-net6\BuildConfig.java;java\mono\android\clr\MonoPackageManager.java <_RuntimeOutput Include="$(OutputPath)java_runtime_net6.jar"> @@ -22,14 +22,29 @@ $(OutputPath)java_runtime_net6.dex $(IntermediateOutputPath)release-net6 $(IntermediateOutputPath)release-net6.txt - ..\..\src-ThirdParty\bazel\java\mono\android\debug\MultiDexLoader.java;java\mono\android\debug-net6\BuildConfig.java;java\mono\android\debug\BuildConfig.java;java\mono\android\release\BuildConfig.java + ..\..\src-ThirdParty\bazel\java\mono\android\debug\MultiDexLoader.java;java\mono\android\debug-net6\BuildConfig.java;java\mono\android\debug\BuildConfig.java;java\mono\android\release\BuildConfig.java;java\mono\android\clr\MonoPackageManager.java <_RuntimeOutput Include="$(OutputPath)java_runtime_fastdev_net6.jar"> $(OutputPath)java_runtime_fastdev_net6.jar $(OutputPath)java_runtime_fastdev_net6.dex $(IntermediateOutputPath)fastdev-net6 $(IntermediateOutputPath)fastdev-net6.txt - ..\..\src-ThirdParty\bazel\java\mono\android\release\MultiDexLoader.java;java\mono\android\release-net6\BuildConfig.java;java\mono\android\release\BuildConfig.java;java\mono\android\debug\BuildConfig.java + ..\..\src-ThirdParty\bazel\java\mono\android\release\MultiDexLoader.java;java\mono\android\release-net6\BuildConfig.java;java\mono\android\release\BuildConfig.java;java\mono\android\debug\BuildConfig.java;java\mono\android\clr\MonoPackageManager.java + + + <_RuntimeOutput Include="$(OutputPath)java_runtime_clr.jar"> + $(OutputPath)java_runtime_clr.jar + $(OutputPath)java_runtime_clr.dex + $(IntermediateOutputPath)release-clr + $(IntermediateOutputPath)release-clr.txt + ..\..\src-ThirdParty\bazel\java\mono\android\debug\MultiDexLoader.java;java\mono\android\debug-net6\BuildConfig.java;java\mono\android\debug\BuildConfig.java;java\mono\android\release\BuildConfig.java;java\mono\android\MonoPackageManager.java + + <_RuntimeOutput Include="$(OutputPath)java_runtime_fastdev_clr.jar"> + $(OutputPath)java_runtime_fastdev_clr.jar + $(OutputPath)java_runtime_fastdev_clr.dex + $(IntermediateOutputPath)fastdev-clr + $(IntermediateOutputPath)fastdev-clr.txt + ..\..\src-ThirdParty\bazel\java\mono\android\release\MultiDexLoader.java;java\mono\android\release-net6\BuildConfig.java;java\mono\android\release\BuildConfig.java;java\mono\android\debug\BuildConfig.java;java\mono\android\MonoPackageManager.java diff --git a/src/java-runtime/java/mono/android/MonoPackageManager.java b/src/java-runtime/java/mono/android/MonoPackageManager.java index fa6ed7be7fc..cd8de5b95d0 100644 --- a/src/java-runtime/java/mono/android/MonoPackageManager.java +++ b/src/java-runtime/java/mono/android/MonoPackageManager.java @@ -55,7 +55,7 @@ public static void LoadApplication (Context context, ApplicationInfo runtimePack } // - // Should the order change here, src/monodroid/jni/SharedConstants.hh must be updated accordingly + // Should the order change here, src/native/runtime-base/shared-constants.hh must be updated accordingly // String[] appDirs = new String[] {filesDir, cacheDir, dataDir}; boolean haveSplitApks = runtimePackage.splitSourceDirs != null && runtimePackage.splitSourceDirs.length > 0; diff --git a/src/java-runtime/java/mono/android/clr/MonoPackageManager.java b/src/java-runtime/java/mono/android/clr/MonoPackageManager.java new file mode 100644 index 00000000000..6ece4b145a0 --- /dev/null +++ b/src/java-runtime/java/mono/android/clr/MonoPackageManager.java @@ -0,0 +1,123 @@ +package mono; + +import java.io.*; +import java.lang.String; +import java.time.OffsetDateTime; +import java.time.ZoneOffset; +import java.util.Calendar; +import java.util.Locale; +import java.util.HashSet; +import java.util.zip.*; +import java.util.Arrays; +import android.content.Context; +import android.content.Intent; +import android.content.pm.ApplicationInfo; +import android.content.res.AssetManager; +import android.os.Build; +import android.util.Log; +import mono.android.Runtime; +import mono.android.DebugRuntime; +import mono.android.BuildConfig; + +public class MonoPackageManager { + + static Object lock = new Object (); + static boolean initialized; + + static android.content.Context Context; + + public static void LoadApplication (Context context, ApplicationInfo runtimePackage, String[] apks) + { + synchronized (lock) { + if (context instanceof android.app.Application) { + Context = context; + } + if (!initialized) { + android.content.IntentFilter timezoneChangedFilter = new android.content.IntentFilter ( + android.content.Intent.ACTION_TIMEZONE_CHANGED + ); + context.registerReceiver (new mono.android.app.NotifyTimeZoneChanges (), timezoneChangedFilter); + + Locale locale = Locale.getDefault (); + String language = locale.getLanguage () + "-" + locale.getCountry (); + String filesDir = context.getFilesDir ().getAbsolutePath (); + String cacheDir = context.getCacheDir ().getAbsolutePath (); + String dataDir = getNativeLibraryPath (context); + ClassLoader loader = context.getClassLoader (); + String runtimeDir = getNativeLibraryPath (runtimePackage); + int localDateTimeOffset; + + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { + localDateTimeOffset = OffsetDateTime.now().getOffset().getTotalSeconds(); + } else { + localDateTimeOffset = (Calendar.getInstance ().get (Calendar.ZONE_OFFSET) + Calendar.getInstance ().get (Calendar.DST_OFFSET)) / 1000; + } + + // + // Should the order change here, src/native-clr/include/constants.hh must be updated accordingly + // + String[] appDirs = new String[] {filesDir, cacheDir, dataDir}; + boolean haveSplitApks = runtimePackage.splitSourceDirs != null && runtimePackage.splitSourceDirs.length > 0; + + System.loadLibrary("monodroid"); + + Runtime.initInternal ( + language, + apks, + runtimeDir, + appDirs, + localDateTimeOffset, + loader, + MonoPackageManager_Resources.Assemblies, + isEmulator (), + haveSplitApks + ); + + mono.android.app.ApplicationRegistration.registerApplications (); + + initialized = true; + } + } + } + + // We need to detect the emulator in order to determine the maximum gref count. + // The official Android emulator requires a much lower maximum than actual + // devices. Hopefully other emulators don't need the treatment. If they do, we + // can add their detection here. We should perform the absolute minimum of + // checking in order to save time. + static boolean isEmulator() + { + String val = Build.HARDWARE; + + // This detects the official Android emulator + if (val.contains ("ranchu") || val.contains ("goldfish")) + return true; + + return false; + } + + public static void setContext (Context context) + { + // Ignore; vestigial + } + + static String getNativeLibraryPath (Context context) + { + return getNativeLibraryPath (context.getApplicationInfo ()); + } + + static String getNativeLibraryPath (ApplicationInfo ainfo) + { + return ainfo.nativeLibraryDir; + } + + public static String[] getAssemblies () + { + return MonoPackageManager_Resources.Assemblies; + } + + public static String[] getDependencies () + { + return MonoPackageManager_Resources.Dependencies; + } +} diff --git a/src/native-clr/host/host-jni.cc b/src/native-clr/host/host-jni.cc index 3e9af6e868a..33b9180eff3 100644 --- a/src/native-clr/host/host-jni.cc +++ b/src/native-clr/host/host-jni.cc @@ -25,10 +25,10 @@ JNICALL Java_mono_android_Runtime_register (JNIEnv *env, [[maybe_unused]] jclass } JNIEXPORT void JNICALL -Java_mono_android_Runtime_init (JNIEnv *env, jclass klass, jstring lang, jobjectArray runtimeApksJava, - jstring runtimeNativeLibDir, jobjectArray appDirs, jint localDateTimeOffset, jobject loader, - jobjectArray assembliesJava, jboolean isEmulator, - jboolean haveSplitApks) +Java_mono_android_Runtime_initInternal (JNIEnv *env, jclass klass, jstring lang, jobjectArray runtimeApksJava, + jstring runtimeNativeLibDir, jobjectArray appDirs, jint localDateTimeOffset, jobject loader, + jobjectArray assembliesJava, jboolean isEmulator, + jboolean haveSplitApks) { } diff --git a/src/native-clr/include/host/host-jni.hh b/src/native-clr/include/host/host-jni.hh index 2104c2b1846..4904644ebd8 100644 --- a/src/native-clr/include/host/host-jni.hh +++ b/src/native-clr/include/host/host-jni.hh @@ -19,10 +19,10 @@ extern "C" { /* * Class: mono_android_Runtime - * Method: init + * Method: initInternal * Signature: (Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;ILjava/lang/ClassLoader;[Ljava/lang/String;IZZ)V */ - JNIEXPORT void JNICALL Java_mono_android_Runtime_init (JNIEnv *, jclass, jstring, jobjectArray, jstring, jobjectArray, jint, jobject, jobjectArray, jboolean, jboolean); + JNIEXPORT void JNICALL Java_mono_android_Runtime_initInternal (JNIEnv *, jclass, jstring, jobjectArray, jstring, jobjectArray, jint, jobject, jobjectArray, jboolean, jboolean); /* * Class: mono_android_Runtime diff --git a/src/native-clr/java-interop/CMakeLists.txt b/src/native-clr/java-interop/CMakeLists.txt index 702401df40c..a731f0110e0 100644 --- a/src/native-clr/java-interop/CMakeLists.txt +++ b/src/native-clr/java-interop/CMakeLists.txt @@ -1,4 +1,4 @@ -set(LIB_NAME xa-java-interop-clr) +set(LIB_NAME xa-java-interop) set(LIB_ALIAS xa::java-interop-clr) set(JAVA_INTEROP_SOURCES diff --git a/src/native-clr/libnet-android.map.txt b/src/native-clr/libnet-android.map.txt index f7e3c7c9fdf..9c8a580bc34 100644 --- a/src/native-clr/libnet-android.map.txt +++ b/src/native-clr/libnet-android.map.txt @@ -2,7 +2,7 @@ LIBNET_ANDROID { global: JNI_OnLoad; Java_mono_android_Runtime_dumpTimingData; - Java_mono_android_Runtime_init; + Java_mono_android_Runtime_initInternal; Java_mono_android_Runtime_notifyTimeZoneChanged; Java_mono_android_Runtime_propagateUncaughtException; Java_mono_android_Runtime_register; diff --git a/src/native-clr/runtime-base/CMakeLists.txt b/src/native-clr/runtime-base/CMakeLists.txt index 7e42498b5e4..6f2c07bb299 100644 --- a/src/native-clr/runtime-base/CMakeLists.txt +++ b/src/native-clr/runtime-base/CMakeLists.txt @@ -1,4 +1,4 @@ -set(LIB_NAME runtime-base-clr) +set(LIB_NAME runtime-base) set(LIB_ALIAS xa::runtime-base-clr) set(XA_RUNTIME_BASE_SOURCES @@ -43,13 +43,5 @@ target_link_libraries( xa::xamarin-app-clr ) -if(DEBUG_BUILD) - set_target_properties( - ${LIB_NAME} - PROPERTIES - ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" - ) -endif() - xa_add_compile_definitions(${LIB_NAME}) xa_add_include_directories(${LIB_NAME}) diff --git a/src/native-clr/runtime-base/android-system.cc b/src/native-clr/runtime-base/android-system.cc index fcf6a82b640..75dc394cdbd 100644 --- a/src/native-clr/runtime-base/android-system.cc +++ b/src/native-clr/runtime-base/android-system.cc @@ -11,13 +11,13 @@ auto AndroidSystem::lookup_system_property (std::string_view const& name, size_t &value_len) noexcept -> const char* { value_len = 0; -#if defined (DEBUG) - BundledProperty *p = lookup_system_property (name); - if (p != nullptr) { - value_len = p->value_len; - return p->name; - } -#endif // DEBUG || !ANDROID +// #if defined (DEBUG) +// BundledProperty *p = lookup_system_property (name); +// if (p != nullptr) { +// value_len = p->value_len; +// return p->name; +// } +// #endif // DEBUG || !ANDROID if (application_config.system_property_count == 0) { return nullptr; diff --git a/src/native-clr/shared/CMakeLists.txt b/src/native-clr/shared/CMakeLists.txt index 9c176e6ac65..c1a85951663 100644 --- a/src/native-clr/shared/CMakeLists.txt +++ b/src/native-clr/shared/CMakeLists.txt @@ -1,4 +1,4 @@ -set(LIB_NAME xa-shared-bits-clr) +set(LIB_NAME xa-shared-bits) set(LIB_ALIAS xa::shared-clr) set(XA_SHARED_SOURCES @@ -11,7 +11,6 @@ add_library( ${LIB_NAME} STATIC ${XA_SHARED_SOURCES} - ${XA_SHARED_CXX_ABI_SOURCES} ) add_library(${LIB_ALIAS} ALIAS ${LIB_NAME}) @@ -44,14 +43,6 @@ macro(lib_target_options TARGET_NAME) ${XA_COMMON_CXX_ARGS} ) - if(DEBUG_BUILD) - set_target_properties( - ${TARGET_NAME} - PROPERTIES - ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" - ) - endif() - xa_add_compile_definitions(${TARGET_NAME}) xa_add_include_directories(${TARGET_NAME}) endmacro() diff --git a/src/native-clr/startup/CMakeLists.txt b/src/native-clr/startup/CMakeLists.txt index 773eda8cf3a..2f6951c6275 100644 --- a/src/native-clr/startup/CMakeLists.txt +++ b/src/native-clr/startup/CMakeLists.txt @@ -1,4 +1,4 @@ -set(LIB_NAME xamarin-startup-clr) +set(LIB_NAME xamarin-startup) set(LIB_ALIAS xa::xamarin-startup-clr) set(XAMARIN_STARTUP_SOURCES @@ -8,11 +8,12 @@ add_clang_check_sources("${XAMARIN_STARTUP_SOURCES}") add_library( ${LIB_NAME} - SHARED + STATIC ${XAMARIN_STARTUP_SOURCES} ) add_library(${LIB_ALIAS} ALIAS ${LIB_NAME}) +set_static_library_suffix(${LIB_NAME}) target_include_directories( ${LIB_NAME} From d0faeb87843190e2d5b7679ab88436edbdbe3fca Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Tue, 3 Dec 2024 22:14:38 +0100 Subject: [PATCH 51/54] Build deps + application config for CLR --- .../Tasks/GeneratePackageManagerJava.cs | 75 ++-- .../Tasks/LinkApplicationSharedLibraries.cs | 8 +- .../Utilities/ApplicationConfigCLR.cs | 52 +++ ...icationConfigNativeAssemblyGeneratorCLR.cs | 388 ++++++++++++++++++ .../Xamarin.Android.Common.targets | 10 +- src/native-clr/host/host-jni.cc | 3 + src/native-clr/host/host.cc | 3 + src/native-clr/include/shared/log_types.hh | 6 + src/native-clr/java-interop/CMakeLists.txt | 8 - src/native-clr/lz4/CMakeLists.txt | 4 +- src/native-clr/native-clr.targets | 11 + src/native-clr/runtime-base/android-system.cc | 5 +- 12 files changed, 534 insertions(+), 39 deletions(-) create mode 100644 src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfigCLR.cs create mode 100644 src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfigNativeAssemblyGeneratorCLR.cs diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs index c0f7f0432ce..1b5eced8bb5 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs @@ -61,6 +61,9 @@ public class GeneratePackageManagerJava : AndroidTask [Required] public bool EnablePreloadAssembliesDefault { get; set; } + [Required] + public bool TargetsCLR { get; set; } + public bool EnableMarshalMethods { get; set; } public string RuntimeConfigBinFilePath { get; set; } public string BoundExceptionType { get; set; } @@ -321,31 +324,53 @@ void AddEnvironment () bool haveRuntimeConfigBlob = !String.IsNullOrEmpty (RuntimeConfigBinFilePath) && File.Exists (RuntimeConfigBinFilePath); var jniRemappingNativeCodeInfo = BuildEngine4.GetRegisteredTaskObjectAssemblyLocal (ProjectSpecificTaskObjectKey (GenerateJniRemappingNativeCode.JniRemappingNativeCodeInfoKey), RegisteredTaskObjectLifetime.Build); - var appConfigAsmGen = new ApplicationConfigNativeAssemblyGenerator (environmentVariables, systemProperties, Log) { - UsesMonoAOT = usesMonoAOT, - UsesMonoLLVM = EnableLLVM, - UsesAssemblyPreload = environmentParser.UsesAssemblyPreload, - MonoAOTMode = aotMode.ToString ().ToLowerInvariant (), - AotEnableLazyLoad = AndroidAotEnableLazyLoad, - AndroidPackageName = AndroidPackageName, - BrokenExceptionTransitions = environmentParser.BrokenExceptionTransitions, - PackageNamingPolicy = pnp, - BoundExceptionType = boundExceptionType, - JniAddNativeMethodRegistrationAttributePresent = NativeCodeGenState.TemplateJniAddNativeMethodRegistrationAttributePresent, - HaveRuntimeConfigBlob = haveRuntimeConfigBlob, - NumberOfAssembliesInApk = assemblyCount, - BundledAssemblyNameWidth = assemblyNameWidth, - MonoComponents = (MonoComponent)monoComponents, - NativeLibraries = uniqueNativeLibraries, - HaveAssemblyStore = UseAssemblyStore, - AndroidRuntimeJNIEnvToken = android_runtime_jnienv_class_token, - JNIEnvInitializeToken = jnienv_initialize_method_token, - JNIEnvRegisterJniNativesToken = jnienv_registerjninatives_method_token, - JniRemappingReplacementTypeCount = jniRemappingNativeCodeInfo == null ? 0 : jniRemappingNativeCodeInfo.ReplacementTypeCount, - JniRemappingReplacementMethodIndexEntryCount = jniRemappingNativeCodeInfo == null ? 0 : jniRemappingNativeCodeInfo.ReplacementMethodIndexEntryCount, - MarshalMethodsEnabled = EnableMarshalMethods, - IgnoreSplitConfigs = ShouldIgnoreSplitConfigs (), - }; + LLVMIR.LlvmIrComposer appConfigAsmGen; + + if (TargetsCLR) { + appConfigAsmGen = new ApplicationConfigNativeAssemblyGeneratorCLR (environmentVariables, systemProperties, Log) { + UsesAssemblyPreload = environmentParser.UsesAssemblyPreload, + AndroidPackageName = AndroidPackageName, + PackageNamingPolicy = pnp, + JniAddNativeMethodRegistrationAttributePresent = NativeCodeGenState.TemplateJniAddNativeMethodRegistrationAttributePresent, + HaveRuntimeConfigBlob = haveRuntimeConfigBlob, + NumberOfAssembliesInApk = assemblyCount, + BundledAssemblyNameWidth = assemblyNameWidth, + NativeLibraries = uniqueNativeLibraries, + AndroidRuntimeJNIEnvToken = android_runtime_jnienv_class_token, + JNIEnvInitializeToken = jnienv_initialize_method_token, + JNIEnvRegisterJniNativesToken = jnienv_registerjninatives_method_token, + JniRemappingReplacementTypeCount = jniRemappingNativeCodeInfo == null ? 0 : jniRemappingNativeCodeInfo.ReplacementTypeCount, + JniRemappingReplacementMethodIndexEntryCount = jniRemappingNativeCodeInfo == null ? 0 : jniRemappingNativeCodeInfo.ReplacementMethodIndexEntryCount, + MarshalMethodsEnabled = EnableMarshalMethods, + IgnoreSplitConfigs = ShouldIgnoreSplitConfigs (), + }; + } else { + appConfigAsmGen = new ApplicationConfigNativeAssemblyGenerator (environmentVariables, systemProperties, Log) { + UsesMonoAOT = usesMonoAOT, + UsesMonoLLVM = EnableLLVM, + UsesAssemblyPreload = environmentParser.UsesAssemblyPreload, + MonoAOTMode = aotMode.ToString ().ToLowerInvariant (), + AotEnableLazyLoad = AndroidAotEnableLazyLoad, + AndroidPackageName = AndroidPackageName, + BrokenExceptionTransitions = environmentParser.BrokenExceptionTransitions, + PackageNamingPolicy = pnp, + BoundExceptionType = boundExceptionType, + JniAddNativeMethodRegistrationAttributePresent = NativeCodeGenState.TemplateJniAddNativeMethodRegistrationAttributePresent, + HaveRuntimeConfigBlob = haveRuntimeConfigBlob, + NumberOfAssembliesInApk = assemblyCount, + BundledAssemblyNameWidth = assemblyNameWidth, + MonoComponents = (MonoComponent)monoComponents, + NativeLibraries = uniqueNativeLibraries, + HaveAssemblyStore = UseAssemblyStore, + AndroidRuntimeJNIEnvToken = android_runtime_jnienv_class_token, + JNIEnvInitializeToken = jnienv_initialize_method_token, + JNIEnvRegisterJniNativesToken = jnienv_registerjninatives_method_token, + JniRemappingReplacementTypeCount = jniRemappingNativeCodeInfo == null ? 0 : jniRemappingNativeCodeInfo.ReplacementTypeCount, + JniRemappingReplacementMethodIndexEntryCount = jniRemappingNativeCodeInfo == null ? 0 : jniRemappingNativeCodeInfo.ReplacementMethodIndexEntryCount, + MarshalMethodsEnabled = EnableMarshalMethods, + IgnoreSplitConfigs = ShouldIgnoreSplitConfigs (), + }; + } LLVMIR.LlvmIrModule appConfigModule = appConfigAsmGen.Construct (); foreach (string abi in SupportedAbis) { diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/LinkApplicationSharedLibraries.cs b/src/Xamarin.Android.Build.Tasks/Tasks/LinkApplicationSharedLibraries.cs index 6fb2dac8967..4d9aef3bcd4 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/LinkApplicationSharedLibraries.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/LinkApplicationSharedLibraries.cs @@ -43,6 +43,9 @@ sealed class InputFiles [Required] public string AndroidBinUtilsDirectory { get; set; } + [Required] + public bool TargetsCLR { get; set; } + public int ZipAlignmentPages { get; set; } = AndroidZipAlign.DefaultZipAlignment64Bit; public override System.Threading.Tasks.Task RunTaskAsync () @@ -123,11 +126,12 @@ IEnumerable GetLinkerConfigs () abis [abi] = GatherFilesForABI (item.ItemSpec, abi, ObjectFiles, runtimeNativeLibsDir, runtimeNativeLibStubsDir); } - const string commonLinkerArgs = + string soname = TargetsCLR ? "libxamarin-app-clr.so" : "libxamarin-app.so"; + string commonLinkerArgs = "--shared " + "--allow-shlib-undefined " + "--export-dynamic " + - "-soname libxamarin-app.so " + + $"-soname {soname} " + "-z relro " + "-z noexecstack " + "--enable-new-dtags " + diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfigCLR.cs b/src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfigCLR.cs new file mode 100644 index 00000000000..0e5593bb363 --- /dev/null +++ b/src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfigCLR.cs @@ -0,0 +1,52 @@ +using System; + +namespace Xamarin.Android.Tasks; + +// Declaration order of fields and their types must correspond *exactly* to that in +// src/native-clr/xamarin-app-stub/xamarin-app.hh ApplicationConfig structure +// +// Type mappings: +// +// C++ C# +// -----------|---------- +// bool | bool +// uint8_t | byte +// int8_t | sbyte +// uint16_t | ushort +// int16_t | short +// uint32_t | uint +// int32_t | int +// uint64_t | ulong +// int64_t | long +// char* | string +// +// Names should be the same as in the above struct, but it's not a requirement +// (they will be used only to generate comments in the native code) +sealed class ApplicationConfigCLR +{ + public bool uses_assembly_preload; + public bool jni_add_native_method_registration_attribute_present; + public bool have_runtime_config_blob; + public bool marshal_methods_enabled; + public bool ignore_split_configs; + public uint package_naming_policy; + public uint environment_variable_count; + public uint system_property_count; + public uint number_of_assemblies_in_apk; + public uint bundled_assembly_name_width; + public uint number_of_dso_cache_entries; + public uint number_of_aot_cache_entries; + public uint number_of_shared_libraries; + + [NativeAssembler (NumberFormat = LLVMIR.LlvmIrVariableNumberFormat.Hexadecimal)] + public uint android_runtime_jnienv_class_token; + + [NativeAssembler (NumberFormat = LLVMIR.LlvmIrVariableNumberFormat.Hexadecimal)] + public uint jnienv_initialize_method_token; + + [NativeAssembler (NumberFormat = LLVMIR.LlvmIrVariableNumberFormat.Hexadecimal)] + public uint jnienv_registerjninatives_method_token; + public uint jni_remapping_replacement_type_count; + public uint jni_remapping_replacement_method_index_entry_count; + public string android_package_name = String.Empty; +} diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfigNativeAssemblyGeneratorCLR.cs b/src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfigNativeAssemblyGeneratorCLR.cs new file mode 100644 index 00000000000..24ec67e9e73 --- /dev/null +++ b/src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfigNativeAssemblyGeneratorCLR.cs @@ -0,0 +1,388 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; + +using Java.Interop.Tools.TypeNameMappings; +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; +using Xamarin.Android.Tasks.LLVMIR; + +namespace Xamarin.Android.Tasks; + +class ApplicationConfigNativeAssemblyGeneratorCLR : LlvmIrComposer +{ + sealed class DSOCacheEntryContextDataProvider : NativeAssemblerStructContextDataProvider + { + public override string GetComment (object data, string fieldName) + { + var dso_entry = EnsureType (data); + if (String.Compare ("hash", fieldName, StringComparison.Ordinal) == 0) { + return $" from name: {dso_entry.HashedName}"; + } + + if (String.Compare ("name", fieldName, StringComparison.Ordinal) == 0) { + return $" name: {dso_entry.name}"; + } + + return String.Empty; + } + } + + // Order of fields and their type must correspond *exactly* (with exception of the + // ignored managed members) to that in + // src/monodroid/jni/xamarin-app.hh DSOCacheEntry structure + [NativeAssemblerStructContextDataProvider (typeof (DSOCacheEntryContextDataProvider))] + sealed class DSOCacheEntry + { + [NativeAssembler (Ignore = true)] + public string HashedName; + + [NativeAssembler (UsesDataProvider = true, NumberFormat = LlvmIrVariableNumberFormat.Hexadecimal)] + public ulong hash; + + [NativeAssembler (NumberFormat = LlvmIrVariableNumberFormat.Hexadecimal)] + public ulong real_name_hash; + public bool ignore; + + [NativeAssembler (UsesDataProvider = true)] + public string name; + public IntPtr handle = IntPtr.Zero; + } + + sealed class DSOApkEntry + { + public ulong name_hash; + public uint offset; // offset into the APK + public int fd; // apk file descriptor + }; + + // Order of fields and their type must correspond *exactly* to that in + // src/monodroid/jni/xamarin-app.hh AssemblyStoreAssemblyDescriptor structure + sealed class AssemblyStoreAssemblyDescriptor + { + public uint data_offset; + public uint data_size; + + public uint debug_data_offset; + public uint debug_data_size; + + public uint config_data_offset; + public uint config_data_size; + } + + // Order of fields and their type must correspond *exactly* to that in + // src/monodroid/jni/xamarin-app.hh AssemblyStoreSingleAssemblyRuntimeData structure + sealed class AssemblyStoreSingleAssemblyRuntimeData + { + [NativePointer] + public byte image_data; + + [NativePointer] + public byte debug_info_data; + + [NativePointer] + public byte config_data; + + [NativePointer] + public AssemblyStoreAssemblyDescriptor descriptor; + } + + // Order of fields and their type must correspond *exactly* to that in + // src/monodroid/jni/xamarin-app.hh AssemblyStoreRuntimeData structure + sealed class AssemblyStoreRuntimeData + { + [NativePointer (IsNull = true)] + public byte data_start; + public uint assembly_count; + public uint index_entry_count; + + [NativePointer (IsNull = true)] + public AssemblyStoreAssemblyDescriptor assemblies; + } + + sealed class XamarinAndroidBundledAssemblyContextDataProvider : NativeAssemblerStructContextDataProvider + { + public override ulong GetBufferSize (object data, string fieldName) + { + var xaba = EnsureType (data); + if (String.Compare ("name", fieldName, StringComparison.Ordinal) == 0) { + return xaba.name_length; + } + + if (String.Compare ("file_name", fieldName, StringComparison.Ordinal) == 0) { + return xaba.name_length + MonoAndroidHelper.GetMangledAssemblyNameSizeOverhead (); + } + + return 0; + } + } + + // Order of fields and their type must correspond *exactly* to that in + // src/monodroid/jni/xamarin-app.hh XamarinAndroidBundledAssembly structure + [NativeAssemblerStructContextDataProvider (typeof (XamarinAndroidBundledAssemblyContextDataProvider))] + sealed class XamarinAndroidBundledAssembly + { + public int file_fd; + + [NativeAssembler (UsesDataProvider = true), NativePointer (PointsToPreAllocatedBuffer = true)] + public string file_name; + public uint data_offset; + public uint data_size; + + [NativePointer] + public byte data; + public uint name_length; + + [NativeAssembler (UsesDataProvider = true), NativePointer (PointsToPreAllocatedBuffer = true)] + public string name; + } + + // Keep in sync with FORMAT_TAG in src/monodroid/jni/xamarin-app.hh + const ulong FORMAT_TAG = 0x00025E6972616D58; // 'Xmari^XY' where XY is the format version + + SortedDictionary ? environmentVariables; + SortedDictionary ? systemProperties; + StructureInstance? application_config; + List>? dsoCache; + List>? aotDsoCache; + List>? xamarinAndroidBundledAssemblies; + + StructureInfo? applicationConfigStructureInfo; + StructureInfo? dsoCacheEntryStructureInfo; + StructureInfo? dsoApkEntryStructureInfo; + StructureInfo? xamarinAndroidBundledAssemblyStructureInfo; + StructureInfo? assemblyStoreSingleAssemblyRuntimeDataStructureinfo; + StructureInfo? assemblyStoreRuntimeDataStructureInfo; + + public bool UsesAssemblyPreload { get; set; } + public string AndroidPackageName { get; set; } + public bool JniAddNativeMethodRegistrationAttributePresent { get; set; } + public bool HaveRuntimeConfigBlob { get; set; } + public int NumberOfAssembliesInApk { get; set; } + public int BundledAssemblyNameWidth { get; set; } // including the trailing NUL + public int AndroidRuntimeJNIEnvToken { get; set; } + public int JNIEnvInitializeToken { get; set; } + public int JNIEnvRegisterJniNativesToken { get; set; } + public int JniRemappingReplacementTypeCount { get; set; } + public int JniRemappingReplacementMethodIndexEntryCount { get; set; } + public PackageNamingPolicy PackageNamingPolicy { get; set; } + public List NativeLibraries { get; set; } + public bool MarshalMethodsEnabled { get; set; } + public bool IgnoreSplitConfigs { get; set; } + + public ApplicationConfigNativeAssemblyGeneratorCLR (IDictionary environmentVariables, IDictionary systemProperties, TaskLoggingHelper log) + : base (log) + { + if (environmentVariables != null) { + this.environmentVariables = new SortedDictionary (environmentVariables, StringComparer.Ordinal); + } + + if (systemProperties != null) { + this.systemProperties = new SortedDictionary (systemProperties, StringComparer.Ordinal); + } + } + + protected override void Construct (LlvmIrModule module) + { + MapStructures (module); + + module.AddGlobalVariable ("format_tag", FORMAT_TAG, comment: $" 0x{FORMAT_TAG:x}"); + + var envVars = new LlvmIrGlobalVariable (environmentVariables, "app_environment_variables") { + Comment = " Application environment variables array, name:value", + }; + module.Add (envVars, stringGroupName: "env", stringGroupComment: " Application environment variables name:value pairs"); + + var sysProps = new LlvmIrGlobalVariable (systemProperties, "app_system_properties") { + Comment = " System properties defined by the application", + }; + module.Add (sysProps, stringGroupName: "sysprop", stringGroupComment: " System properties name:value pairs"); + + (dsoCache, aotDsoCache) = InitDSOCache (); + var app_cfg = new ApplicationConfigCLR { + uses_assembly_preload = UsesAssemblyPreload, + jni_add_native_method_registration_attribute_present = JniAddNativeMethodRegistrationAttributePresent, + have_runtime_config_blob = HaveRuntimeConfigBlob, + marshal_methods_enabled = MarshalMethodsEnabled, + ignore_split_configs = IgnoreSplitConfigs, + package_naming_policy = (uint)PackageNamingPolicy, + environment_variable_count = (uint)(environmentVariables == null ? 0 : environmentVariables.Count * 2), + system_property_count = (uint)(systemProperties == null ? 0 : systemProperties.Count * 2), + number_of_assemblies_in_apk = (uint)NumberOfAssembliesInApk, + number_of_shared_libraries = (uint)NativeLibraries.Count, + bundled_assembly_name_width = (uint)BundledAssemblyNameWidth, + number_of_dso_cache_entries = (uint)dsoCache.Count, + number_of_aot_cache_entries = (uint)aotDsoCache.Count, + android_runtime_jnienv_class_token = (uint)AndroidRuntimeJNIEnvToken, + jnienv_initialize_method_token = (uint)JNIEnvInitializeToken, + jnienv_registerjninatives_method_token = (uint)JNIEnvRegisterJniNativesToken, + jni_remapping_replacement_type_count = (uint)JniRemappingReplacementTypeCount, + jni_remapping_replacement_method_index_entry_count = (uint)JniRemappingReplacementMethodIndexEntryCount, + android_package_name = AndroidPackageName, + }; + application_config = new StructureInstance (applicationConfigStructureInfo, app_cfg); + module.AddGlobalVariable ("application_config", application_config); + + var dso_cache = new LlvmIrGlobalVariable (dsoCache, "dso_cache", LlvmIrVariableOptions.GlobalWritable) { + Comment = " DSO cache entries", + BeforeWriteCallback = HashAndSortDSOCache, + }; + module.Add (dso_cache); + + var aot_dso_cache = new LlvmIrGlobalVariable (aotDsoCache, "aot_dso_cache", LlvmIrVariableOptions.GlobalWritable) { + Comment = " AOT DSO cache entries", + BeforeWriteCallback = HashAndSortDSOCache, + }; + module.Add (aot_dso_cache); + + var dso_apk_entries = new LlvmIrGlobalVariable (typeof(List>), "dso_apk_entries") { + ArrayItemCount = (ulong)NativeLibraries.Count, + Options = LlvmIrVariableOptions.GlobalWritable, + ZeroInitializeArray = true, + }; + module.Add (dso_apk_entries); + + string bundledBuffersSize = xamarinAndroidBundledAssemblies == null ? "empty (unused when assembly stores are enabled)" : $"{BundledAssemblyNameWidth} bytes long"; + var bundled_assemblies = new LlvmIrGlobalVariable (typeof(List>), "bundled_assemblies", LlvmIrVariableOptions.GlobalWritable) { + Value = xamarinAndroidBundledAssemblies, + Comment = $" Bundled assembly name buffers, all {bundledBuffersSize}", + }; + module.Add (bundled_assemblies); + + AddAssemblyStores (module); + } + + void AddAssemblyStores (LlvmIrModule module) + { + ulong itemCount = (ulong)(NumberOfAssembliesInApk); + var assembly_store_bundled_assemblies = new LlvmIrGlobalVariable (typeof(List>), "assembly_store_bundled_assemblies", LlvmIrVariableOptions.GlobalWritable) { + ZeroInitializeArray = true, + ArrayItemCount = itemCount, + }; + module.Add (assembly_store_bundled_assemblies); + + var storeRuntimeData = new AssemblyStoreRuntimeData { + data_start = 0, + assembly_count = 0, + }; + + var assembly_store = new LlvmIrGlobalVariable ( + new StructureInstance(assemblyStoreRuntimeDataStructureInfo, storeRuntimeData), + "assembly_store", + LlvmIrVariableOptions.GlobalWritable + ); + module.Add (assembly_store); + } + + void HashAndSortDSOCache (LlvmIrVariable variable, LlvmIrModuleTarget target, object? state) + { + var cache = variable.Value as List>; + if (cache == null) { + throw new InvalidOperationException ($"Internal error: DSO cache must not be empty"); + } + + bool is64Bit = target.Is64Bit; + foreach (StructureInstance instance in cache) { + if (instance.Obj == null) { + throw new InvalidOperationException ("Internal error: DSO cache must not contain null entries"); + } + + var entry = instance.Obj as DSOCacheEntry; + if (entry == null) { + throw new InvalidOperationException ($"Internal error: DSO cache entry has unexpected type {instance.Obj.GetType ()}"); + } + + entry.hash = MonoAndroidHelper.GetXxHash (entry.HashedName, is64Bit); + entry.real_name_hash = MonoAndroidHelper.GetXxHash (entry.name, is64Bit); + } + + cache.Sort ((StructureInstance a, StructureInstance b) => a.Instance.hash.CompareTo (b.Instance.hash)); + } + + (List> dsoCache, List> aotDsoCache) InitDSOCache () + { + var dsos = new List<(string name, string nameLabel, bool ignore)> (); + var nameCache = new HashSet (StringComparer.OrdinalIgnoreCase); + + foreach (ITaskItem item in NativeLibraries) { + string? name = item.GetMetadata ("ArchiveFileName"); + if (String.IsNullOrEmpty (name)) { + name = item.ItemSpec; + } + name = Path.GetFileName (name); + + if (nameCache.Contains (name)) { + continue; + } + + dsos.Add ((name, $"dsoName{dsos.Count.ToString (CultureInfo.InvariantCulture)}", ELFHelper.IsEmptyAOTLibrary (Log, item.ItemSpec))); + } + + var dsoCache = new List> (); + var aotDsoCache = new List> (); + var nameMutations = new List (); + + for (int i = 0; i < dsos.Count; i++) { + string name = dsos[i].name; + nameMutations.Clear(); + AddNameMutations (name); + // All mutations point to the actual library name, but have hash of the mutated one + foreach (string entryName in nameMutations) { + var entry = new DSOCacheEntry { + HashedName = entryName, + hash = 0, // Hash is arch-specific, we compute it before writing + ignore = dsos[i].ignore, + name = name, + }; + + var item = new StructureInstance (dsoCacheEntryStructureInfo, entry); + if (name.StartsWith ("libaot-", StringComparison.OrdinalIgnoreCase)) { + aotDsoCache.Add (item); + } else { + dsoCache.Add (item); + } + } + } + + return (dsoCache, aotDsoCache); + + void AddNameMutations (string name) + { + nameMutations.Add (name); + if (name.EndsWith (".dll.so", StringComparison.OrdinalIgnoreCase)) { + string nameNoExt = Path.GetFileNameWithoutExtension (Path.GetFileNameWithoutExtension (name))!; + nameMutations.Add (nameNoExt); + + // This helps us at runtime, because sometimes MonoVM will ask for "AssemblyName" and sometimes for "AssemblyName.dll". + // In the former case, the runtime would ask for the "libaot-AssemblyName.so" image, which doesn't exist - we have + // "libaot-AssemblyName.dll.so" instead and, thus, we are forced to check for and append the missing ".dll" extension when + // loading the assembly, unnecessarily wasting time. + nameMutations.Add ($"{nameNoExt}.so"); + } else { + nameMutations.Add (Path.GetFileNameWithoutExtension (name)!); + } + + const string aotPrefix = "libaot-"; + if (name.StartsWith (aotPrefix, StringComparison.OrdinalIgnoreCase)) { + AddNameMutations (name.Substring (aotPrefix.Length)); + } + + const string libPrefix = "lib"; + if (name.StartsWith (libPrefix, StringComparison.OrdinalIgnoreCase)) { + AddNameMutations (name.Substring (libPrefix.Length)); + } + } + } + + void MapStructures (LlvmIrModule module) + { + applicationConfigStructureInfo = module.MapStructure (); + module.MapStructure (); + assemblyStoreSingleAssemblyRuntimeDataStructureinfo = module.MapStructure (); + assemblyStoreRuntimeDataStructureInfo = module.MapStructure (); + xamarinAndroidBundledAssemblyStructureInfo = module.MapStructure (); + dsoCacheEntryStructureInfo = module.MapStructure (); + dsoApkEntryStructureInfo = module.MapStructure (); + } +} diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets index 5f02df064b9..4e33b2af86a 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets @@ -1745,6 +1745,7 @@ because xbuild doesn't support framework reference assemblies. UseAssemblyStore="$(AndroidUseAssemblyStore)" EnableMarshalMethods="$(_AndroidUseMarshalMethods)" CustomBundleConfigFile="$(AndroidBundleConfigurationFile)" + TargetsCLR="$(_AndroidUseCLR)" > @@ -2007,11 +2008,17 @@ because xbuild doesn't support framework reference assemblies. - + <_ApplicationSharedLibrary Include="$(_AndroidApplicationSharedLibraryPath)%(_BuildTargetAbis.Identity)\libxamarin-app.so"> %(_BuildTargetAbis.Identity) + + + <_ApplicationSharedLibrary Include="$(_AndroidApplicationSharedLibraryPath)%(_BuildTargetAbis.Identity)\libxamarin-app-clr.so"> + %(_BuildTargetAbis.Identity) + + diff --git a/src/native-clr/host/host-jni.cc b/src/native-clr/host/host-jni.cc index 33b9180eff3..43775ad0918 100644 --- a/src/native-clr/host/host-jni.cc +++ b/src/native-clr/host/host-jni.cc @@ -1,11 +1,14 @@ #include #include +#include using namespace xamarin::android; JNIEXPORT jint JNICALL JNI_OnLoad (JavaVM *vm, void *reserved) { + log_write (LOG_DEFAULT, LogLevel::Info, "JNI_OnLoad"); + return Host::Java_JNI_OnLoad (vm, reserved); } diff --git a/src/native-clr/host/host.cc b/src/native-clr/host/host.cc index 735ae4dfa60..8ca3f58580c 100644 --- a/src/native-clr/host/host.cc +++ b/src/native-clr/host/host.cc @@ -1,11 +1,14 @@ #include #include #include +#include using namespace xamarin::android; auto Host::Java_JNI_OnLoad (JavaVM *vm, [[maybe_unused]] void *reserved) noexcept -> jint { + log_write (LOG_DEFAULT, LogLevel::Info, "Host init"); + AndroidSystem::init_max_gref_count (); return JNI_VERSION_1_6; } diff --git a/src/native-clr/include/shared/log_types.hh b/src/native-clr/include/shared/log_types.hh index 66b1cae5097..656146ec203 100644 --- a/src/native-clr/include/shared/log_types.hh +++ b/src/native-clr/include/shared/log_types.hh @@ -47,6 +47,12 @@ namespace xamarin::android { // A slightly faster alternative to other log functions as it doesn't parse the message // for format placeholders nor it uses variable arguments void log_write (LogCategories category, LogLevel level, const char *message) noexcept; + + [[gnu::always_inline]] + static inline void log_write (LogCategories category, LogLevel level, std::string_view const& message) noexcept + { + log_write (category, level, message.data ()); + } } template [[gnu::always_inline]] diff --git a/src/native-clr/java-interop/CMakeLists.txt b/src/native-clr/java-interop/CMakeLists.txt index a731f0110e0..24a233e2b80 100644 --- a/src/native-clr/java-interop/CMakeLists.txt +++ b/src/native-clr/java-interop/CMakeLists.txt @@ -39,12 +39,4 @@ target_compile_options( ${XA_COMMON_CXX_ARGS} ) -if(DEBUG_BUILD) - set_target_properties( - ${LIB_NAME} - PROPERTIES - ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" - ) -endif() - xa_add_compile_definitions(${LIB_NAME}) diff --git a/src/native-clr/lz4/CMakeLists.txt b/src/native-clr/lz4/CMakeLists.txt index 16a35099fd5..140034771f1 100644 --- a/src/native-clr/lz4/CMakeLists.txt +++ b/src/native-clr/lz4/CMakeLists.txt @@ -1,4 +1,4 @@ -set(LIB_NAME xa-lz4-clr) +set(LIB_NAME xa-lz4) set(LIB_ALIAS xa::lz4-clr) set(LZ4_SRC_DIR "${EXTERNAL_DIR}/lz4/lib") @@ -16,6 +16,8 @@ add_library( add_library(${LIB_ALIAS} ALIAS ${LIB_NAME}) +set_static_library_suffix(${LIB_NAME}) + target_compile_definitions( ${LIB_NAME} PRIVATE diff --git a/src/native-clr/native-clr.targets b/src/native-clr/native-clr.targets index dba9f075f5b..6b5e9260382 100644 --- a/src/native-clr/native-clr.targets +++ b/src/native-clr/native-clr.targets @@ -15,6 +15,11 @@ <_ConfigureRuntimesInputs Include="CMakeLists.txt" /> + <_ConfigureRuntimesInputs Include="host\CMakeLists.txt" /> + <_ConfigureRuntimesInputs Include="runtime-base\CMakeLists.txt" /> + <_ConfigureRuntimesInputs Include="shared\CMakeLists.txt" /> + <_ConfigureRuntimesInputs Include="startup\CMakeLists.txt" /> + <_ConfigureRuntimesInputs Include="xamarin-app-stub\CMakeLists.txt" /> <_ConfigureRuntimesInputs Include="java-interop\CMakeLists.txt" /> <_ConfigureRuntimesInputs Include="lz4\CMakeLists.txt" /> <_ConfigureRuntimesInputs Include="..\..\build-tools\scripts\Ndk.targets" /> @@ -58,6 +63,12 @@ + <_MonoDroidSources Include="include/**/*.hh" /> + <_MonoDroidSources Include="host/*.cc" /> + <_MonoDroidSources Include="runtime-base/*.cc" /> + <_MonoDroidSources Include="shared/*.cc" /> + <_MonoDroidSources Include="startup/*.cc" /> + <_MonoDroidSources Include="xamarin-app-stub/*.cc" /> <_MonoDroidSources Include="$(JavaInteropFullPath)\src\java-interop\*.cc;$(JavaInteropFullPath)\src\java-interop\*.h" /> <_MonoDroidSources Include="$(LZ4SourceFullPath)\lib\lz4.c;$(LZ4SourceFullPath)\lib\lz4.h" /> diff --git a/src/native-clr/runtime-base/android-system.cc b/src/native-clr/runtime-base/android-system.cc index 75dc394cdbd..dd381f994a8 100644 --- a/src/native-clr/runtime-base/android-system.cc +++ b/src/native-clr/runtime-base/android-system.cc @@ -86,8 +86,9 @@ auto AndroidSystem::monodroid_get_system_property (std::string_view const& name, size_t plen; const char *v = lookup_system_property (name, plen); - if (v == nullptr) + if (v == nullptr) { return len; + } value.assign (v, plen); return Helpers::add_with_overflow_check (plen, 0); @@ -107,7 +108,7 @@ AndroidSystem::get_max_gref_count_from_system () noexcept -> long dynamic_local_string override; if (monodroid_get_system_property (Constants::DEBUG_MONO_MAX_GREFC, override) > 0) { char *e; - max = strtol (override.get (), &e, 10); + max = strtol (override.get (), &e, 10); switch (*e) { case 'k': e++; From 555cd9c0d4f1165ba7ae74dd6ec51b5d47fb3365 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Wed, 4 Dec 2024 19:46:46 +0100 Subject: [PATCH 52/54] Moving on: logging + timing --- src/native-clr/host/host.cc | 18 + src/native-clr/include/constants.hh | 3 + src/native-clr/include/host/host.hh | 14 + src/native-clr/include/runtime-base/logger.hh | 63 +++ .../include/runtime-base/monodroid-state.hh | 21 + .../runtime-base/startup-aware-lock.hh | 40 ++ .../include/runtime-base/strings.hh | 29 ++ .../include/runtime-base/timing-internal.hh | 466 ++++++++++++++++++ src/native-clr/include/runtime-base/timing.hh | 149 ++++++ src/native-clr/include/runtime-base/util.hh | 21 + src/native-clr/runtime-base/CMakeLists.txt | 4 + src/native-clr/runtime-base/logger.cc | 214 ++++++++ .../runtime-base/timing-internal.cc | 83 ++++ src/native-clr/runtime-base/timing.cc | 14 + src/native-clr/runtime-base/util.cc | 45 ++ 15 files changed, 1184 insertions(+) create mode 100644 src/native-clr/include/runtime-base/logger.hh create mode 100644 src/native-clr/include/runtime-base/monodroid-state.hh create mode 100644 src/native-clr/include/runtime-base/startup-aware-lock.hh create mode 100644 src/native-clr/include/runtime-base/timing-internal.hh create mode 100644 src/native-clr/include/runtime-base/timing.hh create mode 100644 src/native-clr/include/runtime-base/util.hh create mode 100644 src/native-clr/runtime-base/logger.cc create mode 100644 src/native-clr/runtime-base/timing-internal.cc create mode 100644 src/native-clr/runtime-base/timing.cc create mode 100644 src/native-clr/runtime-base/util.cc diff --git a/src/native-clr/host/host.cc b/src/native-clr/host/host.cc index 8ca3f58580c..5d3e5830c62 100644 --- a/src/native-clr/host/host.cc +++ b/src/native-clr/host/host.cc @@ -1,10 +1,28 @@ #include #include #include +#include +#include #include using namespace xamarin::android; +void Host::Java_mono_android_Runtime_initInternal (JNIEnv *env, jclass klass, jstring lang, jobjectArray runtimeApksJava, + jstring runtimeNativeLibDir, jobjectArray appDirs, jint localDateTimeOffset, jobject loader, + jobjectArray assembliesJava, jboolean isEmulator, jboolean haveSplitApks) +{ + Logger::init_logging_categories (); + + // If fast logging is disabled, log messages immediately + FastTiming::initialize ((Logger::log_timing_categories() & LogTimingCategories::FastBare) != LogTimingCategories::FastBare); + + size_t total_time_index; + if (FastTiming::enabled ()) [[unlikely]] { + _timing = std::make_unique (); + total_time_index = internal_timing->start_event (TimingEventKind::TotalRuntimeInit); + } +} + auto Host::Java_JNI_OnLoad (JavaVM *vm, [[maybe_unused]] void *reserved) noexcept -> jint { log_write (LOG_DEFAULT, LogLevel::Info, "Host init"); diff --git a/src/native-clr/include/constants.hh b/src/native-clr/include/constants.hh index e850723ec00..d18ba60e0ed 100644 --- a/src/native-clr/include/constants.hh +++ b/src/native-clr/include/constants.hh @@ -92,5 +92,8 @@ namespace xamarin::android { // 64-bit unsigned or 64-bit signed with sign static constexpr size_t MAX_INTEGER_DIGIT_COUNT_BASE10 = 21uz; static constexpr size_t INTEGER_BASE10_BUFFER_SIZE = MAX_INTEGER_DIGIT_COUNT_BASE10 + 1uz; + + // Documented in NDK's comments + static constexpr size_t MAX_LOGCAT_MESSAGE_LENGTH = 1023uz; }; } diff --git a/src/native-clr/include/host/host.hh b/src/native-clr/include/host/host.hh index 03e4186ebae..577dc77f9e3 100644 --- a/src/native-clr/include/host/host.hh +++ b/src/native-clr/include/host/host.hh @@ -1,7 +1,10 @@ #pragma once +#include + #include +#include "../runtime-base/timing.hh" #include "../shared/log_types.hh" namespace xamarin::android { @@ -9,5 +12,16 @@ namespace xamarin::android { { public: static auto Java_JNI_OnLoad (JavaVM *vm, void *reserved) noexcept -> jint; + static void Java_mono_android_Runtime_initInternal (JNIEnv *env, jclass klass, jstring lang, jobjectArray runtimeApksJava, + jstring runtimeNativeLibDir, jobjectArray appDirs, jint localDateTimeOffset, jobject loader, + jobjectArray assembliesJava, jboolean isEmulator, jboolean haveSplitApks); + + static auto get_timing () -> Timing* + { + return _timing.get (); + } + + private: + static inline std::unique_ptr _timing{}; }; } diff --git a/src/native-clr/include/runtime-base/logger.hh b/src/native-clr/include/runtime-base/logger.hh new file mode 100644 index 00000000000..45c9e2449bd --- /dev/null +++ b/src/native-clr/include/runtime-base/logger.hh @@ -0,0 +1,63 @@ +#pragma once + +#include + +#include + +#include +#include "strings.hh" + +namespace xamarin::android { + class Logger + { + public: + static void init_logging_categories () noexcept; + static void init_reference_logging (std::string_view const& override_dir) noexcept; + + static auto log_timing_categories () noexcept -> LogTimingCategories + { + return _log_timing_categories; + } + + static void set_gc_spew_enabled (bool yesno) noexcept + { + _gc_spew_enabled = yesno; + } + + static auto gc_spew_enabled () noexcept -> bool + { + return _gc_spew_enabled; + } + + static auto gref_log () -> FILE* + { + return _gref_log; + } + + static auto lref_log () -> FILE* + { + return _lref_log; + } + + static auto gref_to_logcat () -> bool + { + return _gref_to_logcat; + } + + static auto lref_to_logcat () -> bool + { + return _lref_to_logcat; + } + + private: + static bool set_category (std::string_view const& name, string_segment& arg, unsigned int entry, bool arg_starts_with_name = false) noexcept; + + private: + static inline LogTimingCategories _log_timing_categories; + static inline bool _gc_spew_enabled = false; + static inline FILE *_gref_log = nullptr; + static inline FILE *_lref_log = nullptr; + static inline bool _gref_to_logcat = false; + static inline bool _lref_to_logcat = false; + }; +} diff --git a/src/native-clr/include/runtime-base/monodroid-state.hh b/src/native-clr/include/runtime-base/monodroid-state.hh new file mode 100644 index 00000000000..283040d4992 --- /dev/null +++ b/src/native-clr/include/runtime-base/monodroid-state.hh @@ -0,0 +1,21 @@ +#pragma once + +namespace xamarin::android +{ + class MonodroidState + { + public: + static auto is_startup_in_progress () noexcept -> bool + { + return startup_in_progress; + } + + static void mark_startup_done () noexcept + { + startup_in_progress = false; + } + + private: + inline static bool startup_in_progress = true; + }; +} diff --git a/src/native-clr/include/runtime-base/startup-aware-lock.hh b/src/native-clr/include/runtime-base/startup-aware-lock.hh new file mode 100644 index 00000000000..8b869151b61 --- /dev/null +++ b/src/native-clr/include/runtime-base/startup-aware-lock.hh @@ -0,0 +1,40 @@ +#pragma once + +#include + +#include "monodroid-state.hh" + +namespace xamarin::android +{ + class StartupAwareLock final + { + public: + explicit StartupAwareLock (std::mutex &m) + : lock (m) + { + if (MonodroidState::is_startup_in_progress ()) { + // During startup we run without threads, do nothing + return; + } + + lock.lock (); + } + + ~StartupAwareLock () + { + if (MonodroidState::is_startup_in_progress ()) { + return; + } + + lock.unlock (); + } + + StartupAwareLock (StartupAwareLock const&) = delete; + StartupAwareLock (StartupAwareLock const&&) = delete; + + StartupAwareLock& operator= (StartupAwareLock const&) = delete; + + private: + std::mutex& lock; + }; +} diff --git a/src/native-clr/include/runtime-base/strings.hh b/src/native-clr/include/runtime-base/strings.hh index c3326e91cc1..cfdb56f53b9 100644 --- a/src/native-clr/include/runtime-base/strings.hh +++ b/src/native-clr/include/runtime-base/strings.hh @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -21,6 +22,24 @@ namespace xamarin::android { static constexpr bool BoundsCheck = false; #endif + enum class string_segment_error + { + index_out_of_range, + }; + + static inline auto to_string (string_segment_error error) -> std::string_view const + { + using std::operator""sv; + + switch (error) { + case string_segment_error::index_out_of_range: + return "Index out of range"sv; + + default: + return "Unknown error"sv; + } + } + class string_segment { public: @@ -36,6 +55,16 @@ namespace xamarin::android { return _start; } + [[gnu::always_inline]] + auto at (size_t offset) const noexcept -> std::expected + { + if (offset >= length ()) { + return std::unexpected (string_segment_error::index_out_of_range); + } + + return _start + offset; + } + [[gnu::always_inline]] auto length () const noexcept -> size_t { diff --git a/src/native-clr/include/runtime-base/timing-internal.hh b/src/native-clr/include/runtime-base/timing-internal.hh new file mode 100644 index 00000000000..d9c29ca53a9 --- /dev/null +++ b/src/native-clr/include/runtime-base/timing-internal.hh @@ -0,0 +1,466 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +#include +#include +#include "startup-aware-lock.hh" +#include "strings.hh" +#include "util.hh" +#include "../constants.hh" +#include "monodroid-state.hh" + +namespace xamarin::android { + // bionic should use `time_t` in the timespec struct, but it uses `long` instead + using time_type = long; + + // Events should never change their assigned values and no values should be reused. + // Values are used by the test runner to determine what measurement was taken. + // + // At the same time, the list should be kept sorted alphabetically for easier reading - + // values therefore might be out of order, but always unique. + enum class TimingEventKind + { + AssemblyDecompression = 0, + AssemblyLoad = 1, + AssemblyPreload = 2, + DebugStart = 3, + Init = 4, + JavaToManaged = 5, + ManagedToJava = 6, + MonoRuntimeInit = 7, + NativeToManagedTransition = 8, + RuntimeConfigBlob = 9, + RuntimeRegister = 10, + TotalRuntimeInit = 11, + Unspecified = 12, + }; + + struct TimingEventPoint + { + time_t sec; + uint64_t ns; + }; + + struct TimingInterval + { + time_t sec; + uint32_t ms; + uint32_t ns; + }; + + struct TimingEvent + { + bool before_managed; + TimingEventPoint start; + TimingEventPoint end; + TimingEventKind kind; + std::unique_ptr more_info; + }; + + template + concept TimingPointType = requires (T a) { + { a.sec } -> std::same_as; + { a.ns } -> std::same_as; + }; + + template + concept TimingIntervalType = requires (T a) { + { a.sec } -> std::same_as; + { a.ms } -> std::same_as; + { a.ns } -> std::same_as; + }; + + class FastTiming final + { + // Number of TimingEvent entries in the event vector allocated at the + // time of class instantiation. It's an arbitrary value, but it should + // be large enough to not require any dynamic reallocation of memory at + // the run time. + static constexpr size_t INITIAL_EVENT_VECTOR_SIZE = 4096uz; + static constexpr uint32_t ns_in_millisecond = 1000000u; + static constexpr uint32_t ms_in_second = 1000u; + static constexpr uint32_t ns_in_second = ms_in_second * ns_in_millisecond; + + protected: + FastTiming () noexcept + { + events.reserve (INITIAL_EVENT_VECTOR_SIZE); + } + + public: + [[gnu::always_inline]] + static auto enabled () noexcept -> bool + { + return is_enabled; + } + + [[gnu::always_inline]] + static auto is_bare_mode () noexcept -> bool + { + return + (Logger::log_timing_categories() & LogTimingCategories::Bare) == LogTimingCategories::Bare || + (Logger::log_timing_categories() & LogTimingCategories::FastBare) == LogTimingCategories::FastBare; + } + + [[gnu::always_inline]] + static void initialize (bool log_immediately) noexcept + { + if (!Util::should_log (LOG_TIMING)) [[likely]] { + return; + } + + mark (init_time.start); + really_initialize (log_immediately); + mark (init_time.end); + + init_time.before_managed = true; + init_time.kind = TimingEventKind::Init; + + if (!immediate_logging) { + return; + } + + log (init_time, false /* skip_log_if_more_info_missing */); + } + + // std::vector isn't used in a conventional manner here. We treat it as if it was a standard array and we + // don't take advantage of any emplacement functionality, merely using vector's ability to resize itself when + // needed. The reason for this is speed - we can atomically increase index into the array and relatively + // quickly check whether it's within the boundaries. We can then safely use thus indexed element without + // worrying about concurrency. Emplacing a new element in the vector would require holding the mutex, something + // that's fairly costly and has unpredictable effect on time spent acquiring and holding the lock (the OS can + // preempt us at this point) + [[gnu::always_inline]] + auto start_event (TimingEventKind kind = TimingEventKind::Unspecified) noexcept -> size_t + { + size_t index = next_event_index.fetch_add (1); + + if (index >= events.capacity ()) [[unlikely]] { + StartupAwareLock lock (event_vector_realloc_mutex); + if (index >= events.size ()) { // don't increase unnecessarily, if another thread has already done that + // Double the vector size. We should, in theory, check for integer overflow here, but it's more + // likely we'll run out of memory way, way, way before that happens + size_t old_size = events.capacity (); + events.reserve (old_size << 1); + log_warn (LOG_TIMING, "Reallocated timing event buffer from {} to {}", old_size, events.size ()); + } + } + + TimingEvent &ev = events[index]; + mark (ev.start); + ev.kind = kind; + ev.before_managed = MonodroidState::is_startup_in_progress (); + ev.more_info = nullptr; + + return index; + } + + [[gnu::always_inline]] + void end_event (size_t event_index, bool uses_more_info = false) noexcept + { + if (!is_valid_event_index (event_index, __PRETTY_FUNCTION__)) [[unlikely]] { + return; + } + + mark (events[event_index].end); + log (events[event_index], uses_more_info /* skip_log_if_more_info_missing */); + } + + template + [[gnu::always_inline]] + void add_more_info (size_t event_index, string_base const& str) noexcept + { + if (!is_valid_event_index (event_index, __PRETTY_FUNCTION__)) [[unlikely]] { + return; + } + + events[event_index].more_info = std::make_unique (str.get (), str.length ()); + log (events[event_index], false /* skip_log_if_more_info_missing */); + } + + [[gnu::always_inline]] + void add_more_info (size_t event_index, const char* str) noexcept + { + if (!is_valid_event_index (event_index, __PRETTY_FUNCTION__)) [[unlikely]] { + return; + } + + events[event_index].more_info = std::make_unique (str); + log (events[event_index], false /* skip_log_if_more_info_missing */); + } + + [[gnu::always_inline]] + static void get_time (time_t &seconds_out, uint64_t& ns_out) noexcept + { + int ret; + timespec tv_ctm; + + ret = clock_gettime (CLOCK_MONOTONIC, &tv_ctm); + ns_out = ret == 0 ? static_cast(tv_ctm.tv_nsec) : 0; + seconds_out = ret == 0 ? tv_ctm.tv_sec : 0; + } + + template [[gnu::always_inline]] + static void calculate_interval (P const& start, P const& end, I &result) noexcept + { + uint64_t nsec; + if (end.ns < start.ns) { + result.sec = end.sec - start.sec - 1; + if (result.sec < 0) { + result.sec = 0; + } + nsec = 1000000000ULL + end.ns - start.ns; + } else { + result.sec = end.sec - start.sec; + nsec = end.ns - start.ns; + } + + result.ms = static_cast(nsec / ns_in_millisecond); + if (result.ms >= ms_in_second) { + result.sec += result.ms / ms_in_second; + result.ms = result.ms % ms_in_second; + } + + result.ns = static_cast(nsec % ns_in_millisecond); + } + + template [[gnu::always_inline]] + static void calculate_interval (P const& start, P const& end, I &result, uint64_t& total_ns) noexcept + { + calculate_interval (start, end, result); + total_ns = + (static_cast(result.sec) * static_cast(ns_in_second)) + + (static_cast(result.ms) * static_cast(ns_in_millisecond)) + + static_cast(result.ns); + } + + void dump () noexcept; + + private: + static void really_initialize (bool log_immediately) noexcept; + static void* timing_signal_thread (void *arg) noexcept; + + [[gnu::always_inline]] + static void mark (TimingEventPoint &point) noexcept + { + get_time (point.sec, point.ns); + } + + [[gnu::always_inline]] + auto is_valid_event_index (size_t index, const char *method_name) noexcept -> bool + { + if (index >= events.capacity ()) [[unlikely]] { + log_warn (LOG_TIMING, "Invalid event index passed to method '{}'", method_name); + return false; + } + + return true; + } + + template [[gnu::always_inline]] + static void append_event_kind_description (TimingEventKind kind, dynamic_local_string& message) noexcept + { + switch (kind) { + case TimingEventKind::AssemblyDecompression: { + constexpr char desc[] = "LZ4 decompression time for "; + message.append (desc); + return; + } + + case TimingEventKind::AssemblyLoad: { + constexpr char desc[] = "Assembly load"; + message.append (desc); + return; + } + + case TimingEventKind::AssemblyPreload: { + constexpr char desc[] = "Finished preloading, number of loaded assemblies: "; + message.append (desc); + return; + } + + case TimingEventKind::DebugStart: { + constexpr char desc[] = "Debug::start_debugging_and_profiling: end"; + message.append (desc); + return; + } + + case TimingEventKind::Init: { + constexpr char desc[] = "XATiming: init time"; + message.append (desc); + return; + } + + case TimingEventKind::JavaToManaged: { + constexpr char desc[] = "Typemap.java_to_managed: end, total time"; + message.append (desc); + return; + } + + case TimingEventKind::ManagedToJava: { + constexpr char desc[] = "Typemap.managed_to_java: end, total time"; + message.append (desc); + return; + } + + case TimingEventKind::MonoRuntimeInit: { + constexpr char desc[] = "Runtime.init: Mono runtime init"; + message.append (desc); + return; + } + + case TimingEventKind::NativeToManagedTransition: { + constexpr char desc[] = "Runtime.init: end native-to-managed transition"; + message.append (desc); + return; + } + + case TimingEventKind::RuntimeConfigBlob: { + constexpr char desc[] = "Register runtimeconfig binary blob"; + message.append (desc); + return; + } + + case TimingEventKind::RuntimeRegister: { + constexpr char desc[] = "Runtime.register: end time. Registered type: "; + message.append (desc); + return; + } + + case TimingEventKind::TotalRuntimeInit: { + constexpr char desc[] = "Runtime.init: end, total time"; + message.append (desc); + return; + } + + default: { + constexpr char desc[] = "Unknown timing event"; + message.append (desc); + return; + } + } + } + + // + // Message format is as follows: [STAGE/EVENT] ; elapsed s:ms::ns + // + // STAGE is one of: + // 0 - native init (before managed code runs) + // 1 - managed code enabled + // 2 - events summary (see the `dump()` function) + // + // EVENT is one of: + // for stages 0 and 1, it's the value of the TimingEventKind member + // for stage 2 see the `dump()` function + // + // The [STAGE/EVENT] format is meant to help the test runner application, so that it can parse logcat without + // having to be kept in sync with the actual wording used for the event message. + // + template [[gnu::always_inline]] + static void format_and_log (TimingEvent const& event, TimingInterval const& interval, dynamic_local_string& message, bool indent = false) noexcept + { + constexpr char INDENT[] = " "; + constexpr char NATIVE_INIT_TAG[] = "[0/"; + constexpr char MANAGED_TAG[] = "[1/"; + + message.clear (); + if (indent) { + message.append (INDENT); + } + + if (event.before_managed) { + message.append (NATIVE_INIT_TAG); + } else { + message.append (MANAGED_TAG); + } + + message.append (static_cast(event.kind)); + message.append ("] "); + + append_event_kind_description (event.kind, message); + if (event.more_info && !event.more_info->empty ()) { + message.append (event.more_info->c_str (), event.more_info->length ()); + } + + constexpr char COLON[] = ":"; + constexpr char TWO_COLONS[] = "::"; + + message.append ("; elapsed: "); + message.append (static_cast(interval.sec)); + message.append (COLON); + message.append (interval.ms); + message.append (TWO_COLONS); + message.append (interval.ns); + + log_write (LOG_TIMING, LogLevel::Info, message.get ()); + } + + template [[gnu::always_inline]] + static void format_and_log (TimingEvent const& event, dynamic_local_string& message, uint64_t& total_ns, bool indent = false) noexcept + { + TimingInterval interval; + calculate_interval (event.start, event.end, interval, total_ns); + format_and_log (event, interval, message, indent); + } + + [[gnu::always_inline]] + static void format_and_log (TimingEvent const& event) noexcept + { + TimingInterval interval; + calculate_interval (event.start, event.end, interval); + + // `message` isn't used here, it is passed to `format_and_log` so that the `dump()` function can + // be slightly more efficient when dumping the event buffer. + dynamic_local_string message; + format_and_log (event, interval, message); + } + + [[gnu::always_inline]] + static void log (TimingEvent const& event, bool skip_log_if_more_info_missing) noexcept + { + if (!immediate_logging) { + return; + } + + if (skip_log_if_more_info_missing && (!event.more_info || event.more_info->empty ())) { + return; + } + + format_and_log (event); + } + + [[gnu::always_inline]] + static void ns_to_time (uint64_t total_ns, uint32_t &sec, uint32_t &ms, uint32_t &ns) noexcept + { + sec = static_cast(total_ns / ns_in_second); + if (sec > 0) { + total_ns = total_ns % 1000000000ULL; + } + + ms = static_cast(total_ns / ns_in_millisecond); + if (ms >= 1000) { + sec += ms / 1000; + ms = ms % 1000; + } + + ns = static_cast(total_ns % ns_in_millisecond); + } + + private: + std::atomic_size_t next_event_index = 0uz; + std::mutex event_vector_realloc_mutex; + std::vector events; + + static inline TimingEvent init_time{}; + static inline bool is_enabled = false; + static inline bool immediate_logging = false; + }; + + extern FastTiming *internal_timing; +} diff --git a/src/native-clr/include/runtime-base/timing.hh b/src/native-clr/include/runtime-base/timing.hh new file mode 100644 index 00000000000..9baf105c4b1 --- /dev/null +++ b/src/native-clr/include/runtime-base/timing.hh @@ -0,0 +1,149 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "logger.hh" + +namespace xamarin::android +{ + struct timing_point + { + time_t sec = 0; + uint64_t ns = 0; + + void mark (); + + void reset () + { + sec = 0; + ns = 0; + } + }; + + struct timing_period + { + timing_point start; + timing_point end; + + void mark_start () + { + start.mark (); + } + + void mark_end () + { + end.mark (); + } + + void reset () + { + start.reset (); + end.reset (); + } + }; + + struct timing_diff + { + static constexpr uint32_t ms_in_nsec = 1000000ULL; + + time_t sec; + uint32_t ms; + uint32_t ns; + + timing_diff (const timing_period &period); + }; + + struct managed_timing_sequence + { + timing_period period; + bool in_use; + bool dynamic; + }; + + // This class is intended to be used by the managed code. It can be used by the native code as + // well, but the overhead it has (out of necessity) might not be desirable in native code. + class Timing + { + static inline constexpr std::string_view MESSAGE_FORMAT { "{}; elapsed: {}:{}::{}" }; + + public: + static constexpr size_t DEFAULT_POOL_SIZE = 16uz; + + public: + explicit Timing (size_t initial_pool_size = DEFAULT_POOL_SIZE) noexcept + : sequence_pool_size (initial_pool_size) + { + sequence_pool = new managed_timing_sequence [initial_pool_size] (); + } + + ~Timing () noexcept + { + delete[] sequence_pool; + } + + static void info (timing_period const &period, const char *message) noexcept + { + timing_diff diff (period); + + log_info_nocheck (LOG_TIMING, MESSAGE_FORMAT.data (), message == nullptr ? ""sv : message, diff.sec, diff.ms, diff.ns); + } + + static void warn (timing_period const &period, const char *message) noexcept + { + timing_diff diff (period); + + log_warn (LOG_TIMING, MESSAGE_FORMAT.data (), message == nullptr ? ""sv : message, diff.sec, diff.ms, diff.ns); + } + + managed_timing_sequence* get_available_sequence () noexcept + { + std::lock_guard lock (sequence_lock); + + managed_timing_sequence *ret; + for (size_t i = 0uz; i < sequence_pool_size; i++) { + if (sequence_pool[i].in_use) { + continue; + } + + ret = &sequence_pool[i]; + ret->in_use = true; + ret->dynamic = false; + + return ret; + } + + ret = new managed_timing_sequence (); + ret->dynamic = true; + + return ret; + } + + void release_sequence (managed_timing_sequence *sequence) + { + if (sequence == nullptr) + return; + + std::lock_guard lock (sequence_lock); + if (sequence->dynamic) { + sequence->period.reset (); + delete sequence; + return; + } + + sequence->in_use = false; + } + + private: + managed_timing_sequence *sequence_pool; + size_t sequence_pool_size; + std::mutex sequence_lock; + }; +} diff --git a/src/native-clr/include/runtime-base/util.hh b/src/native-clr/include/runtime-base/util.hh new file mode 100644 index 00000000000..d469871b6eb --- /dev/null +++ b/src/native-clr/include/runtime-base/util.hh @@ -0,0 +1,21 @@ +#pragma once + +#include +#include + +#include "logger.hh" + +namespace xamarin::android { + class Util + { + public: + static void create_public_directory (std::string_view const& dir); + static auto monodroid_fopen (std::string_view const& filename, std::string_view const& mode) noexcept -> FILE*; + static void set_world_accessable (std::string_view const& path); + + static auto should_log (LogCategories category) noexcept -> bool + { + return (log_categories & category) != 0; + } + }; +} diff --git a/src/native-clr/runtime-base/CMakeLists.txt b/src/native-clr/runtime-base/CMakeLists.txt index 6f2c07bb299..462a62e36dc 100644 --- a/src/native-clr/runtime-base/CMakeLists.txt +++ b/src/native-clr/runtime-base/CMakeLists.txt @@ -3,6 +3,10 @@ set(LIB_ALIAS xa::runtime-base-clr) set(XA_RUNTIME_BASE_SOURCES android-system.cc + logger.cc + timing.cc + timing-internal.cc + util.cc ) add_clang_check_sources("${XA_RUNTIME_BASE_SOURCES}") diff --git a/src/native-clr/runtime-base/logger.cc b/src/native-clr/runtime-base/logger.cc new file mode 100644 index 00000000000..c0d06769988 --- /dev/null +++ b/src/native-clr/runtime-base/logger.cc @@ -0,0 +1,214 @@ +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +using namespace xamarin::android; +using std::operator""sv; + +namespace { + FILE* + open_file (LogCategories category, std::string const& custom_path, std::string_view const& override_dir, std::string_view const& filename) + { + bool ignore_path = false; + if (!custom_path.empty () && access (custom_path.c_str (), W_OK) < 0) { + log_warn (category, + "Could not open path '{}' for logging (\"{}\"). Using '{}/{}' instead.", + custom_path, + strerror (errno), + override_dir, + filename + ); + ignore_path = true; + } + + std::string p{}; + if (custom_path.empty () || ignore_path) { + Util::create_public_directory (override_dir); + p.assign (override_dir); + p.append ("/"); + p.append (filename); + } + + std::string const& path = p.empty () ? custom_path : p; + unlink (path.c_str ()); + + FILE *f = Util::monodroid_fopen (path, "a"sv); + + if (f) { + Util::set_world_accessable (path); + } else { + log_warn (category, "Could not open path '{}' for logging: {}", path, strerror (errno)); + } + + return f; + } + + std::string gref_file{}; + std::string lref_file{}; + bool light_gref = false; + bool light_lref = false; +} + +void +Logger::init_reference_logging (std::string_view const& override_dir) noexcept +{ + if ((log_categories & LOG_GREF) != 0 && !light_gref) { + _gref_log = open_file (LOG_GREF, gref_file, override_dir, "grefs.txt"sv); + } + + if ((log_categories & LOG_LREF) != 0 && !light_lref) { + // if both lref & gref have files specified, and they're the same path, reuse the FILE*. + if (!lref_file.empty () && strcmp (lref_file.c_str (), !gref_file.empty () ? gref_file.c_str () : "") == 0) { + _lref_log = _gref_log; + } else { + _lref_log = open_file (LOG_LREF, lref_file, override_dir, "lrefs.txt"sv); + } + } +} + +[[gnu::always_inline]] bool +Logger::set_category (std::string_view const& name, string_segment& arg, unsigned int entry, bool arg_starts_with_name) noexcept +{ + if ((log_categories & entry) == entry) { + return false; + } + + if (arg_starts_with_name ? arg.starts_with (name) : arg.equal (name)) { + log_categories |= entry; + return true; + } + + return false; +} + +void +Logger::init_logging_categories () noexcept +{ + _log_timing_categories = LogTimingCategories::Default; + + dynamic_local_string value; + if (AndroidSystem::monodroid_get_system_property (Constants::DEBUG_MONO_LOG_PROPERTY, value) == 0) { + return; + } + + string_segment param; + while (value.next_token (',', param)) { + constexpr std::string_view CAT_ALL { "all" }; + + if (param.equal (CAT_ALL)) { + log_categories = 0xFFFFFFFF; + break; + } + + if (set_category ("assembly", param, LOG_ASSEMBLY)) { + continue; + } + + if (set_category ("default", param, LOG_DEFAULT)) { + continue; + } + + if (set_category ("debugger", param, LOG_DEBUGGER)) { + continue; + } + + if (set_category ("gc", param, LOG_GC)) { + continue; + } + + if (set_category ("gref", param, LOG_GREF)) { + continue; + } + + if (set_category ("lref", param, LOG_LREF)) { + continue; + } + + if (set_category ("timing", param, LOG_TIMING)) { + continue; + } + + if (set_category ("network", param, LOG_NET)) { + continue; + } + + if (set_category ("netlink", param, LOG_NETLINK)) { + continue; + } + + auto get_log_file_name = [](std::string_view const& file_kind, string_segment const& segment, size_t offset) -> const char* { + auto file_name = segment.at (offset); + + if (!file_name.has_value ()) { + log_warn (LOG_DEFAULT, "Unable to set path to {} log file: {}", file_kind, to_string (file_name.error ())); + return nullptr; + } + + return file_name.value (); + }; + + constexpr std::string_view CAT_GREF_EQUALS { "gref=" }; + if (set_category (CAT_GREF_EQUALS, param, LOG_GREF, true /* arg_starts_with_name */)) { + gref_file = get_log_file_name ("gref"sv, param, CAT_GREF_EQUALS.length ()); + continue; + } + + if (set_category ("gref-", param, LOG_GREF)) { + light_gref = true; + continue; + } + + if (set_category ("gref+", param, LOG_GREF)) { + _gref_to_logcat = true; + continue; + } + + constexpr std::string_view CAT_LREF_EQUALS { "lref=" }; + if (set_category (CAT_LREF_EQUALS, param, LOG_LREF, true /* arg_starts_with_name */)) { + lref_file = get_log_file_name ("lref"sv, param, CAT_LREF_EQUALS.length ()); + continue; + } + + if (set_category ("lref-", param, LOG_LREF)) { + light_lref = true; + continue; + } + + if (set_category ("lref+", param, LOG_LREF)) { + _lref_to_logcat = true; + continue; + } + + if (param.starts_with ("timing=fast-bare")) { + log_categories |= LOG_TIMING; + _log_timing_categories |= LogTimingCategories::FastBare; + continue; + } + + if (param.starts_with ("timing=bare")) { + log_categories |= LOG_TIMING; + _log_timing_categories |= LogTimingCategories::Bare; + continue; + } + } + + if ((log_categories & LOG_GC) != 0) { + _gc_spew_enabled = true; + } +} diff --git a/src/native-clr/runtime-base/timing-internal.cc b/src/native-clr/runtime-base/timing-internal.cc new file mode 100644 index 00000000000..fab5e4ed160 --- /dev/null +++ b/src/native-clr/runtime-base/timing-internal.cc @@ -0,0 +1,83 @@ +#include +#include + +using namespace xamarin::android; + +namespace xamarin::android { + FastTiming *internal_timing = nullptr; +} + +void +FastTiming::really_initialize (bool log_immediately) noexcept +{ + internal_timing = new FastTiming (); + is_enabled = true; + immediate_logging = log_immediately; + + if (immediate_logging) { + return; + } + + log_write (LOG_TIMING, LogLevel::Info, "[2/1] To get timing results, send the mono.android.app.DUMP_TIMING_DATA intent to the application"); +} + +void +FastTiming::dump () noexcept +{ + if (immediate_logging) { + return; + } + + StartupAwareLock lock { event_vector_realloc_mutex }; + size_t entries = next_event_index.load (); + + log_write (LOG_TIMING, LogLevel::Info, "[2/2] Performance measurement results"); + if (entries == 0) { + log_write (LOG_TIMING, LogLevel::Info, "[2/3] No events logged"); + return; + } + + dynamic_local_string message; + + // Values are in nanoseconds + uint64_t total_assembly_load_time = 0u; + uint64_t total_java_to_managed_time = 0u; + uint64_t total_managed_to_java_time = 0u; + uint64_t total_ns; + + format_and_log (init_time, message, total_ns, true /* indent */); + for (size_t i = 0uz; i < entries; i++) { + TimingEvent const& event = events[i]; + format_and_log (event, message, total_ns, true /* indent */); + + switch (event.kind) { + case TimingEventKind::AssemblyLoad: + total_assembly_load_time += total_ns; + break; + + case TimingEventKind::JavaToManaged: + total_java_to_managed_time += total_ns; + break; + + case TimingEventKind::ManagedToJava: + total_managed_to_java_time += total_ns; + break; + + default: + // Ignore other kinds + break; + } + } + + uint32_t sec, ms, ns; + log_write (LOG_TIMING, LogLevel::Info, "[2/4] Accumulated performance results"); + + ns_to_time (total_assembly_load_time, sec, ms, ns); + log_info_nocheck (LOG_TIMING, " [2/5] Assembly load: {}:{}::{}", sec, ms, ns); + + ns_to_time (total_java_to_managed_time, sec, ms, ns); + log_info_nocheck (LOG_TIMING, " [2/6] Java to Managed lookup: {}:{}::{}", sec, ms, ns); + + ns_to_time (total_managed_to_java_time, sec, ms, ns); + log_info_nocheck (LOG_TIMING, " [2/7] Managed to Java lookup: {}:{}::{}", sec, ms, ns); +} diff --git a/src/native-clr/runtime-base/timing.cc b/src/native-clr/runtime-base/timing.cc new file mode 100644 index 00000000000..930139e06e4 --- /dev/null +++ b/src/native-clr/runtime-base/timing.cc @@ -0,0 +1,14 @@ +#include +#include + +using namespace xamarin::android; + +void timing_point::mark () +{ + FastTiming::get_time (sec, ns); +} + +timing_diff::timing_diff (const timing_period &period) +{ + FastTiming::calculate_interval (period.start, period.end, *this); +} diff --git a/src/native-clr/runtime-base/util.cc b/src/native-clr/runtime-base/util.cc new file mode 100644 index 00000000000..1fb943b90cd --- /dev/null +++ b/src/native-clr/runtime-base/util.cc @@ -0,0 +1,45 @@ +#include +#include + +#include + +#include +#include + +using namespace xamarin::android; + +void Util::create_public_directory (std::string_view const& dir) +{ + mode_t m = umask (0); + int ret = mkdir (dir.data (), 0777); + if (ret < 0) { + log_warn (LOG_DEFAULT, "Failed to create directory '{}'. {}", dir, std::strerror (errno)); + } + umask (m); +} + +auto Util::monodroid_fopen (std::string_view const& filename, std::string_view const& mode) noexcept -> FILE* +{ + /* On Unix, both path and system calls are all assumed + * to be UTF-8 compliant. + */ + FILE *ret = fopen (filename.data (), mode.data ()); + if (ret == nullptr) { + log_error (LOG_DEFAULT, "fopen failed for file {}: {}", filename, strerror (errno)); + return nullptr; + } + + return ret; +} + +void Util::set_world_accessable (std::string_view const& path) +{ + int r; + do { + r = chmod (path.data (), 0664); + } while (r == -1 && errno == EINTR); + + if (r == -1) { + log_error (LOG_DEFAULT, "chmod(\"{}\", 0664) failed: {}", path, strerror (errno)); + } +} From 77aa40a0e37cac9d465fb2166f05301a7fbe91ec Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Wed, 4 Dec 2024 23:10:03 +0100 Subject: [PATCH 53/54] Beginnings of initialization code --- src/native-clr/host/host-jni.cc | 13 ++ src/native-clr/host/host.cc | 25 ++- src/native-clr/include/constants.hh | 8 + src/native-clr/include/host/host.hh | 2 +- .../include/runtime-base/android-system.hh | 8 + .../include/runtime-base/jni-wrappers.hh | 209 ++++++++++++++++++ .../include/runtime-base/strings.hh | 3 +- src/native-clr/include/runtime-base/util.hh | 95 ++++++++ src/native-clr/include/shared/cpp-util.hh | 63 +++++- src/native-clr/runtime-base/android-system.cc | 23 ++ src/native-clr/runtime-base/util.cc | 41 +++- src/native/shared/cpp-util.hh | 2 +- 12 files changed, 481 insertions(+), 11 deletions(-) create mode 100644 src/native-clr/include/runtime-base/jni-wrappers.hh diff --git a/src/native-clr/host/host-jni.cc b/src/native-clr/host/host-jni.cc index 43775ad0918..349bd178221 100644 --- a/src/native-clr/host/host-jni.cc +++ b/src/native-clr/host/host-jni.cc @@ -33,6 +33,19 @@ Java_mono_android_Runtime_initInternal (JNIEnv *env, jclass klass, jstring lang, jobjectArray assembliesJava, jboolean isEmulator, jboolean haveSplitApks) { + Host::Java_mono_android_Runtime_initInternal ( + env, + klass, + lang, + runtimeApksJava, + runtimeNativeLibDir, + appDirs, + localDateTimeOffset, + loader, + assembliesJava, + isEmulator, + haveSplitApks + ); } JNIEXPORT void diff --git a/src/native-clr/host/host.cc b/src/native-clr/host/host.cc index 5d3e5830c62..9164449d064 100644 --- a/src/native-clr/host/host.cc +++ b/src/native-clr/host/host.cc @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -17,10 +18,26 @@ void Host::Java_mono_android_Runtime_initInternal (JNIEnv *env, jclass klass, js FastTiming::initialize ((Logger::log_timing_categories() & LogTimingCategories::FastBare) != LogTimingCategories::FastBare); size_t total_time_index; - if (FastTiming::enabled ()) [[unlikely]] { - _timing = std::make_unique (); - total_time_index = internal_timing->start_event (TimingEventKind::TotalRuntimeInit); - } + if (FastTiming::enabled ()) [[unlikely]] { + _timing = std::make_unique (); + total_time_index = internal_timing->start_event (TimingEventKind::TotalRuntimeInit); + } + + jstring_array_wrapper applicationDirs (env, appDirs); + + jstring_wrapper jstr (env, lang); + Util::set_environment_variable ("LANG", jstr); + + jstring_wrapper &home = applicationDirs[Constants::APP_DIRS_FILES_DIR_INDEX]; + Util::set_environment_variable_for_directory ("TMPDIR", applicationDirs[Constants::APP_DIRS_CACHE_DIR_INDEX]); + Util::set_environment_variable_for_directory ("HOME", home); + + AndroidSystem::detect_embedded_dso_mode (applicationDirs); + AndroidSystem::set_running_in_emulator (isEmulator); + + if (FastTiming::enabled ()) [[unlikely]] { + internal_timing->end_event (total_time_index); + } } auto Host::Java_JNI_OnLoad (JavaVM *vm, [[maybe_unused]] void *reserved) noexcept -> jint diff --git a/src/native-clr/include/constants.hh b/src/native-clr/include/constants.hh index d18ba60e0ed..e7a5018b06c 100644 --- a/src/native-clr/include/constants.hh +++ b/src/native-clr/include/constants.hh @@ -1,5 +1,6 @@ #pragma once +#include #include #include @@ -95,5 +96,12 @@ namespace xamarin::android { // Documented in NDK's comments static constexpr size_t MAX_LOGCAT_MESSAGE_LENGTH = 1023uz; + + // PATH_MAX is always 4096 on Linux, but for our purposes it's most likely too much and since + // we use this value to allocate stack variables mostly, let's downsize it a bit to what the + // _XOPEN_PATH_MAX is set to + static constexpr size_t SENSIBLE_PATH_MAX = 1024uz; + + static constexpr int DEFAULT_DIRECTORY_MODE = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; }; } diff --git a/src/native-clr/include/host/host.hh b/src/native-clr/include/host/host.hh index 577dc77f9e3..d7c613da750 100644 --- a/src/native-clr/include/host/host.hh +++ b/src/native-clr/include/host/host.hh @@ -1,6 +1,6 @@ #pragma once -#include +#include #include diff --git a/src/native-clr/include/runtime-base/android-system.hh b/src/native-clr/include/runtime-base/android-system.hh index ad9975f9fc6..974cdecb97d 100644 --- a/src/native-clr/include/runtime-base/android-system.hh +++ b/src/native-clr/include/runtime-base/android-system.hh @@ -4,6 +4,7 @@ #include "../constants.hh" #include "../shared/log_types.hh" +#include "jni-wrappers.hh" #include "strings.hh" namespace xamarin::android { @@ -26,14 +27,21 @@ namespace xamarin::android { } static auto monodroid_get_system_property (std::string_view const& name, dynamic_local_string &value) noexcept -> int; + static void detect_embedded_dso_mode (jstring_array_wrapper& appDirs) noexcept; private: static auto lookup_system_property (std::string_view const &name, size_t &value_len) noexcept -> const char*; static auto monodroid__system_property_get (std::string_view const&, char *sp_value, size_t sp_value_len) noexcept -> int; static auto get_max_gref_count_from_system () noexcept -> long; + static void set_embedded_dso_mode_enabled (bool yesno) noexcept + { + embedded_dso_mode_enabled = yesno; + } + private: static inline long max_gref_count = 0; static inline bool running_in_emulator = false; + static inline bool embedded_dso_mode_enabled = false; }; } diff --git a/src/native-clr/include/runtime-base/jni-wrappers.hh b/src/native-clr/include/runtime-base/jni-wrappers.hh new file mode 100644 index 00000000000..679aed3df59 --- /dev/null +++ b/src/native-clr/include/runtime-base/jni-wrappers.hh @@ -0,0 +1,209 @@ +#pragma once + +#include + +#include + +#include + +namespace xamarin::android +{ + class jstring_array_wrapper; + + class jstring_wrapper + { + public: + explicit jstring_wrapper (JNIEnv *_env) noexcept + : env (_env), + jstr (nullptr) + { + abort_if_invalid_pointer_argument (_env, "_env"); + } + + explicit jstring_wrapper (JNIEnv *_env, const jobject jo) noexcept + : env (_env), + jstr (reinterpret_cast (jo)) + { + abort_if_invalid_pointer_argument (_env, "_env"); + } + + explicit jstring_wrapper (JNIEnv *_env, const jstring js) noexcept + : env (_env), + jstr (js) + { + abort_if_invalid_pointer_argument (_env, "_env"); + } + + jstring_wrapper (const jstring_wrapper&) = delete; + + ~jstring_wrapper () noexcept + { + release (); + } + + jstring_wrapper& operator=(const jstring_wrapper&) = delete; + + bool hasValue () noexcept + { + return jstr != nullptr; + } + + private: + [[gnu::always_inline]] + void ensure_cstr () noexcept + { + if (cstr != nullptr || env == nullptr) { + return; + } + + cstr = env->GetStringUTFChars (jstr, nullptr); + } + + public: + const char* get_cstr () noexcept + { + if (jstr == nullptr) { + return nullptr; + } + + ensure_cstr (); + return cstr; + } + + [[gnu::always_inline]] + const std::string_view get_string_view () noexcept + { + if (jstr == nullptr) { + return {}; + } + + ensure_cstr (); + return {cstr}; + } + + jstring_wrapper& operator= (const jobject new_jo) noexcept + { + assign (reinterpret_cast (new_jo)); + return *this; + } + + jstring_wrapper& operator= (const jstring new_js) noexcept + { + assign (new_js); + return *this; + } + + protected: + void release () noexcept + { + if (jstr == nullptr || cstr == nullptr || env == nullptr) { + return; + } + env->ReleaseStringUTFChars (jstr, cstr); + jobjectRefType type = env->GetObjectRefType (jstr); + switch (type) { + case JNILocalRefType: + env->DeleteLocalRef (jstr); + break; + + case JNIGlobalRefType: + env->DeleteGlobalRef (jstr); + break; + + case JNIWeakGlobalRefType: + env->DeleteWeakGlobalRef (jstr); + break; + + case JNIInvalidRefType: // To hush compiler warning + break; + } + + jstr = nullptr; + cstr = nullptr; + } + + void assign (const jstring new_js) noexcept + { + release (); + if (new_js == nullptr) { + return; + } + + jstr = new_js; + cstr = nullptr; + } + + friend class jstring_array_wrapper; + + private: + jstring_wrapper () + : env (nullptr), + jstr (nullptr) + {} + + private: + JNIEnv *env; + jstring jstr; + const char *cstr = nullptr; + }; + + class jstring_array_wrapper + { + public: + explicit jstring_array_wrapper (JNIEnv *_env) noexcept + : jstring_array_wrapper(_env, nullptr) + {} + + explicit jstring_array_wrapper (JNIEnv *_env, jobjectArray _arr) + : env (_env), + arr (_arr) + { + abort_if_invalid_pointer_argument (_env, "_env"); + if (_arr != nullptr) { + len = static_cast(_env->GetArrayLength (_arr)); + if (len > sizeof (static_wrappers) / sizeof (jstring_wrapper)) { + wrappers = new jstring_wrapper [len]; + } else { + wrappers = static_wrappers; + } + } else { + len = 0; + wrappers = nullptr; + } + } + + ~jstring_array_wrapper () noexcept + { + if (wrappers != nullptr && wrappers != static_wrappers) { + delete[] wrappers; + } + } + + size_t get_length () const noexcept + { + return len; + } + + jstring_wrapper& operator[] (size_t index) noexcept + { + if (index >= len) { + return invalid_wrapper; + } + + if (wrappers [index].env == nullptr) { + wrappers [index].env = env; + wrappers [index].jstr = reinterpret_cast (env->GetObjectArrayElement (arr, static_cast(index))); + } + + return wrappers [index]; + } + + private: + JNIEnv *env; + jobjectArray arr; + size_t len; + jstring_wrapper *wrappers; + jstring_wrapper static_wrappers[5]; + jstring_wrapper invalid_wrapper; + }; +} diff --git a/src/native-clr/include/runtime-base/strings.hh b/src/native-clr/include/runtime-base/strings.hh index cfdb56f53b9..aae49968f84 100644 --- a/src/native-clr/include/runtime-base/strings.hh +++ b/src/native-clr/include/runtime-base/strings.hh @@ -534,8 +534,9 @@ namespace xamarin::android { [[gnu::always_inline]] auto append_c (const char *s) noexcept -> string_base& { - if (s == nullptr) + if (s == nullptr) { return *this; + } return append (s, strlen (s)); } diff --git a/src/native-clr/include/runtime-base/util.hh b/src/native-clr/include/runtime-base/util.hh index d469871b6eb..f19feafc3c2 100644 --- a/src/native-clr/include/runtime-base/util.hh +++ b/src/native-clr/include/runtime-base/util.hh @@ -1,14 +1,37 @@ #pragma once +#include #include #include +#include + +#include "../constants.hh" +#include "../shared/helpers.hh" +#include "jni-wrappers.hh" #include "logger.hh" +#include "strings.hh" namespace xamarin::android { + namespace detail { + template + concept PathComponentString = requires { + std::same_as, char*> || + std::same_as, std::string_view> || + std::same_as, std::string>; + }; + + template + concept PathBuffer = requires { + std::derived_from, dynamic_local_storage> || + std::derived_from, static_local_storage>; + }; + } + class Util { public: + static int create_directory (const char *pathname, mode_t mode); static void create_public_directory (std::string_view const& dir); static auto monodroid_fopen (std::string_view const& filename, std::string_view const& mode) noexcept -> FILE*; static void set_world_accessable (std::string_view const& path); @@ -17,5 +40,77 @@ namespace xamarin::android { { return (log_categories & category) != 0; } + + static auto file_exists (const char *file) noexcept -> bool + { + if (file == nullptr) { + return false; + } + + struct stat s; + if (::stat (file, &s) == 0 && (s.st_mode & S_IFMT) == S_IFREG) { + return true; + } + return false; + } + + template + static auto file_exists (dynamic_local_string const& file) noexcept -> bool + { + if (file.empty ()) { + return false; + } + + return file_exists (file.get ()); + } + + static void set_environment_variable (std::string_view const& name, jstring_wrapper& value) noexcept + { + ::setenv (name.data (), value.get_cstr (), 1); + } + + static void set_environment_variable_for_directory (std::string_view const& name, jstring_wrapper& value, bool createDirectory, mode_t mode) noexcept + { + if (createDirectory) { + int rv = create_directory (value.get_cstr (), mode); + if (rv < 0 && errno != EEXIST) { + log_warn (LOG_DEFAULT, "Failed to create directory '{}' for environment variable '{}'. {}", value.get_string_view (), name, strerror (errno)); + } + } + set_environment_variable (name, value); + } + + static void set_environment_variable_for_directory (const char *name, jstring_wrapper &value) noexcept + { + set_environment_variable_for_directory (name, value, true, Constants::DEFAULT_DIRECTORY_MODE); + } + + private: + template TBuffer, detail::PathComponentString ...TPart> + static void path_combine_common (TBuffer& buf, TPart&&... parts) noexcept + { + buf.clear (); + + for (auto const& part : {parts...}) { + if (!buf.empty ()) { + buf.append ("/"sv); + } + + if constexpr (std::same_as, char*>) { + if (part != nullptr) { + buf.append_c (part); + } + } else { + buf.append (part); + } + } + } + + public: + template + static void path_combine (dynamic_local_string& buf, TParts&&... parts) noexcept + { + path_combine_common (buf, std::forward(parts)...); + } }; } diff --git a/src/native-clr/include/shared/cpp-util.hh b/src/native-clr/include/shared/cpp-util.hh index 2121305dd94..396292613bb 100644 --- a/src/native-clr/include/shared/cpp-util.hh +++ b/src/native-clr/include/shared/cpp-util.hh @@ -6,9 +6,12 @@ #include #include #include +#include #include +#include #include #include +#include #include #include @@ -29,6 +32,50 @@ namespace xamarin::android::detail { va_end (ap); return ret == -1 ? "Out of memory" : message; } + + [[gnu::always_inline]] + static inline std::string get_function_name (const char *signature) + { + using std::operator""sv; + + std::string_view sig { signature }; + if (sig.length () == 0) { + return ""; + } + + auto splitSignature = sig | std::views::split ("::"sv) | std::ranges::to> (); + + std::string ret; + if (splitSignature.size () > 1) { + ret.append (splitSignature [splitSignature.size () - 2]); + ret.append ("::"sv); + } + std::string_view func_name { splitSignature[splitSignature.size () - 1] }; + std::string_view::size_type args_pos = func_name.find ('('); + std::string_view::size_type name_start_pos = func_name.find (' '); + + if (name_start_pos == std::string_view::npos) { + name_start_pos = 0; + } else { + name_start_pos++; // point to after the space which separates return type from name + if (name_start_pos >= func_name.length ()) [[unlikely]] { + name_start_pos = 0; + } + } + + if (args_pos == std::string_view::npos) { + ret.append (func_name.substr (name_start_pos)); + } else { + // If there's a snafu with positions, start from 0 + if (name_start_pos >= args_pos || name_start_pos > func_name.length ()) [[unlikely]] { + name_start_pos = 0; + } + + ret.append (func_name.substr (name_start_pos, args_pos - name_start_pos)); + } + + return ret; + } } template F> @@ -62,7 +109,13 @@ abort_if_invalid_pointer_argument (T *ptr, const char *ptr_name, std::source_loc { abort_unless ( ptr != nullptr, - [&ptr_name] { return xamarin::android::detail::_format_message ("Parameter '%s' must be a valid pointer", ptr_name); }, + [&ptr_name, &sloc] { + return xamarin::android::detail::_format_message ( + "%s: parameter '%s' must be a valid pointer", + xamarin::android::detail::get_function_name (sloc.function_name ()).c_str (), + ptr_name + ); + }, sloc ); } @@ -73,7 +126,13 @@ abort_if_negative_integer_argument (int arg, const char *arg_name, std::source_l { abort_unless ( arg > 0, - [&arg_name] { return xamarin::android::detail::_format_message ("Parameter '%s' must be a valid pointer", arg_name); }, + [&arg_name, &sloc] { + return xamarin::android::detail::_format_message ( + "%s: parameter '%s' must be a positive integer", + xamarin::android::detail::get_function_name (sloc.function_name ()).c_str (), + arg_name + ); + }, sloc ); } diff --git a/src/native-clr/runtime-base/android-system.cc b/src/native-clr/runtime-base/android-system.cc index dd381f994a8..b2118026a1f 100644 --- a/src/native-clr/runtime-base/android-system.cc +++ b/src/native-clr/runtime-base/android-system.cc @@ -1,11 +1,34 @@ #include +#include #include #include #include #include +#include using namespace xamarin::android; +using std::operator""sv; + +void +AndroidSystem::detect_embedded_dso_mode (jstring_array_wrapper& appDirs) noexcept +{ + // appDirs[Constants::APP_DIRS_DATA_DIR_INDEX] points to the native library directory + dynamic_local_string libmonodroid_path; + Util::path_combine (libmonodroid_path, appDirs[Constants::APP_DIRS_DATA_DIR_INDEX].get_string_view (), "libmonodroid.so"sv); + + log_debug (LOG_ASSEMBLY, "Checking if libmonodroid was unpacked to {}", libmonodroid_path.get ()); + if (!Util::file_exists (libmonodroid_path)) { + log_debug (LOG_ASSEMBLY, "{} not found, assuming application/android:extractNativeLibs == false", libmonodroid_path.get ()); + set_embedded_dso_mode_enabled (true); + } else { + log_debug (LOG_ASSEMBLY, "Native libs extracted to {}, assuming application/android:extractNativeLibs == true", appDirs[Constants::APP_DIRS_DATA_DIR_INDEX].get_cstr ()); + set_embedded_dso_mode_enabled (false); + } + + Util::path_combine (libmonodroid_path, "first_part"sv, "second_part"sv, "third_part"sv, "file.txt"sv); + log_warn (LOG_DEFAULT, "path_combine test: {}", libmonodroid_path.get ()); +} auto AndroidSystem::lookup_system_property (std::string_view const& name, size_t &value_len) noexcept -> const char* diff --git a/src/native-clr/runtime-base/util.cc b/src/native-clr/runtime-base/util.cc index 1fb943b90cd..6cce7591a6a 100644 --- a/src/native-clr/runtime-base/util.cc +++ b/src/native-clr/runtime-base/util.cc @@ -8,7 +8,43 @@ using namespace xamarin::android; -void Util::create_public_directory (std::string_view const& dir) +int +Util::create_directory (const char *pathname, mode_t mode) +{ + // if (mode <= 0) + // mode = DEFAULT_DIRECTORY_MODE; + + // if (!pathname || *pathname == '\0') { + // errno = EINVAL; + // return -1; + // } + // mode_t oldumask = umask (022); + // std::unique_ptr path {strdup_new (pathname)}; + // int rv, ret = 0; + // for (char *d = path.get (); d != nullptr && *d; ++d) { + // if (*d != '/') + // continue; + // *d = 0; + // if (*path) { + // rv = make_directory (path.get (), mode); + // if (rv == -1 && errno != EEXIST) { + // ret = -1; + // break; + // } + // } + // *d = '/'; + // } + + // if (ret == 0) + // ret = make_directory (pathname, mode); + // umask (oldumask); + + // return ret; + return -1; +} + +void +Util::create_public_directory (std::string_view const& dir) { mode_t m = umask (0); int ret = mkdir (dir.data (), 0777); @@ -18,7 +54,8 @@ void Util::create_public_directory (std::string_view const& dir) umask (m); } -auto Util::monodroid_fopen (std::string_view const& filename, std::string_view const& mode) noexcept -> FILE* +auto +Util::monodroid_fopen (std::string_view const& filename, std::string_view const& mode) noexcept -> FILE* { /* On Unix, both path and system calls are all assumed * to be UTF-8 compliant. diff --git a/src/native/shared/cpp-util.hh b/src/native/shared/cpp-util.hh index 6e77d98f5f7..bf9b01bcadf 100644 --- a/src/native/shared/cpp-util.hh +++ b/src/native/shared/cpp-util.hh @@ -129,7 +129,7 @@ abort_if_negative_integer_argument (int arg, const char *arg_name, std::source_l arg > 0, [&arg_name, &sloc] { return xamarin::android::detail::_format_message ( - "%s: parameter '%s' must be a valid pointer", + "%s: parameter '%s' must be a positive integer", xamarin::android::detail::get_function_name (sloc.function_name ()).c_str (), arg_name ); From 5d96662c9e7a8277d418a0b98227e0c8777ea90a Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Thu, 5 Dec 2024 17:34:26 +0100 Subject: [PATCH 54/54] More environment work --- src/native-clr/host/host.cc | 33 +++ src/native-clr/include/constants.hh | 12 ++ src/native-clr/include/host/host.hh | 5 + .../include/runtime-base/android-system.hh | 57 ++++++ src/native-clr/include/runtime-base/util.hh | 7 + src/native-clr/runtime-base/android-system.cc | 192 +++++++++++++++++- .../xamarin-app-stub/application_dso_stub.cc | 1 + 7 files changed, 297 insertions(+), 10 deletions(-) diff --git a/src/native-clr/host/host.cc b/src/native-clr/host/host.cc index 9164449d064..2e8b58f4bc7 100644 --- a/src/native-clr/host/host.cc +++ b/src/native-clr/host/host.cc @@ -8,6 +8,35 @@ using namespace xamarin::android; +void Host::create_xdg_directory (jstring_wrapper& home, size_t home_len, std::string_view const& relative_path, std::string_view const& environment_variable_name) noexcept +{ + static_local_string dir (home_len + relative_path.length ()); + Util::path_combine (dir, home.get_string_view (), relative_path); + + log_debug (LOG_DEFAULT, "Creating XDG directory: {}", optional_string (dir.get ())); + int rv = Util::create_directory (dir.get (), Constants::DEFAULT_DIRECTORY_MODE); + if (rv < 0 && errno != EEXIST) { + log_warn (LOG_DEFAULT, "Failed to create XDG directory {}. {}", optional_string (dir.get ()), strerror (errno)); + } + + if (!environment_variable_name.empty ()) { + setenv (environment_variable_name.data (), dir.get (), 1); + } +} + +void Host::create_xdg_directories_and_environment (jstring_wrapper &homeDir) noexcept +{ + size_t home_len = strlen (homeDir.get_cstr ()); + + constexpr auto XDG_DATA_HOME = "XDG_DATA_HOME"sv; + constexpr auto HOME_PATH = ".local/share"sv; + create_xdg_directory (homeDir, home_len, HOME_PATH, XDG_DATA_HOME); + + constexpr auto XDG_CONFIG_HOME = "XDG_CONFIG_HOME"sv; + constexpr auto CONFIG_PATH = ".config"sv; + create_xdg_directory (homeDir, home_len, CONFIG_PATH, XDG_CONFIG_HOME); +} + void Host::Java_mono_android_Runtime_initInternal (JNIEnv *env, jclass klass, jstring lang, jobjectArray runtimeApksJava, jstring runtimeNativeLibDir, jobjectArray appDirs, jint localDateTimeOffset, jobject loader, jobjectArray assembliesJava, jboolean isEmulator, jboolean haveSplitApks) @@ -31,9 +60,13 @@ void Host::Java_mono_android_Runtime_initInternal (JNIEnv *env, jclass klass, js jstring_wrapper &home = applicationDirs[Constants::APP_DIRS_FILES_DIR_INDEX]; Util::set_environment_variable_for_directory ("TMPDIR", applicationDirs[Constants::APP_DIRS_CACHE_DIR_INDEX]); Util::set_environment_variable_for_directory ("HOME", home); + create_xdg_directories_and_environment (home); AndroidSystem::detect_embedded_dso_mode (applicationDirs); AndroidSystem::set_running_in_emulator (isEmulator); + AndroidSystem::set_primary_override_dir (home); + AndroidSystem::create_update_dir (AndroidSystem::get_primary_override_dir ()); + AndroidSystem::setup_environment (); if (FastTiming::enabled ()) [[unlikely]] { internal_timing->end_event (total_time_index); diff --git a/src/native-clr/include/constants.hh b/src/native-clr/include/constants.hh index e7a5018b06c..f024da0a6eb 100644 --- a/src/native-clr/include/constants.hh +++ b/src/native-clr/include/constants.hh @@ -17,6 +17,13 @@ namespace xamarin::android { #endif public: +#if defined(RELEASE) + static constexpr bool IsReleaseBuild = true; + static constexpr bool IsDebugBuild = false; +#else + static constexpr bool IsReleaseBuild = false; + static constexpr bool IsDebugBuild = true; +#endif static constexpr std::string_view MANGLED_ASSEMBLY_NAME_EXT { ".so" }; private: @@ -103,5 +110,10 @@ namespace xamarin::android { static constexpr size_t SENSIBLE_PATH_MAX = 1024uz; static constexpr int DEFAULT_DIRECTORY_MODE = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; + +#if defined (DEBUG) + static constexpr std::string_view OVERRIDE_ENVIRONMENT_FILE_NAME { "environment" }; + static constexpr uint32_t OVERRIDE_ENVIRONMENT_FILE_HEADER_SIZE = 22; +#endif }; } diff --git a/src/native-clr/include/host/host.hh b/src/native-clr/include/host/host.hh index d7c613da750..347e318e6c8 100644 --- a/src/native-clr/include/host/host.hh +++ b/src/native-clr/include/host/host.hh @@ -4,6 +4,7 @@ #include +#include "../runtime-base/jni-wrappers.hh" #include "../runtime-base/timing.hh" #include "../shared/log_types.hh" @@ -21,6 +22,10 @@ namespace xamarin::android { return _timing.get (); } + private: + static void create_xdg_directory (jstring_wrapper& home, size_t home_len, std::string_view const& relative_path, std::string_view const& environment_variable_name) noexcept; + static void create_xdg_directories_and_environment (jstring_wrapper &homeDir) noexcept; + private: static inline std::unique_ptr _timing{}; }; diff --git a/src/native-clr/include/runtime-base/android-system.hh b/src/native-clr/include/runtime-base/android-system.hh index 974cdecb97d..cf21b566dca 100644 --- a/src/native-clr/include/runtime-base/android-system.hh +++ b/src/native-clr/include/runtime-base/android-system.hh @@ -1,11 +1,16 @@ #pragma once +#include #include +#include #include "../constants.hh" #include "../shared/log_types.hh" #include "jni-wrappers.hh" #include "strings.hh" +#include "util.hh" + +struct BundledProperty; namespace xamarin::android { class AndroidSystem @@ -26,22 +31,74 @@ namespace xamarin::android { running_in_emulator = yesno; } + static auto get_primary_override_dir () noexcept -> std::string const& + { + return primary_override_dir; + } + + static void set_primary_override_dir (jstring_wrapper& home) noexcept + { + primary_override_dir = determine_primary_override_dir (home); + } + + static void create_update_dir (std::string const& override_dir) noexcept + { + if constexpr (Constants::IsReleaseBuild) { + /* + * Don't create .__override__ on Release builds, because Google requires + * that pre-loaded apps not create world-writable directories. + * + * However, if any logging is enabled (which should _not_ happen with + * pre-loaded apps!), we need the .__override__ directory... + */ + dynamic_local_string value; + if (log_categories == 0 && monodroid_get_system_property (Constants::DEBUG_MONO_PROFILE_PROPERTY, value) == 0) [[likely]] { + return; + } + } + + Util::create_public_directory (override_dir); + log_warn (LOG_DEFAULT, "Creating public update directory: `{}`", override_dir); + } + static auto monodroid_get_system_property (std::string_view const& name, dynamic_local_string &value) noexcept -> int; static void detect_embedded_dso_mode (jstring_array_wrapper& appDirs) noexcept; + static void setup_environment () noexcept; private: static auto lookup_system_property (std::string_view const &name, size_t &value_len) noexcept -> const char*; static auto monodroid__system_property_get (std::string_view const&, char *sp_value, size_t sp_value_len) noexcept -> int; static auto get_max_gref_count_from_system () noexcept -> long; +#if defined(DEBUG) + static void add_system_property (const char *name, const char *value) noexcept; + static void setup_environment (const char *name, const char *value) noexcept; + static void setup_environment_from_override_file (dynamic_local_string const& path) noexcept; +#endif static void set_embedded_dso_mode_enabled (bool yesno) noexcept { embedded_dso_mode_enabled = yesno; } + static auto determine_primary_override_dir (jstring_wrapper &home) noexcept -> std::string + { + dynamic_local_string name { home.get_cstr () }; + name.append ("/") + .append (Constants::OVERRIDE_DIRECTORY_NAME) + .append ("/") + .append (Constants::android_lib_abi); + + return {name.get (), name.length ()}; + } + private: static inline long max_gref_count = 0; static inline bool running_in_emulator = false; static inline bool embedded_dso_mode_enabled = false; + static inline std::string primary_override_dir; + +#if defined (DEBUG) + static inline std::unordered_map bundled_properties; +#endif }; } diff --git a/src/native-clr/include/runtime-base/util.hh b/src/native-clr/include/runtime-base/util.hh index f19feafc3c2..555b81e8db2 100644 --- a/src/native-clr/include/runtime-base/util.hh +++ b/src/native-clr/include/runtime-base/util.hh @@ -86,6 +86,7 @@ namespace xamarin::android { } private: + // TODO: needs some work to accept mixed params of different accepted types template TBuffer, detail::PathComponentString ...TPart> static void path_combine_common (TBuffer& buf, TPart&&... parts) noexcept { @@ -112,5 +113,11 @@ namespace xamarin::android { { path_combine_common (buf, std::forward(parts)...); } + + template + static void path_combine (static_local_string& buf, TParts&&... parts) noexcept + { + path_combine_common (buf, std::forward(parts)...); + } }; } diff --git a/src/native-clr/runtime-base/android-system.cc b/src/native-clr/runtime-base/android-system.cc index b2118026a1f..7946cc30580 100644 --- a/src/native-clr/runtime-base/android-system.cc +++ b/src/native-clr/runtime-base/android-system.cc @@ -10,6 +10,179 @@ using namespace xamarin::android; using std::operator""sv; +#if defined(DEBUG) +[[gnu::always_inline]] +void +AndroidSystem::add_system_property (const char *name, const char *value) noexcept +{ + if (name == nullptr || *name == '\0') { + log_warn (LOG_DEFAULT, "Attempt to add a bundled system property without a valid name"); + return; + } + + if (value == nullptr) { + value = ""; + } + + bundled_properties[name] = value; +} + +void +AndroidSystem::setup_environment (const char *name, const char *value) noexcept +{ + if (name == nullptr || *name == '\0') { + return; + } + + const char *v = value; + if (v == nullptr) { + v = ""; + } + + if (isupper (name [0]) || name [0] == '_') { + if (setenv (name, v, 1) < 0) { + log_warn (LOG_DEFAULT, "(Debug) Failed to set environment variable: {}", strerror (errno)); + } + return; + } + + add_system_property (name, v); +} + +void +AndroidSystem::setup_environment_from_override_file (dynamic_local_string const& path) noexcept +{ + using read_count_type = size_t; + + struct stat sbuf; + if (::stat (path.get (), &sbuf) < 0) { + log_warn (LOG_DEFAULT, "Failed to stat the environment override file {}: {}", path.get (), strerror (errno)); + return; + } + + int fd = open (path.get (), O_RDONLY); + if (fd < 0) { + log_warn (LOG_DEFAULT, "Failed to open the environment override file {}: {}", path.get (), strerror (errno)); + return; + } + + auto file_size = static_cast(sbuf.st_size); + size_t nread = 0uz; + ssize_t r; + auto buf = std::make_unique (file_size); + + do { + auto read_count = static_cast(file_size - nread); + r = read (fd, buf.get () + nread, read_count); + if (r > 0) { + nread += static_cast(r); + } + } while (r < 0 && errno == EINTR); + + if (nread == 0) { + log_warn (LOG_DEFAULT, "Failed to read the environment override file {}: {}", path.get (), strerror (errno)); + return; + } + + // The file format is as follows (no newlines are used, this is just for illustration + // purposes, comments aren't part of the file either): + // + // # 10 ASCII characters formattted as a C++ hexadecimal number terminated with NUL: name + // # width (including the terminating NUL) + // 0x00000000\0 + // + // # 10 ASCII characters formattted as a C++ hexadecimal number terminated with NUL: value + // # width (including the terminating NUL) + // 0x00000000\0 + // + // # Variable name, terminated with NUL and padded to [name width] with NUL characters + // name\0 + // + // # Variable value, terminated with NUL and padded to [value width] with NUL characters + // value\0 + if (nread < Constants::OVERRIDE_ENVIRONMENT_FILE_HEADER_SIZE) { + log_warn (LOG_DEFAULT, "Invalid format of the environment override file {}: malformatted header", path.get ()); + return; + } + + char *endptr; + unsigned long name_width = strtoul (buf.get (), &endptr, 16); + if ((name_width == std::numeric_limits::max () && errno == ERANGE) || (buf[0] != '\0' && *endptr != '\0')) { + log_warn (LOG_DEFAULT, "Malformed header of the environment override file {}: name width has invalid format", path.get ()); + return; + } + + unsigned long value_width = strtoul (buf.get () + 11, &endptr, 16); + if ((value_width == std::numeric_limits::max () && errno == ERANGE) || (buf[0] != '\0' && *endptr != '\0')) { + log_warn (LOG_DEFAULT, "Malformed header of the environment override file {}: value width has invalid format", path.get ()); + return; + } + + uint64_t data_width = name_width + value_width; + if (data_width > file_size - Constants::OVERRIDE_ENVIRONMENT_FILE_HEADER_SIZE || (file_size - Constants::OVERRIDE_ENVIRONMENT_FILE_HEADER_SIZE) % data_width != 0) { + log_warn (LOG_DEFAULT, "Malformed environment override file {}: invalid data size", path.get ()); + return; + } + + uint64_t data_size = static_cast(file_size); + char *name = buf.get () + Constants::OVERRIDE_ENVIRONMENT_FILE_HEADER_SIZE; + while (data_size > 0 && data_size >= data_width) { + if (*name == '\0') { + log_warn (LOG_DEFAULT, "Malformed environment override file {}: name at offset {} is empty", path.get (), name - buf.get ()); + return; + } + + log_debug (LOG_DEFAULT, "Setting environment variable from the override file {}: '{}' = '{}'", path.get (), name, name + name_width); + setup_environment (name, name + name_width); + name += data_width; + data_size -= data_width; + } +} +#endif + +void +AndroidSystem::setup_environment () noexcept +{ + if (application_config.environment_variable_count % 2 != 0) { + log_warn (LOG_DEFAULT, "Corrupted environment variable array: does not contain an even number of entries ({})", application_config.environment_variable_count); + return; + } + + const char *var_name; + const char *var_value; + for (size_t i = 0uz; i < application_config.environment_variable_count; i += 2) { + var_name = app_environment_variables [i]; + if (var_name == nullptr || *var_name == '\0') { + continue; + } + + var_value = app_environment_variables [i + 1uz]; + if (var_value == nullptr) { + var_value = ""; + } + + if constexpr (Constants::IsDebugBuild) { + log_info (LOG_DEFAULT, "Setting environment variable '{}' to '{}'", var_name, var_value); + } + + if (setenv (var_name, var_value, 1) < 0) { + log_warn (LOG_DEFAULT, "Failed to set environment variable: {}", strerror (errno)); + } + } + +#if defined(DEBUG) + log_debug (LOG_DEFAULT, "Loading environment from the override directory."sv); + + dynamic_local_string env_override_file; + Util::path_combine (env_override_file, std::string_view {primary_override_dir}, Constants::OVERRIDE_ENVIRONMENT_FILE_NAME); + log_debug (LOG_DEFAULT, "{}", env_override_file.get ()); + if (Util::file_exists (env_override_file)) { + log_debug (LOG_DEFAULT, "Loading {}"sv, env_override_file.get ()); + setup_environment_from_override_file (env_override_file); + } +#endif // def DEBUG +} + void AndroidSystem::detect_embedded_dso_mode (jstring_array_wrapper& appDirs) noexcept { @@ -25,22 +198,21 @@ AndroidSystem::detect_embedded_dso_mode (jstring_array_wrapper& appDirs) noexcep log_debug (LOG_ASSEMBLY, "Native libs extracted to {}, assuming application/android:extractNativeLibs == true", appDirs[Constants::APP_DIRS_DATA_DIR_INDEX].get_cstr ()); set_embedded_dso_mode_enabled (false); } - - Util::path_combine (libmonodroid_path, "first_part"sv, "second_part"sv, "third_part"sv, "file.txt"sv); - log_warn (LOG_DEFAULT, "path_combine test: {}", libmonodroid_path.get ()); } auto AndroidSystem::lookup_system_property (std::string_view const& name, size_t &value_len) noexcept -> const char* { value_len = 0; -// #if defined (DEBUG) -// BundledProperty *p = lookup_system_property (name); -// if (p != nullptr) { -// value_len = p->value_len; -// return p->name; -// } -// #endif // DEBUG || !ANDROID +#if defined (DEBUG) + if (!bundled_properties.empty ()) { + auto prop_iter = bundled_properties.find (name.data ()); + if (prop_iter != bundled_properties.end ()) { + value_len = prop_iter->second.length (); + return prop_iter->first.c_str (); + } + } +#endif // DEBUG if (application_config.system_property_count == 0) { return nullptr; diff --git a/src/native-clr/xamarin-app-stub/application_dso_stub.cc b/src/native-clr/xamarin-app-stub/application_dso_stub.cc index e9a8bf35235..2a34ff4c13d 100644 --- a/src/native-clr/xamarin-app-stub/application_dso_stub.cc +++ b/src/native-clr/xamarin-app-stub/application_dso_stub.cc @@ -62,6 +62,7 @@ const ApplicationConfig application_config = { .android_package_name = android_package_name, }; +// TODO: migrate to std::string_view for these two const char* const app_environment_variables[] = {}; const char* const app_system_properties[] = {};