From 00cddbb9bc9667ada61dc420163cd488f6f19655 Mon Sep 17 00:00:00 2001 From: Elinor Fung Date: Tue, 25 Feb 2025 21:39:18 -0800 Subject: [PATCH] Make AndroidSampleApp use host_runtime_contact::external_assembly_probe --- .../sample/Android/AndroidSampleApp.csproj | 1 + .../Templates/monodroid-coreclr.c | 100 +++++++++++++++--- 2 files changed, 84 insertions(+), 17 deletions(-) diff --git a/src/mono/sample/Android/AndroidSampleApp.csproj b/src/mono/sample/Android/AndroidSampleApp.csproj index fed0625f246c35..74ce1168a1ab57 100644 --- a/src/mono/sample/Android/AndroidSampleApp.csproj +++ b/src/mono/sample/Android/AndroidSampleApp.csproj @@ -19,6 +19,7 @@ + diff --git a/src/tasks/AndroidAppBuilder/Templates/monodroid-coreclr.c b/src/tasks/AndroidAppBuilder/Templates/monodroid-coreclr.c index 210b8025312ec3..a6047658415179 100644 --- a/src/tasks/AndroidAppBuilder/Templates/monodroid-coreclr.c +++ b/src/tasks/AndroidAppBuilder/Templates/monodroid-coreclr.c @@ -16,6 +16,8 @@ #include #include +#include + /********* exported symbols *********/ /* JNI exports */ @@ -34,11 +36,15 @@ Java_net_dot_MonoRunner_freeNativeResources (JNIEnv* env, jobject thiz); /********* implementation *********/ -static const char* g_bundle_path = NULL; +static char* g_bundle_path = NULL; static const char* g_executable_path = NULL; static unsigned int g_coreclr_domainId = 0; static void* g_coreclr_handle = NULL; +#define MAX_MAPPED_COUNT 50 // Arbitrarily 'large enough' number +static void* g_mapped_files[MAX_MAPPED_COUNT]; +static size_t g_mapped_file_sizes[MAX_MAPPED_COUNT]; +static unsigned int g_mapped_files_count = 0; #define LOG_INFO(fmt, ...) __android_log_print(ANDROID_LOG_DEBUG, "DOTNET", fmt, ##__VA_ARGS__) #define LOG_ERROR(fmt, ...) __android_log_print(ANDROID_LOG_ERROR, "DOTNET", fmt, ##__VA_ARGS__) @@ -70,7 +76,7 @@ strncpy_str (JNIEnv *env, char *buff, jstring str, int nbuff) /* * Get the list of trusted assemblies from a specified @dir_path. -* The path is searched for .dll files which when found are concatenated +* The path is searched for .dll files which when found are concatenated * to the output string @tpas separated by ':'. * The output string should be freed by the caller. * The return value is the length of the output string. @@ -147,6 +153,56 @@ bundle_executable_path (const char* executable, const char* bundle_path, const c return executable_path_len; } +static bool +external_assembly_probe(const char* name, void** data, int64_t* size) +{ + if (g_mapped_files_count >= MAX_MAPPED_COUNT) + { + LOG_ERROR("Too many mapped files, cannot map %s", name); + return false; + } + + // Get just the file name + const char* pos = strrchr(name, '/'); + if (pos != NULL) + name = pos + 1; + + // Look in the bundle path where the files were extracted + char full_path[1024]; + size_t path_len = strlen(g_bundle_path) + strlen(name) + 1; // +1 for '/' + size_t res = snprintf(full_path, path_len + 1, "%s/%s", g_bundle_path, name); + if (res < 0 || res != path_len) + return false; + + int fd = open(full_path, O_RDONLY); + if (fd == -1) + return false; + + struct stat buf; + if (fstat(fd, &buf) == -1) + { + close(fd); + return false; + } + + int64_t size_local = buf.st_size; + void* mapped = mmap(NULL, size_local, PROT_READ, MAP_PRIVATE, fd, 0); + if (mapped == MAP_FAILED) + { + close(fd); + return false; + } + + LOG_INFO("Mapped %s -> %s", name, full_path); + g_mapped_files[g_mapped_files_count] = mapped; + g_mapped_file_sizes[g_mapped_files_count] = size_local; + g_mapped_files_count++; + close(fd); + *data = mapped; + *size = size_local; + return true; +} + static void free_resources () { @@ -166,9 +222,13 @@ free_resources () coreclr_shutdown (g_coreclr_handle, g_coreclr_domainId); g_coreclr_handle = NULL; } + for (int i = 0; i < g_mapped_files_count; ++i) + { + munmap (g_mapped_files[i], g_mapped_file_sizes[i]); + } } -static int +static int mono_droid_execute_assembly (const char* executable_path, void* coreclr_handle, unsigned int coreclr_domainId, int managed_argc, const char** managed_argv) { unsigned int rv; @@ -178,6 +238,8 @@ mono_droid_execute_assembly (const char* executable_path, void* coreclr_handle, return rv; } +#define PROPERTY_COUNT 3 + static int mono_droid_runtime_init (const char* executable) { @@ -198,34 +260,38 @@ mono_droid_runtime_init (const char* executable) chdir (g_bundle_path); - // TODO: set TRUSTED_PLATFORM_ASSEMBLIES, APP_PATHS and NATIVE_DLL_SEARCH_DIRECTORIES + struct host_runtime_contract host_contract = { + sizeof(struct host_runtime_contract), + NULL, // context + NULL, // get_runtime_property + NULL, // bundle_proble + NULL, // pinvoke_override + &external_assembly_probe }; - const char* appctx_keys[3]; + const char* appctx_keys[PROPERTY_COUNT]; appctx_keys[0] = "RUNTIME_IDENTIFIER"; appctx_keys[1] = "APP_CONTEXT_BASE_DIRECTORY"; - appctx_keys[2] = "TRUSTED_PLATFORM_ASSEMBLIES"; + appctx_keys[2] = "HOST_RUNTIME_CONTRACT"; - const char* appctx_values[3]; + const char* appctx_values[PROPERTY_COUNT]; appctx_values[0] = ANDROID_RUNTIME_IDENTIFIER; appctx_values[1] = g_bundle_path; - size_t tpas_len = get_tpas_from_path(g_bundle_path, &appctx_values[2]); - if (tpas_len < 1) - { - LOG_ERROR("Failed to get trusted assemblies from path: %s", g_bundle_path); - return -1; - } + + char contract_str[19]; // 0x + 16 hex digits + '\0' + snprintf(contract_str, 19, "0x%zx", (size_t)(&host_contract)); + appctx_values[2] = contract_str; LOG_INFO ("Calling coreclr_initialize"); int rv = coreclr_initialize ( g_executable_path, executable, - 3, + PROPERTY_COUNT, appctx_keys, appctx_values, &g_coreclr_handle, &g_coreclr_domainId ); - LOG_INFO ("coreclr_initialize returned %d", rv); + LOG_INFO ("coreclr_initialize returned 0x%x", rv); return rv; } @@ -237,7 +303,7 @@ Java_net_dot_MonoRunner_setEnv (JNIEnv* env, jobject thiz, jstring j_key, jstrin const char *key = (*env)->GetStringUTFChars(env, j_key, 0); const char *val = (*env)->GetStringUTFChars(env, j_value, 0); - + LOG_INFO ("Setting env: %s=%s", key, val); setenv (key, val, true); (*env)->ReleaseStringUTFChars(env, j_key, key); @@ -270,7 +336,7 @@ int Java_net_dot_MonoRunner_execEntryPoint (JNIEnv* env, jobject thiz, jstring j_entryPointLibName, jobjectArray j_args) { LOG_INFO("Java_net_dot_MonoRunner_execEntryPoint (CoreCLR):"); - + if ((g_bundle_path == NULL) || (g_executable_path == NULL)) { LOG_ERROR("Bundle path or executable path not set");