[Loader] Change mono_trace level from info to debug (#19110)
[mono-project.git] / mono / mini / monovm.c
blobd723e5fe8fe51c938a3370b672e2e9deaffce91c
1 #include <config.h>
2 #include <mono/utils/mono-compiler.h>
3 #include "monovm.h"
5 #if ENABLE_NETCORE
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>
15 typedef struct {
16 int assembly_count;
17 char **basenames; /* Foo.dll */
18 int *basename_lens;
19 char **assembly_filepaths; /* /blah/blah/blah/Foo.dll */
20 } MonoCoreTrustedPlatformAssemblies;
22 typedef struct {
23 int dir_count;
24 char **dirs;
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;
33 static void
34 mono_core_trusted_platform_assemblies_free (MonoCoreTrustedPlatformAssemblies *a)
36 if (!a)
37 return;
38 g_strfreev (a->basenames);
39 g_strfreev (a->assembly_filepaths);
40 g_free (a);
43 static void
44 mono_core_lookup_paths_free (MonoCoreLookupPaths *dl)
46 if (!dl)
47 return;
48 g_strfreev (dl->dirs);
49 g_free (dl);
52 static gboolean
53 parse_trusted_platform_assemblies (const char *assemblies_paths)
55 // From
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);
59 int asm_count = 0;
60 for (char **p = parts; *p != NULL && **p != '\0'; p++) {
61 #if 0
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);
65 #endif
66 asm_count++;
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;
81 return TRUE;
84 static MonoCoreLookupPaths *
85 parse_lookup_paths (const char *search_path)
87 char **parts = g_strsplit (search_path, G_SEARCHPATH_SEPARATOR_S, 0);
88 int dir_count = 0;
89 for (char **p = parts; *p != NULL && **p != '\0'; p++) {
90 #if 0
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);
94 #endif
95 dir_count++;
97 MonoCoreLookupPaths *dl = g_new0 (MonoCoreLookupPaths, 1);
98 dl->dirs = parts;
99 dl->dir_count = dir_count;
100 return dl;
103 static MonoAssembly*
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
114 goto leave;
116 g_assert (aname);
117 g_assert (aname->name);
118 g_assert (!refonly);
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);
136 if (found) {
137 MonoImageOpenStatus status;
138 result = mono_assembly_request_open (fullpath, &req, &status);
139 /* TODO: do something with the status at the end? */
140 if (result)
141 break;
146 leave:
147 g_free (basename);
149 if (!result) {
150 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "netcore preload hook: did not find '%s'.", aname->name);
151 } else {
152 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "netcore preload hook: loading '%s' from '%s'.", aname->name, result->image->name);
154 return result;
157 static void
158 install_assembly_loader_hooks (void)
160 mono_install_assembly_preload_hook_v2 (mono_core_preload_hook, (void*)trusted_platform_assemblies, FALSE);
163 static gboolean
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);
184 } else {
185 #if 0
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]);
188 #endif
191 return TRUE;
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);
216 return 0;
220 monovm_execute_assembly (int argc, const char **argv, const char *managedAssemblyPath, unsigned int *exitCode)
222 if (exitCode == NULL)
224 return -1;
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;
235 *ptr++ = NULL;
237 // executable assembly
238 *ptr++ = (char*) managedAssemblyPath;
240 // the rest
241 for (int i = 0; i < argc; ++i)
242 *ptr++ = argv [i];
244 *ptr = NULL;
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);
251 return 0;
255 monovm_shutdown (int *latchedExitCode)
257 *latchedExitCode = mono_environment_exitcode_get ();
259 return 0;
262 #else
265 monovm_initialize (int propertyCount, const char **propertyKeys, const char **propertyValues)
267 return -1;
271 monovm_execute_assembly (int argc, const char **argv, const char *managedAssemblyPath, unsigned int *exitCode)
273 return -1;
277 monovm_shutdown (int *latchedExitCode)
279 return -1;
282 #endif // ENABLE_NETCORE