@@ -29,18 +29,65 @@ namespace xamarin::android::internal
2929 return lflags;
3030 }
3131
32- static DSOCacheEntry* find_dso_cache_entry (hash_t hash) noexcept
32+ template <bool AotCache>
33+ [[gnu::always_inline, gnu::flatten]]
34+ static DSOCacheEntry* find_dso_cache_entry_common (hash_t hash) noexcept
3335 {
36+ DSOCacheEntry *arr;
37+ size_t arr_size;
38+
39+ if constexpr (AotCache) {
40+ log_debug (LOG_ASSEMBLY, " Looking for hash 0x%x in AOT cache" , hash);
41+ arr = aot_dso_cache;
42+ arr_size = application_config.number_of_aot_cache_entries ;
43+ } else {
44+ log_debug (LOG_ASSEMBLY, " Looking for hash 0x%x in DSO cache" , hash);
45+ arr = dso_cache;
46+ arr_size = application_config.number_of_dso_cache_entries ;
47+ }
48+
3449 auto equal = [](DSOCacheEntry const & entry, hash_t key) -> bool { return entry.hash == key; };
3550 auto less_than = [](DSOCacheEntry const & entry, hash_t key) -> bool { return entry.hash < key; };
36- ssize_t idx = Search::binary_search<DSOCacheEntry, equal, less_than> (hash, dso_cache, application_config.number_of_dso_cache_entries );
51+ ssize_t idx = Search::binary_search<DSOCacheEntry, equal, less_than> (hash, arr, arr_size);
52+
3753 if (idx >= 0 ) {
38- return &dso_cache [idx];
54+ return &arr [idx];
3955 }
4056
4157 return nullptr ;
4258 }
4359
60+ [[gnu::always_inline, gnu::flatten]]
61+ static DSOCacheEntry* find_only_aot_cache_entry (hash_t hash) noexcept
62+ {
63+ constexpr bool IsAotCache = true ;
64+ return find_dso_cache_entry_common<IsAotCache> (hash);
65+ }
66+
67+ [[gnu::always_inline, gnu::flatten]]
68+ static DSOCacheEntry* find_only_dso_cache_entry (hash_t hash) noexcept
69+ {
70+ constexpr bool IsAotCache = false ;
71+ return find_dso_cache_entry_common<IsAotCache> (hash);
72+ }
73+
74+ [[gnu::always_inline, gnu::flatten]]
75+ static DSOCacheEntry* find_any_dso_cache_entry (hash_t hash) noexcept
76+ {
77+ // If we're asked to look in the AOT DSO cache, do it first. This is because we're likely called from the
78+ // MonoVM's dlopen fallback handler and it will not be a request to resolved a p/invoke, but most likely to
79+ // find and load an AOT image for a managed assembly. Since there might be naming/hash conflicts in this
80+ // scenario, we look at the AOT cache first.
81+ //
82+ // See: https://github.com/dotnet/android/issues/9081
83+ DSOCacheEntry *ret = find_only_aot_cache_entry (hash);
84+ if (ret != nullptr ) {
85+ return ret;
86+ }
87+
88+ return find_only_dso_cache_entry (hash);
89+ }
90+
4491 static void * monodroid_dlopen_log_and_return (void *handle, char **err, const char *full_name, bool free_memory)
4592 {
4693 if (handle == nullptr && err != nullptr ) {
@@ -103,7 +150,7 @@ namespace xamarin::android::internal
103150
104151 public:
105152 [[gnu::flatten]]
106- static void * monodroid_dlopen (const char *name, int flags, char **err, [[maybe_unused]] void *user_data ) noexcept
153+ static void * monodroid_dlopen (const char *name, int flags, char **err, bool use_aot_cache ) noexcept
107154 {
108155 if (name == nullptr ) {
109156 log_warn (LOG_ASSEMBLY, " monodroid_dlopen got a null name. This is not supported in NET+" );
@@ -112,7 +159,7 @@ namespace xamarin::android::internal
112159
113160 hash_t name_hash = xxhash::hash (name, strlen (name));
114161 log_debug (LOG_ASSEMBLY, " monodroid_dlopen: hash for name '%s' is 0x%zx" , name, name_hash);
115- DSOCacheEntry *dso = find_dso_cache_entry (name_hash);
162+ DSOCacheEntry *dso = use_aot_cache ? find_any_dso_cache_entry (name_hash) : find_only_dso_cache_entry (name_hash);
116163 log_debug (LOG_ASSEMBLY, " monodroid_dlopen: hash match %sfound, DSO name is '%s'" , dso == nullptr ? " not " : " " , dso == nullptr ? " <unknown>" : dso->name );
117164
118165 if (dso == nullptr ) {
@@ -161,6 +208,15 @@ namespace xamarin::android::internal
161208 return monodroid_dlopen_log_and_return (dso->handle , err, name, false /* name_needs_free */ );
162209 }
163210
211+ [[gnu::flatten]]
212+ static void * monodroid_dlopen (const char *name, int flags, char **err, [[maybe_unused]] void *user_data) noexcept
213+ {
214+ // We're called by MonoVM via a callback, we might need to return an AOT DSO.
215+ // See: https://github.com/dotnet/android/issues/9081
216+ constexpr bool USE_AOT_CACHE = true ;
217+ return monodroid_dlopen (name, flags, err, USE_AOT_CACHE);
218+ }
219+
164220 [[gnu::flatten]]
165221 static void * monodroid_dlsym (void *handle, const char *name, char **err, [[maybe_unused]] void *user_data)
166222 {
0 commit comments