forked from dotnet/runtime
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathruntime-coreclr.m
More file actions
245 lines (202 loc) · 7.84 KB
/
runtime-coreclr.m
File metadata and controls
245 lines (202 loc) · 7.84 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
#import <Foundation/Foundation.h>
#include "coreclrhost.h"
#include "host_runtime_contract.h"
#include <TargetConditionals.h>
#import <os/log.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <stdio.h>
#include <dlfcn.h>
#import "util.h"
#define APPLE_RUNTIME_IDENTIFIER "//%APPLE_RUNTIME_IDENTIFIER%"
const char *
get_bundle_path (void)
{
static char *bundle_path = NULL;
if (bundle_path)
return bundle_path;
NSBundle* main_bundle = [NSBundle mainBundle];
NSString* path = [main_bundle bundlePath];
#if TARGET_OS_MACCATALYST
path = [path stringByAppendingString:@"/Contents/Resources"];
#endif
bundle_path = strdup ([path UTF8String]);
return bundle_path;
}
char *
compute_trusted_platform_assemblies ()
{
const char *bundle_path = get_bundle_path ();
NSMutableArray<NSString *> *files = [NSMutableArray array];
NSMutableArray<NSString *> *exes = [NSMutableArray array];
NSFileManager *manager = [NSFileManager defaultManager];
NSString *dir = [NSString stringWithUTF8String: bundle_path];
NSDirectoryEnumerator *enumerator = [manager enumeratorAtURL:[NSURL fileURLWithPath: dir]
includingPropertiesForKeys:@[NSURLNameKey, NSURLIsDirectoryKey]
options:NSDirectoryEnumerationSkipsSubdirectoryDescendants
errorHandler:nil];
for (NSURL *file in enumerator) {
// skip subdirectories
NSNumber *isDirectory = nil;
if (![file getResourceValue:&isDirectory forKey:NSURLIsDirectoryKey error:nil] || [isDirectory boolValue])
continue;
NSString *name = nil;
if (![file getResourceValue:&name forKey:NSURLNameKey error:nil])
continue;
if ([name length] < 4)
continue;
if ([name compare: @".dll" options: NSCaseInsensitiveSearch range: NSMakeRange ([name length] - 4, 4)] == NSOrderedSame) {
[files addObject: [dir stringByAppendingPathComponent: name]];
}
}
// Join them all together with a colon separating them
NSString *joined = [files componentsJoinedByString: @":"];
return strdup([joined UTF8String]);
}
const void*
pinvoke_override (const char *libraryName, const char *entrypointName)
{
if (!strcmp (libraryName, "__Internal"))
{
return dlsym (RTLD_DEFAULT, entrypointName);
}
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)
{
#if INVARIANT_GLOBALIZATION
setenv ("DOTNET_SYSTEM_GLOBALIZATION_INVARIANT", "1", TRUE);
#endif
#if HYBRID_GLOBALIZATION
setenv ("DOTNET_SYSTEM_GLOBALIZATION_HYBRID", "1", TRUE);
#endif
// build using DiagnosticPorts property in AppleAppBuilder
// or set DOTNET_DiagnosticPorts env via mlaunch, xharness when undefined.
// NOTE, using DOTNET_DiagnosticPorts requires app build using AppleAppBuilder and RuntimeComponents=diagnostics_tracing
#ifdef DIAGNOSTIC_PORTS
setenv ("DOTNET_DiagnosticPorts", DIAGNOSTIC_PORTS, true);
#endif
%EnvVariables%
char **managed_argv;
int argi = get_managed_args (&managed_argv);
bool wait_for_debugger = FALSE;
const char* bundle = get_bundle_path ();
chdir (bundle);
char icu_dat_path [1024];
int res;
#if defined(HYBRID_GLOBALIZATION)
res = snprintf (icu_dat_path, sizeof (icu_dat_path) - 1, "%s/%s", bundle, "icudt_hybrid.dat");
#else
res = snprintf (icu_dat_path, sizeof (icu_dat_path) - 1, "%s/%s", bundle, "icudt.dat");
#endif
assert (res > 0);
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",
"HOST_RUNTIME_CONTRACT",
#if !defined(INVARIANT_GLOBALIZATION)
"ICU_DAT_FILE_PATH"
#endif
};
const char *appctx_values [] = {
APPLE_RUNTIME_IDENTIFIER,
bundle,
compute_trusted_platform_assemblies(),
contract_str,
#if !defined(INVARIANT_GLOBALIZATION)
icu_dat_path
#endif
};
const char* executable = "%EntryPointLibName%";
const char *executablePath = [[[[NSBundle mainBundle] executableURL] path] UTF8String];
unsigned int coreclr_domainId = 0;
void *coreclr_handle = NULL;
char path [1024];
res = snprintf (path, sizeof (path) - 1, "%s/%s", bundle, executable);
assert (res > 0);
res = coreclr_initialize (
executablePath, executable,
sizeof (appctx_keys) / sizeof (appctx_keys [0]), appctx_keys, appctx_values,
&coreclr_handle, &coreclr_domainId);
assert (res == 0);
coreclr_execute_assembly (coreclr_handle, coreclr_domainId, argi, managed_argv, path, &res);
// Print this so apps parsing logs can detect when we exited
os_log_info (OS_LOG_DEFAULT, EXIT_CODE_TAG ": %d", res);
free_managed_args (&managed_argv, argi);
exit (res);
}