2 #include <mono/utils/mono-compiler.h>
7 #include <mono/metadata/assembly-internals.h>
8 #include <mono/metadata/assembly.h>
9 #include <mono/metadata/environment.h>
10 #include <mono/metadata/loader-internals.h>
11 #include <mono/mini/mini-runtime.h>
12 #include <mono/mini/mini.h>
13 #include <mono/utils/mono-logger-internals.h>
17 char **basenames
; /* Foo.dll */
19 char **assembly_filepaths
; /* /blah/blah/blah/Foo.dll */
20 } MonoCoreTrustedPlatformAssemblies
;
25 } MonoCoreLookupPaths
;
27 static MonoCoreTrustedPlatformAssemblies
*trusted_platform_assemblies
;
28 static MonoCoreLookupPaths
*native_lib_paths
;
29 static MonoCoreLookupPaths
*app_paths
;
30 static MonoCoreLookupPaths
*app_ni_paths
;
31 static MonoCoreLookupPaths
*platform_resource_roots
;
34 mono_core_trusted_platform_assemblies_free (MonoCoreTrustedPlatformAssemblies
*a
)
38 g_strfreev (a
->basenames
);
39 g_strfreev (a
->assembly_filepaths
);
44 mono_core_lookup_paths_free (MonoCoreLookupPaths
*dl
)
48 g_strfreev (dl
->dirs
);
53 parse_trusted_platform_assemblies (const char *assemblies_paths
)
56 // https://docs.microsoft.com/en-us/dotnet/core/tutorials/netcore-hosting#step-3---prepare-runtime-properties
57 // this is ';' separated on Windows and ':' separated elsewhere.
58 char **parts
= g_strsplit (assemblies_paths
, G_SEARCHPATH_SEPARATOR_S
, 0);
60 for (char **p
= parts
; *p
!= NULL
&& **p
!= '\0'; p
++) {
62 const char *part
= *p
;
63 // can't use logger, it's not initialized yet.
64 printf ("\t\tassembly %d = <%s>\n", asm_count
, part
);
68 MonoCoreTrustedPlatformAssemblies
*a
= g_new0 (MonoCoreTrustedPlatformAssemblies
, 1);
69 a
->assembly_count
= asm_count
;
70 a
->assembly_filepaths
= parts
;
71 a
->basenames
= g_new0 (char*, asm_count
+ 1);
72 a
->basename_lens
= g_new0 (int, asm_count
+ 1);
73 for (int i
= 0; i
< asm_count
; ++i
) {
74 a
->basenames
[i
] = g_path_get_basename (a
->assembly_filepaths
[i
]);
75 a
->basename_lens
[i
] = strlen (a
->basenames
[i
]);
77 a
->basenames
[asm_count
] = NULL
;
78 a
->basename_lens
[asm_count
] = 0;
80 trusted_platform_assemblies
= a
;
84 static MonoCoreLookupPaths
*
85 parse_lookup_paths (const char *search_path
)
87 char **parts
= g_strsplit (search_path
, G_SEARCHPATH_SEPARATOR_S
, 0);
89 for (char **p
= parts
; *p
!= NULL
&& **p
!= '\0'; p
++) {
91 const char *part
= *p
;
92 // can't use logger, it's not initialized yet.
93 printf ("\t\tnative search dir %d = <%s>\n", dir_count
, part
);
97 MonoCoreLookupPaths
*dl
= g_new0 (MonoCoreLookupPaths
, 1);
99 dl
->dir_count
= dir_count
;
104 mono_core_preload_hook (MonoAssemblyLoadContext
*alc
, MonoAssemblyName
*aname
, char **assemblies_path
, gboolean refonly
, gpointer user_data
, MonoError
*error
)
106 MonoAssembly
*result
= NULL
;
107 MonoCoreTrustedPlatformAssemblies
*a
= (MonoCoreTrustedPlatformAssemblies
*)user_data
;
108 /* TODO: check that CoreCLR wants the strong name semantics here */
109 MonoAssemblyCandidatePredicate predicate
= &mono_assembly_candidate_predicate_sn_same_name
;
110 void* predicate_ud
= aname
;
111 char *basename
= NULL
;
113 if (a
== NULL
) // no TPA paths set
117 g_assert (aname
->name
);
119 /* alc might be a user ALC - we get here from alc.LoadFromAssemblyName(), but we should load TPA assemblies into the default alc */
120 MonoAssemblyLoadContext
*default_alc
= mono_domain_default_alc (mono_alc_domain (alc
));
122 basename
= g_strconcat (aname
->name
, ".dll", (const char*)NULL
); /* TODO: make sure CoreCLR never needs to load .exe files */
123 size_t basename_len
= strlen (basename
);
125 for (int i
= 0; i
< a
->assembly_count
; ++i
) {
126 if (basename_len
== a
->basename_lens
[i
] && !g_strncasecmp (basename
, a
->basenames
[i
], a
->basename_lens
[i
])) {
127 MonoAssemblyOpenRequest req
;
128 mono_assembly_request_prepare_open (&req
, MONO_ASMCTX_DEFAULT
, default_alc
);
129 req
.request
.predicate
= predicate
;
130 req
.request
.predicate_ud
= predicate_ud
;
132 const char *fullpath
= a
->assembly_filepaths
[i
];
134 gboolean found
= g_file_test (fullpath
, G_FILE_TEST_IS_REGULAR
);
137 MonoImageOpenStatus status
;
138 result
= mono_assembly_request_open (fullpath
, &req
, &status
);
139 /* TODO: do something with the status at the end? */
150 mono_trace (G_LOG_LEVEL_DEBUG
, MONO_TRACE_ASSEMBLY
, "netcore preload hook: did not find '%s'.", aname
->name
);
152 mono_trace (G_LOG_LEVEL_DEBUG
, MONO_TRACE_ASSEMBLY
, "netcore preload hook: loading '%s' from '%s'.", aname
->name
, result
->image
->name
);
158 install_assembly_loader_hooks (void)
160 mono_install_assembly_preload_hook_v2 (mono_core_preload_hook
, (void*)trusted_platform_assemblies
, FALSE
);
164 parse_properties (int propertyCount
, const char **propertyKeys
, const char **propertyValues
)
166 // A partial list of relevant properties is at:
167 // https://docs.microsoft.com/en-us/dotnet/core/tutorials/netcore-hosting#step-3---prepare-runtime-properties
169 for (int i
= 0; i
< propertyCount
; ++i
) {
170 size_t prop_len
= strlen (propertyKeys
[i
]);
171 if (prop_len
== 27 && !strncmp (propertyKeys
[i
], "TRUSTED_PLATFORM_ASSEMBLIES", 27)) {
172 parse_trusted_platform_assemblies (propertyValues
[i
]);
173 } else if (prop_len
== 9 && !strncmp (propertyKeys
[i
], "APP_PATHS", 9)) {
174 app_paths
= parse_lookup_paths (propertyValues
[i
]);
175 } else if (prop_len
== 12 && !strncmp (propertyKeys
[i
], "APP_NI_PATHS", 12)) {
176 app_ni_paths
= parse_lookup_paths (propertyValues
[i
]);
177 } else if (prop_len
== 23 && !strncmp (propertyKeys
[i
], "PLATFORM_RESOURCE_ROOTS", 23)) {
178 platform_resource_roots
= parse_lookup_paths (propertyValues
[i
]);
179 } else if (prop_len
== 29 && !strncmp (propertyKeys
[i
], "NATIVE_DLL_SEARCH_DIRECTORIES", 29)) {
180 native_lib_paths
= parse_lookup_paths (propertyValues
[i
]);
181 } else if (prop_len
== 30 && !strncmp (propertyKeys
[i
], "System.Globalization.Invariant", 30)) {
182 // TODO: Ideally we should propagate this through AppContext options
183 g_setenv ("DOTNET_SYSTEM_GLOBALIZATION_INVARIANT", propertyValues
[i
], TRUE
);
186 // can't use mono logger, it's not initialized yet.
187 printf ("\t Unprocessed property %03d '%s': <%s>\n", i
, propertyKeys
[i
], propertyValues
[i
]);
195 monovm_initialize (int propertyCount
, const char **propertyKeys
, const char **propertyValues
)
197 mono_runtime_register_appctx_properties (propertyCount
, propertyKeys
, propertyValues
);
199 if (!parse_properties (propertyCount
, propertyKeys
, propertyValues
))
200 return 0x80004005; /* E_FAIL */
202 install_assembly_loader_hooks ();
203 if (native_lib_paths
!= NULL
)
204 mono_set_pinvoke_search_directories (native_lib_paths
->dir_count
, g_strdupv (native_lib_paths
->dirs
));
205 // Our load hooks don't distinguish between normal, AOT'd, and satellite lookups the way CoreCLR's does.
206 // For now, just set assemblies_path with APP_PATHS and leave the rest.
207 if (app_paths
!= NULL
)
208 mono_set_assemblies_path_direct (g_strdupv (app_paths
->dirs
));
211 * Don't use Mono's legacy assembly name matching behavior - respect
212 * the requested version and culture.
214 mono_loader_set_strict_assembly_name_check (TRUE
);
220 monovm_execute_assembly (int argc
, const char **argv
, const char *managedAssemblyPath
, unsigned int *exitCode
)
222 if (exitCode
== NULL
)
228 // Make room for program name and executable assembly
230 int mono_argc
= argc
+ 2;
232 char **mono_argv
= (char **) malloc (sizeof (char *) * (mono_argc
+ 1 /* null terminated */));
233 const char **ptr
= (const char **) mono_argv
;
237 // executable assembly
238 *ptr
++ = (char*) managedAssemblyPath
;
241 for (int i
= 0; i
< argc
; ++i
)
246 mono_parse_env_options (&mono_argc
, &mono_argv
);
248 // TODO: Should be return code of Main only (mono_jit_exec result)
249 *exitCode
= mono_main (mono_argc
, mono_argv
);
255 monovm_shutdown (int *latchedExitCode
)
257 *latchedExitCode
= mono_environment_exitcode_get ();
265 monovm_initialize (int propertyCount
, const char **propertyKeys
, const char **propertyValues
)
271 monovm_execute_assembly (int argc
, const char **argv
, const char *managedAssemblyPath
, unsigned int *exitCode
)
277 monovm_shutdown (int *latchedExitCode
)
282 #endif // ENABLE_NETCORE