diff --git a/dotnet/targets/Xamarin.Shared.Sdk.props b/dotnet/targets/Xamarin.Shared.Sdk.props index 38d185fb27fd..3d078f69feec 100644 --- a/dotnet/targets/Xamarin.Shared.Sdk.props +++ b/dotnet/targets/Xamarin.Shared.Sdk.props @@ -213,6 +213,23 @@ true + + + true + true + macho + true + + + + + + + + + <_BundlerEnvironmentVariables Include="DOTNET_ReadyToRun" Value="0" /> + + <_SdkIsSimulator Condition="'$(RuntimeIdentifier)' != '' And '$(_SdkIsSimulator)' == ''">$(RuntimeIdentifier.Contains('simulator')) diff --git a/dotnet/targets/Xamarin.Shared.Sdk.targets b/dotnet/targets/Xamarin.Shared.Sdk.targets index b997fbac4bf3..890feeb0d8de 100644 --- a/dotnet/targets/Xamarin.Shared.Sdk.targets +++ b/dotnet/targets/Xamarin.Shared.Sdk.targets @@ -1246,13 +1246,14 @@ '%(ResolvedFileToPublish.NuGetPackageId)' == '$(_MonoNugetPackageId)' " /> - - - - - - <_BundlerEnvironmentVariables Include="DOTNET_Interpreter" Value="%2A%21%2A" /> - <_BundlerEnvironmentVariables Include="DOTNET_ReadyToRun" Value="0" /> + + <_MonoLibrary + Remove="@(_MonoLibrary)" + Condition=" '$(_XamarinRuntime)' == 'CoreCLR' And + '$(_PlatformName)' != 'macOS' And + '%(Filename)' == 'libclrjit' + " + /> @@ -2095,6 +2096,19 @@ + + + + + + + <_Crossgen2Path Condition="'$(Crossgen2Path)' != ''">$(Crossgen2Path) + <_Crossgen2Path Condition="'$(Crossgen2Path)' == ''">$([MSBuild]::NormalizePath('$(MSBuildThisFileDirectory)', '..', '..', 'packs', 'Microsoft.NETCore.App.Runtime.$(_PlatformName.ToLowerInvariant())-$(RuntimeIdentifier.Split('-')[1])', '$(BundledNETCoreAppPackageVersion)', 'tools', 'crossgen2')) + + <_TargetArch>$(RuntimeIdentifier.Split('-')[1]) + <_TargetOS>$(RuntimeIdentifier.Split('-')[0]) + + + + + + + + + + + + diff --git a/runtime/.gitignore b/runtime/.gitignore index 075909938859..cb42427f6eca 100644 --- a/runtime/.gitignore +++ b/runtime/.gitignore @@ -12,3 +12,4 @@ bindings-generated.m *.dylib *.o coreclrhost.h +host_runtime_contract.h \ No newline at end of file diff --git a/runtime/Makefile b/runtime/Makefile index d5348366632c..ca26775c7da1 100644 --- a/runtime/Makefile +++ b/runtime/Makefile @@ -35,10 +35,14 @@ IOS_SIMULATOR_ARCHITECTURES+=x86_64 IOS_DEVICE_ARCHITECTURES+=arm64 coreclrhost.h: Makefile - $(Q_CURL) curl -L --retry 3 --retry-all-errors --fail --output "$@.tmp" https://raw.githubusercontent.com/dotnet/runtime/f1b8d5a4448d072c9d390744777a87921e45bf2f/src/coreclr/hosts/inc/coreclrhost.h + $(Q_CURL) curl -L --retry 3 --retry-all-errors --fail --output "$@.tmp" https://raw.githubusercontent.com/dotnet/runtime/main/src/coreclr/hosts/inc/coreclrhost.h $(Q) mv "$@.tmp" "$@" -coreclr-bridge.m: coreclrhost.h +host_runtime_contract.h: Makefile + $(Q_CURL) curl -L --retry 3 --retry-all-errors --fail --output "$@.tmp" https://raw.githubusercontent.com/dotnet/runtime/main/src/native/corehost/host_runtime_contract.h + $(Q) mv "$@.tmp" "$@" + +coreclr-bridge.m: coreclrhost.h host_runtime_contract.h xamarin/mono-runtime.h: mono-runtime.h.t4 exports.t4 $(Q_GEN) $(TT) $< -o $@ diff --git a/runtime/coreclr-bridge.m b/runtime/coreclr-bridge.m index 8554e64980c9..2d39b09b4564 100644 --- a/runtime/coreclr-bridge.m +++ b/runtime/coreclr-bridge.m @@ -339,7 +339,7 @@ { struct TrackedObjectInfo *info = (struct TrackedObjectInfo *) ptr; info->data->flags = (enum NSObjectFlags) (info->data->flags | NSObjectFlagsInFinalizerQueue); - LOG_CORECLR (stderr, "%s (%p) flags: %i\n", __func__, ptr, (int) info->flags); + LOG_CORECLR (stderr, "%s (%p) flags: %i\n", __func__, ptr, (int) info->data->flags); } void @@ -492,6 +492,7 @@ xamarin_bridge_compute_properties (propertyCount, propertyKeys, propertyValues, &combinedPropertyCount, &combinedPropertyKeys, &combinedPropertyValues); const char *executablePath = [[[[NSBundle mainBundle] executableURL] path] UTF8String]; + rv = coreclr_initialize ( executablePath, xamarin_executable_name, diff --git a/runtime/runtime.m b/runtime/runtime.m index fc0dedb34290..b7da178c124f 100644 --- a/runtime/runtime.m +++ b/runtime/runtime.m @@ -11,6 +11,8 @@ #include #include #include +#include +#include #include "product.h" #include "shared.h" @@ -22,6 +24,7 @@ #include "xamarin/monovm-bridge.h" #else #include "xamarin/coreclr-bridge.h" +#include "host_runtime_contract.h" #endif #if defined (DEBUG) @@ -2436,10 +2439,99 @@ -(struct NSObjectData*) xamarinGetNSObjectData; return rv; } +#if defined (CORECLR_RUNTIME) +size_t get_image_size(void* base_address) +{ + uint32_t image_count = _dyld_image_count(); + for (uint32_t i = 0; i < image_count; ++i) + { + const struct mach_header_64* header = (const struct mach_header_64*)_dyld_get_image_header(i); + if ((const void*)header != base_address) + continue; + + const struct load_command* cmd = (const struct load_command*)((const char*)header + sizeof(struct mach_header_64)); + + size_t image_size = 0; + for (uint32_t j = 0; j < header->ncmds; ++j) + { + if (cmd->cmd == LC_SEGMENT_64) + { + const struct segment_command_64* seg = (const struct segment_command_64*)cmd; + size_t end_addr = (size_t)(seg->vmaddr + seg->vmsize); + if (end_addr > image_size) + image_size = end_addr; + } + + cmd = (const struct load_command*)((const char*)cmd + cmd->cmdsize); + } + + return image_size; + } + + return 0; +} + +bool get_native_code_data(const struct host_runtime_contract_native_code_context* context, struct host_runtime_contract_native_code_data* data) +{ + if (!context || !data || !context->assembly_path || !context->owner_composite_name) + return false; + + // Look for the owner composite R2R image in the same directory as the assembly + char r2r_path[PATH_MAX]; + const char *last_slash = strrchr(context->assembly_path, '/'); + size_t dir_len = last_slash ? (size_t)(last_slash - context->assembly_path) : 0; + if (dir_len >= sizeof(r2r_path) - 1) + return false; + + strncpy(r2r_path, context->assembly_path, dir_len); + int written = snprintf(r2r_path + dir_len, sizeof(r2r_path) - dir_len, "/%s", context->owner_composite_name); + if (written <= 0 || (size_t)written >= sizeof(r2r_path) - dir_len) + return false; + + void* handle = dlopen(r2r_path, RTLD_LAZY | RTLD_LOCAL); + if (handle == NULL) { + return false; + } + + void* r2r_header = dlsym(handle, "RTR_HEADER"); + if (r2r_header == NULL) + { + dlclose(handle); + return false; + } + + Dl_info info; + if (dladdr(r2r_header, &info) == 0) + { + dlclose(handle); + return false; + } + + data->size = sizeof(struct host_runtime_contract_native_code_data); + data->r2r_header_ptr = r2r_header; + data->image_size = get_image_size(info.dli_fbase); + data->image_base = info.dli_fbase; + + return true; +} +#endif // defined (CORECLR_RUNTIME) + void xamarin_vm_initialize () { +#if defined (CORECLR_RUNTIME) + struct host_runtime_contract host_contract = { + .size = sizeof(struct host_runtime_contract), + .pinvoke_override = &xamarin_pinvoke_override, + .get_native_code_data = &get_native_code_data + }; + + char contract_str[19]; // 0x + 16 hex digits + '\0' + snprintf(contract_str, 19, "0x%zx", (size_t)(&host_contract)); +#else char *pinvokeOverride = xamarin_strdup_printf ("%p", &xamarin_pinvoke_override); +#endif + char *trusted_platform_assemblies = xamarin_compute_trusted_platform_assemblies (); char *native_dll_search_directories = xamarin_compute_native_dll_search_directories (); @@ -2447,18 +2539,22 @@ -(struct NSObjectData*) xamarinGetNSObjectData; // for the _CreateRuntimeConfiguration target in dotnet/targets/Xamarin.Shared.Sdk.targets. const char *propertyKeys[] = { "APP_CONTEXT_BASE_DIRECTORY", // path to where the managed assemblies are (usually at least - RID-specific assemblies will be in subfolders) - "APP_PATHS", +#if defined (CORECLR_RUNTIME) + "HOST_RUNTIME_CONTRACT", +#else "PINVOKE_OVERRIDE", +#endif "TRUSTED_PLATFORM_ASSEMBLIES", - "NATIVE_DLL_SEARCH_DIRECTORIES", "RUNTIME_IDENTIFIER", }; const char *propertyValues[] = { xamarin_get_bundle_path (), - xamarin_get_bundle_path (), +#if defined (CORECLR_RUNTIME) + contract_str, +#else pinvokeOverride, +#endif trusted_platform_assemblies, - native_dll_search_directories, RUNTIMEIDENTIFIER, }; static_assert (sizeof (propertyKeys) == sizeof (propertyValues), "The number of keys and values must be the same."); @@ -2466,7 +2562,9 @@ -(struct NSObjectData*) xamarinGetNSObjectData; int propertyCount = (int) (sizeof (propertyValues) / sizeof (propertyValues [0])); bool rv = xamarin_bridge_vm_initialize (propertyCount, propertyKeys, propertyValues); +#if !defined (CORECLR_RUNTIME) xamarin_free (pinvokeOverride); +#endif xamarin_free (trusted_platform_assemblies); xamarin_free (native_dll_search_directories); @@ -2502,7 +2600,7 @@ -(struct NSObjectData*) xamarinGetNSObjectData; return rv; } -void* +const void* xamarin_pinvoke_override (const char *libraryName, const char *entrypointName) { diff --git a/runtime/xamarin/runtime.h b/runtime/xamarin/runtime.h index 54b8b878f01a..90566324d0e2 100644 --- a/runtime/xamarin/runtime.h +++ b/runtime/xamarin/runtime.h @@ -220,7 +220,7 @@ MonoAssembly* xamarin_assembly_preload_hook (MonoAssemblyName *aname, char **ass void xamarin_handle_bridge_exception (GCHandle gchandle, const char *method); void xamarin_vm_initialize (); bool xamarin_bridge_vm_initialize (int propertyCount, const char **propertyKeys, const char **propertyValues); -void* xamarin_pinvoke_override (const char *libraryName, const char *entrypointName); +const void* xamarin_pinvoke_override (const char *libraryName, const char *entrypointName); void xamarin_bridge_call_runtime_initialize (struct InitializationOptions* options, GCHandle* exception_gchandle); void xamarin_bridge_register_product_assembly (GCHandle* exception_gchandle); MonoMethod * xamarin_bridge_get_mono_method (MonoReflectionMethod *method);