Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Make AppleAppBuilder host template use host_runtime_contract
  • Loading branch information
elinor-fung committed Nov 14, 2025
commit 78376fc27023eaf18d67f10cc046bdef3196dd2c
1 change: 1 addition & 0 deletions src/tasks/AppleAppBuilder/AppleAppBuilder.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
<ItemGroup>
<EmbeddedResource Include="Templates\*.*" />
<EmbeddedResource Include="$(CoreClrProjectRoot)hosts\inc\coreclrhost.h" Link="Templates\coreclrhost.h" />
<EmbeddedResource Include="$(SharedNativeRoot)corehost\host_runtime_contract.h" Link="Templates\host_runtime_contract.h" />
</ItemGroup>
<ItemGroup>
<Compile Include="AppleAppBuilder.cs" />
Expand Down
91 changes: 86 additions & 5 deletions src/tasks/AppleAppBuilder/Templates/runtime-coreclr.m
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#import <Foundation/Foundation.h>
#include "coreclrhost.h"
#include "host_runtime_contract.h"
#include <TargetConditionals.h>
#import <os/log.h>
#include <sys/stat.h>
Expand Down Expand Up @@ -68,7 +69,7 @@
return strdup([joined UTF8String]);
}

void*
const void*
pinvoke_override (const char *libraryName, const char *entrypointName)
{
if (!strcmp (libraryName, "__Internal"))
Expand All @@ -79,6 +80,80 @@
return NULL;
}

#include <mach-o/dyld.h>
#include <mach-o/loader.h>
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;
}
}

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;

// TODO: store and dlclose the handles after the app runs
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;
}

void
mono_ios_runtime_init (void)
{
Expand Down Expand Up @@ -116,15 +191,21 @@
#endif
assert (res > 0);

char pinvoke_override_addr [16];
sprintf (pinvoke_override_addr, "%p", &pinvoke_override);
struct host_runtime_contract host_contract = {
.size = sizeof(struct host_runtime_contract),
.pinvoke_override = &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));

// TODO: set TRUSTED_PLATFORM_ASSEMBLIES, APP_PATHS and NATIVE_DLL_SEARCH_DIRECTORIES
const char *appctx_keys [] = {
"RUNTIME_IDENTIFIER",
"APP_CONTEXT_BASE_DIRECTORY",
"TRUSTED_PLATFORM_ASSEMBLIES",
"PINVOKE_OVERRIDE",
"HOST_RUNTIME_CONTRACT",
#if !defined(INVARIANT_GLOBALIZATION)
"ICU_DAT_FILE_PATH"
#endif
Expand All @@ -133,7 +214,7 @@
APPLE_RUNTIME_IDENTIFIER,
bundle,
compute_trusted_platform_assemblies(),
pinvoke_override_addr,
contract_str,
#if !defined(INVARIANT_GLOBALIZATION)
icu_dat_path
#endif
Expand Down
2 changes: 2 additions & 0 deletions src/tasks/AppleAppBuilder/Xcode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -618,6 +618,8 @@ public string GenerateCMake(
{
File.WriteAllText(Path.Combine(binDir, "coreclrhost.h"),
Utils.GetEmbeddedResource("coreclrhost.h"));
File.WriteAllText(Path.Combine(binDir, "host_runtime_contract.h"),
Utils.GetEmbeddedResource("host_runtime_contract.h"));

// NOTE: Library mode is not supported yet
File.WriteAllText(Path.Combine(binDir, "runtime.m"),
Expand Down