From 7a962fdd819d1ea9b11016e3a52e97a9b2e0029b Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Mon, 29 Jul 2024 20:34:57 +0200 Subject: [PATCH] Restore changes that somehow went AWOL... ...and caused the ILStrip tests to fail. Doh. --- .../pinvoke-override-api-impl.hh | 4 +- src/native/runtime-base/monodroid-dl.hh | 66 +++++++++++++++++-- 2 files changed, 64 insertions(+), 6 deletions(-) diff --git a/src/native/pinvoke-override/pinvoke-override-api-impl.hh b/src/native/pinvoke-override/pinvoke-override-api-impl.hh index 9e14dc14ac4..e796a7f6ef8 100644 --- a/src/native/pinvoke-override/pinvoke-override-api-impl.hh +++ b/src/native/pinvoke-override/pinvoke-override-api-impl.hh @@ -19,7 +19,9 @@ namespace xamarin::android { void *lib_handle = dso_handle == nullptr ? nullptr : *dso_handle; if (lib_handle == nullptr) { - lib_handle = internal::MonodroidDl::monodroid_dlopen (library_name, MONO_DL_LOCAL, nullptr, nullptr); + // We're being called as part of the p/invoke mechanism, we don't need to look in the AOT cache + constexpr bool USE_AOT_CACHE = false; + lib_handle = internal::MonodroidDl::monodroid_dlopen (library_name, MONO_DL_LOCAL, nullptr, USE_AOT_CACHE); if (lib_handle == nullptr) { log_warn (LOG_ASSEMBLY, "Shared library '%s' not loaded, p/invoke '%s' may fail", library_name, symbol_name); return nullptr; diff --git a/src/native/runtime-base/monodroid-dl.hh b/src/native/runtime-base/monodroid-dl.hh index 4c9143e537e..cc88f926596 100644 --- a/src/native/runtime-base/monodroid-dl.hh +++ b/src/native/runtime-base/monodroid-dl.hh @@ -29,18 +29,65 @@ namespace xamarin::android::internal return lflags; } - static DSOCacheEntry* find_dso_cache_entry (hash_t hash) noexcept + template + [[gnu::always_inline, gnu::flatten]] + static DSOCacheEntry* find_dso_cache_entry_common (hash_t hash) noexcept { + DSOCacheEntry *arr; + size_t arr_size; + + if constexpr (AotCache) { + log_debug (LOG_ASSEMBLY, "Looking for hash 0x%x in AOT cache", hash); + arr = aot_dso_cache; + arr_size = application_config.number_of_aot_cache_entries; + } else { + log_debug (LOG_ASSEMBLY, "Looking for hash 0x%x in DSO cache", hash); + arr = dso_cache; + arr_size = application_config.number_of_dso_cache_entries; + } + auto equal = [](DSOCacheEntry const& entry, hash_t key) -> bool { return entry.hash == key; }; auto less_than = [](DSOCacheEntry const& entry, hash_t key) -> bool { return entry.hash < key; }; - ssize_t idx = Search::binary_search (hash, dso_cache, application_config.number_of_dso_cache_entries); + ssize_t idx = Search::binary_search (hash, arr, arr_size); + if (idx >= 0) { - return &dso_cache[idx]; + return &arr[idx]; } return nullptr; } + [[gnu::always_inline, gnu::flatten]] + static DSOCacheEntry* find_only_aot_cache_entry (hash_t hash) noexcept + { + constexpr bool IsAotCache = true; + return find_dso_cache_entry_common (hash); + } + + [[gnu::always_inline, gnu::flatten]] + static DSOCacheEntry* find_only_dso_cache_entry (hash_t hash) noexcept + { + constexpr bool IsAotCache = false; + return find_dso_cache_entry_common (hash); + } + + [[gnu::always_inline, gnu::flatten]] + static DSOCacheEntry* find_any_dso_cache_entry (hash_t hash) noexcept + { + // If we're asked to look in the AOT DSO cache, do it first. This is because we're likely called from the + // MonoVM's dlopen fallback handler and it will not be a request to resolved a p/invoke, but most likely to + // find and load an AOT image for a managed assembly. Since there might be naming/hash conflicts in this + // scenario, we look at the AOT cache first. + // + // See: https://github.com/dotnet/android/issues/9081 + DSOCacheEntry *ret = find_only_aot_cache_entry (hash); + if (ret != nullptr) { + return ret; + } + + return find_only_dso_cache_entry (hash); + } + static void* monodroid_dlopen_log_and_return (void *handle, char **err, const char *full_name, bool free_memory) { if (handle == nullptr && err != nullptr) { @@ -103,7 +150,7 @@ namespace xamarin::android::internal public: [[gnu::flatten]] - static void* monodroid_dlopen (const char *name, int flags, char **err, [[maybe_unused]] void *user_data) noexcept + static void* monodroid_dlopen (const char *name, int flags, char **err, bool use_aot_cache) noexcept { if (name == nullptr) { log_warn (LOG_ASSEMBLY, "monodroid_dlopen got a null name. This is not supported in NET+"); @@ -112,7 +159,7 @@ namespace xamarin::android::internal 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); - DSOCacheEntry *dso = find_dso_cache_entry (name_hash); + DSOCacheEntry *dso = use_aot_cache ? find_any_dso_cache_entry (name_hash) : 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); if (dso == nullptr) { @@ -161,6 +208,15 @@ namespace xamarin::android::internal return monodroid_dlopen_log_and_return (dso->handle, err, name, false /* name_needs_free */); } + [[gnu::flatten]] + static void* monodroid_dlopen (const char *name, int flags, char **err, [[maybe_unused]] void *user_data) noexcept + { + // We're called by MonoVM via a callback, we might need to return an AOT DSO. + // See: https://github.com/dotnet/android/issues/9081 + constexpr bool USE_AOT_CACHE = true; + return monodroid_dlopen (name, flags, err, USE_AOT_CACHE); + } + [[gnu::flatten]] static void* monodroid_dlsym (void *handle, const char *name, char **err, [[maybe_unused]] void *user_data) {