Skip to content

Commit d759388

Browse files
committed
Add ReadyToRun support for CoreCLR and update related configurations
- Introduced ReadyToRun configuration in Xamarin.Shared.Sdk.props. - Updated bundler environment variables in Xamarin.Shared.Sdk.targets to support ReadyToRun. - Added host_runtime_contract.h to the build process in Makefile. - Updated coreclr-bridge.m and runtime.m for R2R image handling and logging. - Updated runtime.h to reflect changes in the xamarin_pinvoke_override function signature.
1 parent d6afe37 commit d759388

File tree

7 files changed

+178
-12
lines changed

7 files changed

+178
-12
lines changed

dotnet/targets/Xamarin.Shared.Sdk.props

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,12 @@
213213
<CustomNativeMain Condition="'$(OutputType)' == 'Exe'">true</CustomNativeMain>
214214
</PropertyGroup>
215215

216+
<!-- ReadyToRun configuration for CoreCLR -->
217+
<PropertyGroup Condition="'$(UseMonoRuntime)' != 'true' And '$(PublishReadyToRun)' == 'true'">
218+
<PublishReadyToRunComposite>true</PublishReadyToRunComposite>
219+
<PublishReadyToRunContainerFormat>macho</PublishReadyToRunContainerFormat>
220+
</PropertyGroup>
221+
216222
<!-- Compute _SdkIsSimulator from the RuntimeIdentifier -->
217223
<PropertyGroup>
218224
<_SdkIsSimulator Condition="'$(RuntimeIdentifier)' != '' And '$(_SdkIsSimulator)' == ''">$(RuntimeIdentifier.Contains('simulator'))</_SdkIsSimulator>

dotnet/targets/Xamarin.Shared.Sdk.targets

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1250,9 +1250,10 @@
12501250

12511251
<!-- CoreCLR: these are variables currently needed to make CoreCLR work -->
12521252
<ItemGroup Condition="'$(UseMonoRuntime)' == 'false' And '$(_PlatformName)' != 'macOS'">
1253-
<!-- Only the interpreter works so far, so make sure only the interpreter executes and that everything is executed with the interpreter -->
1253+
<!-- TODO: Remove DOTNET_Interpreter -->
12541254
<_BundlerEnvironmentVariables Include="DOTNET_Interpreter" Value="%2A%21%2A" /> <!-- This is the string "*!*" url encoded -->
1255-
<_BundlerEnvironmentVariables Include="DOTNET_ReadyToRun" Value="0" />
1255+
<_BundlerEnvironmentVariables Include="DOTNET_ReadyToRun" Value="1" Condition="'$(PublishReadyToRun)' == 'true'" />
1256+
<_BundlerEnvironmentVariables Include="DOTNET_ReadyToRun" Value="0" Condition="'$(PublishReadyToRun)' != 'true'" />
12561257
</ItemGroup>
12571258
</Target>
12581259

@@ -2753,4 +2754,27 @@ global using nfloat = global::System.Runtime.InteropServices.NFloat%3B
27532754
<Import Project="dotnet-xcsync.targets" />
27542755
<Import Project="Microsoft.MaciOS.Sdk.Xcode.targets" />
27552756

2757+
<!-- TODO: Remove ResolveReadyToRunCompilers target -->
2758+
<Target Name="ResolveReadyToRunCompilers" Condition="'$(PublishReadyToRun)' == 'true' And '$(UseMonoRuntime)' != 'true'">
2759+
<PropertyGroup>
2760+
<_Crossgen2Path Condition="'$(Crossgen2Path)' != ''">$(Crossgen2Path)</_Crossgen2Path>
2761+
<_Crossgen2Path Condition="'$(Crossgen2Path)' == ''">$([MSBuild]::NormalizePath('$(MSBuildThisFileDirectory)', '..', '..', 'packs', 'Microsoft.NETCore.App.Runtime.$(_PlatformName.ToLowerInvariant())-$(RuntimeIdentifier.Split('-')[1])', '$(BundledNETCoreAppPackageVersion)', 'tools', 'crossgen2'))</_Crossgen2Path>
2762+
2763+
<_TargetArch>$(RuntimeIdentifier.Split('-')[1])</_TargetArch>
2764+
<_TargetOS>$(RuntimeIdentifier.Split('-')[0])</_TargetOS>
2765+
</PropertyGroup>
2766+
2767+
<ItemGroup>
2768+
<Crossgen2Tool Include="$(_Crossgen2Path)"
2769+
TargetArch="$(_TargetArch)"
2770+
TargetOS="$(_TargetOS)"
2771+
PerfmapFormatVersion="$(PublishReadyToRunPerfmapFormatVersion)"/>
2772+
</ItemGroup>
2773+
2774+
<Message Text="Using crossgen2: $(_Crossgen2Path)" Importance="high" />
2775+
<Message Text=" RuntimeIdentifier: $(RuntimeIdentifier)" Importance="high" />
2776+
<Message Text=" TargetArch: $(_TargetArch)" Importance="high" />
2777+
<Message Text=" TargetOS: $(_TargetOS)" Importance="high" />
2778+
</Target>
2779+
27562780
</Project>

runtime/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ bindings-generated.m
1212
*.dylib
1313
*.o
1414
coreclrhost.h
15+
host_runtime_contract.h

runtime/Makefile

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,14 @@ IOS_SIMULATOR_ARCHITECTURES+=x86_64
3535
IOS_DEVICE_ARCHITECTURES+=arm64
3636

3737
coreclrhost.h: Makefile
38-
$(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
38+
$(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
3939
$(Q) mv "$@.tmp" "$@"
4040

41-
coreclr-bridge.m: coreclrhost.h
41+
host_runtime_contract.h: Makefile
42+
$(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
43+
$(Q) mv "$@.tmp" "$@"
44+
45+
coreclr-bridge.m: coreclrhost.h host_runtime_contract.h
4246

4347
xamarin/mono-runtime.h: mono-runtime.h.t4 exports.t4
4448
$(Q_GEN) $(TT) $< -o $@

runtime/coreclr-bridge.m

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,7 @@
339339
{
340340
struct TrackedObjectInfo *info = (struct TrackedObjectInfo *) ptr;
341341
info->data->flags = (enum NSObjectFlags) (info->data->flags | NSObjectFlagsInFinalizerQueue);
342-
LOG_CORECLR (stderr, "%s (%p) flags: %i\n", __func__, ptr, (int) info->flags);
342+
LOG_CORECLR (stderr, "%s (%p) flags: %i\n", __func__, ptr, (int) info->data->flags);
343343
}
344344

345345
void
@@ -483,15 +483,29 @@
483483
bool
484484
xamarin_bridge_vm_initialize (int propertyCount, const char **propertyKeys, const char **propertyValues)
485485
{
486+
// TODO: Remove fprintf logs
487+
fprintf (stderr, "xamarin_bridge_vm_initialize: ENTRY propertyCount=%i\n", propertyCount);
486488
int rv;
487489

488490
int combinedPropertyCount = 0;
489491
const char **combinedPropertyKeys = NULL;
490492
const char **combinedPropertyValues = NULL;
491493

494+
fprintf (stderr, "xamarin_bridge_vm_initialize: calling xamarin_bridge_compute_properties\n");
492495
xamarin_bridge_compute_properties (propertyCount, propertyKeys, propertyValues, &combinedPropertyCount, &combinedPropertyKeys, &combinedPropertyValues);
496+
fprintf (stderr, "xamarin_bridge_vm_initialize: xamarin_bridge_compute_properties returned, combinedPropertyCount=%i\n", combinedPropertyCount);
493497

494498
const char *executablePath = [[[[NSBundle mainBundle] executableURL] path] UTF8String];
499+
500+
fprintf (stderr, "xamarin_vm_initialize: executablePath: %s\n", executablePath);
501+
fprintf (stderr, "xamarin_vm_initialize: xamarin_executable_name: %s\n", xamarin_executable_name);
502+
fprintf (stderr, "xamarin_vm_initialize: combinedPropertyCount: %i\n", combinedPropertyCount);
503+
for (int i = 0; i < combinedPropertyCount; i++) {
504+
fprintf (stderr, " Property[%i]: %s = %s\n", i, combinedPropertyKeys[i], combinedPropertyValues[i]);
505+
}
506+
fprintf (stderr, "xamarin_vm_initialize: calling coreclr_initialize\n");
507+
fprintf (stderr, "xamarin_vm_initialize: calling coreclr_initialize\n");
508+
495509
rv = coreclr_initialize (
496510
executablePath,
497511
xamarin_executable_name,
@@ -502,14 +516,16 @@
502516
&coreclr_domainId
503517
);
504518

519+
fprintf (stderr, "xamarin_vm_initialize: coreclr_initialize returned rv=%i\n", rv);
520+
505521
for (int i = 0; i < combinedPropertyCount; i++) {
506522
free ((void *) combinedPropertyKeys [i]);
507523
free ((void *) combinedPropertyValues [i]);
508524
}
509525
free ((void *) combinedPropertyKeys);
510526
free ((void *) combinedPropertyValues);
511527

512-
LOG_CORECLR (stderr, "xamarin_vm_initialize (%i, %p, %p): rv: %i domainId: %i handle: %p\n", combinedPropertyCount, combinedPropertyKeys, combinedPropertyValues, rv, coreclr_domainId, coreclr_handle);
528+
fprintf (stderr, "xamarin_vm_initialize (%i, %p, %p): rv: %i (0x%x) domainId: %i handle: %p\n", combinedPropertyCount, combinedPropertyKeys, combinedPropertyValues, rv, rv, coreclr_domainId, coreclr_handle);
513529

514530
return rv == 0;
515531
}

runtime/runtime.m

Lines changed: 120 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
#include <sys/stat.h>
1212
#include <dlfcn.h>
1313
#include <mach/mach.h>
14+
#include <mach-o/dyld.h>
15+
#include <mach-o/loader.h>
1416

1517
#include "product.h"
1618
#include "shared.h"
@@ -22,6 +24,7 @@
2224
#include "xamarin/monovm-bridge.h"
2325
#else
2426
#include "xamarin/coreclr-bridge.h"
27+
#include "host_runtime_contract.h"
2528
#endif
2629

2730
#if defined (DEBUG)
@@ -2436,37 +2439,149 @@ -(struct NSObjectData*) xamarinGetNSObjectData;
24362439
return rv;
24372440
}
24382441

2442+
#if defined (CORECLR_RUNTIME)
2443+
size_t get_image_size(void* base_address)
2444+
{
2445+
uint32_t image_count = _dyld_image_count();
2446+
for (uint32_t i = 0; i < image_count; ++i)
2447+
{
2448+
const struct mach_header_64* header = (const struct mach_header_64*)_dyld_get_image_header(i);
2449+
if ((const void*)header != base_address)
2450+
continue;
2451+
2452+
const struct load_command* cmd = (const struct load_command*)((const char*)header + sizeof(struct mach_header_64));
2453+
2454+
size_t image_size = 0;
2455+
for (uint32_t j = 0; j < header->ncmds; ++j)
2456+
{
2457+
if (cmd->cmd == LC_SEGMENT_64)
2458+
{
2459+
const struct segment_command_64* seg = (const struct segment_command_64*)cmd;
2460+
size_t end_addr = (size_t)(seg->vmaddr + seg->vmsize);
2461+
if (end_addr > image_size)
2462+
image_size = end_addr;
2463+
}
2464+
2465+
cmd = (const struct load_command*)((const char*)cmd + cmd->cmdsize);
2466+
}
2467+
2468+
return image_size;
2469+
}
2470+
2471+
return 0;
2472+
}
2473+
2474+
bool get_native_code_data(const struct host_runtime_contract_native_code_context* context, struct host_runtime_contract_native_code_data* data)
2475+
{
2476+
// TODO: Remove fprintf logs
2477+
fprintf (stderr, "R2R: get_native_code_data called for assembly: %s, composite: %s\n",
2478+
context ? context->assembly_path : "(null)",
2479+
context ? context->owner_composite_name : "(null)");
2480+
2481+
if (!context || !data || !context->assembly_path || !context->owner_composite_name)
2482+
return false;
2483+
2484+
// Look for the owner composite R2R image in the same directory as the assembly
2485+
char r2r_path[PATH_MAX];
2486+
const char *last_slash = strrchr(context->assembly_path, '/');
2487+
size_t dir_len = last_slash ? (size_t)(last_slash - context->assembly_path) : 0;
2488+
if (dir_len >= sizeof(r2r_path) - 1)
2489+
return false;
2490+
2491+
strncpy(r2r_path, context->assembly_path, dir_len);
2492+
int written = snprintf(r2r_path + dir_len, sizeof(r2r_path) - dir_len, "/%s", context->owner_composite_name);
2493+
if (written <= 0 || (size_t)written >= sizeof(r2r_path) - dir_len)
2494+
return false;
2495+
2496+
fprintf (stderr, "R2R: Attempting to load R2R image from: %s\n", r2r_path);
2497+
2498+
void* handle = dlopen(r2r_path, RTLD_LAZY | RTLD_LOCAL);
2499+
if (handle == NULL) {
2500+
fprintf (stderr, "R2R: Failed to dlopen R2R image: %s\n", dlerror ());
2501+
return false;
2502+
}
2503+
2504+
fprintf (stderr, "R2R: Successfully loaded R2R image, looking for RTR_HEADER symbol\n");
2505+
2506+
void* r2r_header = dlsym(handle, "RTR_HEADER");
2507+
if (r2r_header == NULL)
2508+
{
2509+
fprintf (stderr, "R2R: Failed to find RTR_HEADER symbol: %s\n", dlerror ());
2510+
dlclose(handle);
2511+
return false;
2512+
}
2513+
2514+
fprintf (stderr, "R2R: Found RTR_HEADER at %p\n", r2r_header);
2515+
2516+
Dl_info info;
2517+
if (dladdr(r2r_header, &info) == 0)
2518+
{
2519+
fprintf (stderr, "R2R: Failed to get dladdr info for RTR_HEADER\n");
2520+
dlclose(handle);
2521+
return false;
2522+
}
2523+
2524+
data->size = sizeof(struct host_runtime_contract_native_code_data);
2525+
data->r2r_header_ptr = r2r_header;
2526+
data->image_size = get_image_size(info.dli_fbase);
2527+
data->image_base = info.dli_fbase;
2528+
2529+
fprintf (stderr, "R2R: Successfully loaded R2R data - header: %p, base: %p, size: %lu\n",
2530+
data->r2r_header_ptr, data->image_base, (unsigned long)data->image_size);
2531+
2532+
return true;
2533+
}
2534+
#endif // defined (CORECLR_RUNTIME)
2535+
24392536
void
24402537
xamarin_vm_initialize ()
24412538
{
2539+
#if defined (CORECLR_RUNTIME)
2540+
struct host_runtime_contract host_contract = {
2541+
.size = sizeof(struct host_runtime_contract),
2542+
.pinvoke_override = &xamarin_pinvoke_override,
2543+
.get_native_code_data = &get_native_code_data
2544+
};
2545+
2546+
char contract_str[19]; // 0x + 16 hex digits + '\0'
2547+
snprintf(contract_str, 19, "0x%zx", (size_t)(&host_contract));
2548+
#else
24422549
char *pinvokeOverride = xamarin_strdup_printf ("%p", &xamarin_pinvoke_override);
2550+
#endif
2551+
24432552
char *trusted_platform_assemblies = xamarin_compute_trusted_platform_assemblies ();
24442553
char *native_dll_search_directories = xamarin_compute_native_dll_search_directories ();
24452554

24462555
// All the properties we pass here must also be listed in the _RuntimeConfigReservedProperties item group
24472556
// for the _CreateRuntimeConfiguration target in dotnet/targets/Xamarin.Shared.Sdk.targets.
24482557
const char *propertyKeys[] = {
24492558
"APP_CONTEXT_BASE_DIRECTORY", // path to where the managed assemblies are (usually at least - RID-specific assemblies will be in subfolders)
2450-
"APP_PATHS",
2559+
#if defined (CORECLR_RUNTIME)
2560+
"HOST_RUNTIME_CONTRACT",
2561+
#else
24512562
"PINVOKE_OVERRIDE",
2563+
#endif
24522564
"TRUSTED_PLATFORM_ASSEMBLIES",
2453-
"NATIVE_DLL_SEARCH_DIRECTORIES",
24542565
"RUNTIME_IDENTIFIER",
24552566
};
24562567
const char *propertyValues[] = {
24572568
xamarin_get_bundle_path (),
2458-
xamarin_get_bundle_path (),
2569+
#if defined (CORECLR_RUNTIME)
2570+
contract_str,
2571+
#else
24592572
pinvokeOverride,
2573+
#endif
24602574
trusted_platform_assemblies,
2461-
native_dll_search_directories,
24622575
RUNTIMEIDENTIFIER,
24632576
};
24642577
static_assert (sizeof (propertyKeys) == sizeof (propertyValues), "The number of keys and values must be the same.");
24652578

24662579
int propertyCount = (int) (sizeof (propertyValues) / sizeof (propertyValues [0]));
24672580
bool rv = xamarin_bridge_vm_initialize (propertyCount, propertyKeys, propertyValues);
24682581

2582+
#if !defined (CORECLR_RUNTIME)
24692583
xamarin_free (pinvokeOverride);
2584+
#endif
24702585
xamarin_free (trusted_platform_assemblies);
24712586
xamarin_free (native_dll_search_directories);
24722587

@@ -2502,7 +2617,7 @@ -(struct NSObjectData*) xamarinGetNSObjectData;
25022617
return rv;
25032618
}
25042619

2505-
void*
2620+
const void*
25062621
xamarin_pinvoke_override (const char *libraryName, const char *entrypointName)
25072622
{
25082623

runtime/xamarin/runtime.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ MonoAssembly* xamarin_assembly_preload_hook (MonoAssemblyName *aname, char **ass
220220
void xamarin_handle_bridge_exception (GCHandle gchandle, const char *method);
221221
void xamarin_vm_initialize ();
222222
bool xamarin_bridge_vm_initialize (int propertyCount, const char **propertyKeys, const char **propertyValues);
223-
void* xamarin_pinvoke_override (const char *libraryName, const char *entrypointName);
223+
const void* xamarin_pinvoke_override (const char *libraryName, const char *entrypointName);
224224
void xamarin_bridge_call_runtime_initialize (struct InitializationOptions* options, GCHandle* exception_gchandle);
225225
void xamarin_bridge_register_product_assembly (GCHandle* exception_gchandle);
226226
MonoMethod * xamarin_bridge_get_mono_method (MonoReflectionMethod *method);

0 commit comments

Comments
 (0)