static char **extra_gac_paths = NULL;
#ifndef DISABLE_ASSEMBLY_REMAPPING
+
+static GHashTable* assembly_remapping_table;
/* The list of system assemblies what will be remapped to the running
- * runtime version. WARNING: this list must be sorted.
+ * runtime version.
+ * This list is stored in @assembly_remapping_table during initialization.
+ * Keep it sorted just to make maintenance easier.
+ *
* The integer number is an index in the MonoRuntimeInfo structure, whose
* values can be found in domain.c - supported_runtimes. Look there
* to understand what remapping will be made.
{"System.Drawing", 0},
{"System.Drawing.Design", 0},
{"System.EnterpriseServices", 0},
+ {"System.IO.Compression", 2},
{"System.IdentityModel", 3},
{"System.IdentityModel.Selectors", 3},
- {"System.IO.Compression", 2},
{"System.Management", 0},
{"System.Messaging", 0},
{"System.Net", 2},
- {"System.Net.Http", 3},
+ {"System.Net.Http", 4},
{"System.Numerics.Vectors", 3},
{"System.Runtime.InteropServices.RuntimeInformation", 2},
{"System.Runtime.Remoting", 0},
static GSList *loaded_assembly_bindings = NULL;
/* Class lazy loading functions */
-static GENERATE_TRY_GET_CLASS_WITH_CACHE (internals_visible, System.Runtime.CompilerServices, "InternalsVisibleToAttribute")
+static GENERATE_TRY_GET_CLASS_WITH_CACHE (internals_visible, "System.Runtime.CompilerServices", "InternalsVisibleToAttribute")
static MonoAssembly*
mono_assembly_invoke_search_hook_internal (MonoAssemblyName *aname, MonoAssembly *requesting, gboolean refonly, gboolean postload);
static MonoAssembly*
}
static MonoAssembly *
-load_in_path (const char *basename, const char** search_path, MonoImageOpenStatus *status, MonoBoolean refonly)
+load_in_path (const char *basename, const char** search_path, MonoImageOpenStatus *status, MonoBoolean refonly, MonoAssemblyCandidatePredicate predicate, gpointer user_data)
{
int i;
char *fullpath;
for (i = 0; search_path [i]; ++i) {
fullpath = g_build_filename (search_path [i], basename, NULL);
- result = mono_assembly_open_full (fullpath, status, refonly);
+ result = mono_assembly_open_predicate (fullpath, refonly, FALSE, predicate, user_data, status);
g_free (fullpath);
if (result)
return result;
mono_os_mutex_init_recursive (&assemblies_mutex);
mono_os_mutex_init (&assembly_binding_mutex);
+
+#ifndef DISABLE_ASSEMBLY_REMAPPING
+ assembly_remapping_table = g_hash_table_new (g_str_hash, g_str_equal);
+
+ int i;
+ for (i = 0; i < G_N_ELEMENTS (framework_assemblies) - 1; ++i)
+ g_hash_table_insert (assembly_remapping_table, (void*)framework_assemblies [i].assembly_name, (void*)&framework_assemblies [i]);
+
+#endif
}
static void
mono_assembly_remap_version (MonoAssemblyName *aname, MonoAssemblyName *dest_aname)
{
const MonoRuntimeInfo *current_runtime;
- int pos, first, last;
if (aname->name == NULL) return aname;
}
#ifndef DISABLE_ASSEMBLY_REMAPPING
- first = 0;
- last = G_N_ELEMENTS (framework_assemblies) - 1;
-
- while (first <= last) {
- int res;
- pos = first + (last - first) / 2;
- res = strcmp (aname->name, framework_assemblies[pos].assembly_name);
- if (res == 0) {
- const AssemblyVersionSet* vset;
- int index = framework_assemblies[pos].version_set_index;
- g_assert (index < G_N_ELEMENTS (current_runtime->version_sets));
- vset = ¤t_runtime->version_sets [index];
-
- if (aname->major == vset->major && aname->minor == vset->minor &&
- aname->build == vset->build && aname->revision == vset->revision)
- return aname;
-
- if (framework_assemblies[pos].only_lower_versions && compare_versions ((AssemblyVersionSet*)vset, aname) < 0)
- return aname;
-
- if ((aname->major | aname->minor | aname->build | aname->revision) != 0)
- mono_trace (G_LOG_LEVEL_WARNING, MONO_TRACE_ASSEMBLY,
- "The request to load the assembly %s v%d.%d.%d.%d was remapped to v%d.%d.%d.%d",
- aname->name,
- aname->major, aname->minor, aname->build, aname->revision,
- vset->major, vset->minor, vset->build, vset->revision
- );
-
- memcpy (dest_aname, aname, sizeof(MonoAssemblyName));
- dest_aname->major = vset->major;
- dest_aname->minor = vset->minor;
- dest_aname->build = vset->build;
- dest_aname->revision = vset->revision;
- if (framework_assemblies[pos].new_assembly_name != NULL) {
- dest_aname->name = framework_assemblies[pos].new_assembly_name;
- mono_trace (G_LOG_LEVEL_WARNING, MONO_TRACE_ASSEMBLY,
- "The assembly name %s was remapped to %s",
- aname->name,
- dest_aname->name);
- }
- return dest_aname;
- } else if (res < 0) {
- last = pos - 1;
- } else {
- first = pos + 1;
+ const AssemblyVersionMap *vmap = (AssemblyVersionMap *)g_hash_table_lookup (assembly_remapping_table, aname->name);
+ if (vmap) {
+ const AssemblyVersionSet* vset;
+ int index = vmap->version_set_index;
+ g_assert (index < G_N_ELEMENTS (current_runtime->version_sets));
+ vset = ¤t_runtime->version_sets [index];
+
+ if (aname->major == vset->major && aname->minor == vset->minor &&
+ aname->build == vset->build && aname->revision == vset->revision) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "Found assembly remapping for %s and was for the same version %d.%d.%d.%d",
+ aname->name,
+ aname->major, aname->minor, aname->build, aname->revision);
+ return aname;
+ }
+
+ if (vmap->only_lower_versions && compare_versions ((AssemblyVersionSet*)vset, aname) < 0) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY,
+ "Found lower-versions-only assembly remaping to load %s %d.%d.%d.%d but mapping has %d.%d.%d.%d",
+ aname->name,
+ aname->major, aname->minor, aname->build, aname->revision,
+ vset->major, vset->minor, vset->build, vset->revision
+ );
+ return aname;
+ }
+
+ if ((aname->major | aname->minor | aname->build | aname->revision) != 0)
+ mono_trace (G_LOG_LEVEL_WARNING, MONO_TRACE_ASSEMBLY,
+ "The request to load the assembly %s v%d.%d.%d.%d was remapped to v%d.%d.%d.%d",
+ aname->name,
+ aname->major, aname->minor, aname->build, aname->revision,
+ vset->major, vset->minor, vset->build, vset->revision
+ );
+
+ memcpy (dest_aname, aname, sizeof(MonoAssemblyName));
+ dest_aname->major = vset->major;
+ dest_aname->minor = vset->minor;
+ dest_aname->build = vset->build;
+ dest_aname->revision = vset->revision;
+ if (current_runtime->public_key_token != NULL &&
+ dest_aname->public_key_token [0] != 0 &&
+ !mono_public_tokens_are_equal (dest_aname->public_key_token, (const mono_byte *)current_runtime->public_key_token)) {
+ mono_trace (G_LOG_LEVEL_WARNING, MONO_TRACE_ASSEMBLY,
+ "The request for assembly name '%s' with PublicKeyToken=%s was remapped to PublicKeyToken=%s",
+ dest_aname->name,
+ dest_aname->public_key_token,
+ current_runtime->public_key_token);
+ memcpy (dest_aname->public_key_token, current_runtime->public_key_token, MONO_PUBLIC_KEY_TOKEN_LENGTH);
+ }
+ if (vmap->new_assembly_name != NULL) {
+ dest_aname->name = vmap->new_assembly_name;
+ mono_trace (G_LOG_LEVEL_WARNING, MONO_TRACE_ASSEMBLY,
+ "The assembly name %s was remapped to %s",
+ aname->name,
+ dest_aname->name);
}
+ return dest_aname;
}
#endif
*/
MonoAssembly *
mono_assembly_open_full (const char *filename, MonoImageOpenStatus *status, gboolean refonly)
+{
+ return mono_assembly_open_a_lot (filename, status, refonly, FALSE);
+}
+
+MonoAssembly *
+mono_assembly_open_a_lot (const char *filename, MonoImageOpenStatus *status, gboolean refonly, gboolean load_from_context)
+{
+ return mono_assembly_open_predicate (filename, refonly, load_from_context, NULL, NULL, status);
+}
+
+MonoAssembly *
+mono_assembly_open_predicate (const char *filename, gboolean refonly,
+ gboolean load_from_context,
+ MonoAssemblyCandidatePredicate predicate,
+ gpointer user_data,
+ MonoImageOpenStatus *status)
{
MonoImage *image;
MonoAssembly *ass;
}
if (!image)
- image = mono_image_open_full (fname, status, refonly);
+ image = mono_image_open_a_lot (fname, status, refonly, load_from_context);
if (!image){
if (*status == MONO_IMAGE_OK)
return image->assembly;
}
- ass = mono_assembly_load_from_full (image, fname, status, refonly);
+ ass = mono_assembly_load_from_predicate (image, fname, refonly, predicate, user_data, status);
if (ass) {
if (!loaded_from_bundle)
gboolean
mono_assembly_has_reference_assembly_attribute (MonoAssembly *assembly, MonoError *error)
{
- mono_error_init (error);
+ error_init (error);
/*
* This might be called during assembly loading, so do everything using the low-level
MonoAssembly *
mono_assembly_open (const char *filename, MonoImageOpenStatus *status)
{
- return mono_assembly_open_full (filename, status, FALSE);
+ return mono_assembly_open_predicate (filename, FALSE, FALSE, NULL, NULL, status);
}
/**
MonoAssembly *
mono_assembly_load_from_full (MonoImage *image, const char*fname,
MonoImageOpenStatus *status, gboolean refonly)
+{
+ return mono_assembly_load_from_predicate (image, fname, refonly, NULL, NULL, status);
+}
+
+MonoAssembly *
+mono_assembly_load_from_predicate (MonoImage *image, const char *fname,
+ gboolean refonly,
+ MonoAssemblyCandidatePredicate predicate,
+ gpointer user_data,
+ MonoImageOpenStatus *status)
{
MonoAssembly *ass, *ass2;
char *base_dir;
mono_error_cleanup (&refasm_error);
}
+ if (predicate && !predicate (ass, user_data)) {
+ mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Predicate returned FALSE, skipping '%s' (%s)\n", ass->aname.name, image->name);
+ g_free (ass);
+ g_free (base_dir);
+ mono_image_close (image);
+ *status = MONO_IMAGE_IMAGE_INVALID;
+ return NULL;
+ }
+
mono_assemblies_lock ();
if (image->assembly) {
if (fullpath == NULL)
return NULL;
else {
- MonoAssembly *res = mono_assembly_open (fullpath, status);
+ MonoAssembly *res = mono_assembly_open_predicate (fullpath, FALSE, FALSE, NULL, NULL, status);
g_free (fullpath);
return res;
}
if (strstr (aname->name, ".dll")) {
len = strlen (aname->name) - 4;
name = (gchar *)g_malloc (len + 1);
- strncpy (name, aname->name, len);
+ memcpy (name, aname->name, len);
name[len] = 0;
} else
name = g_strdup (aname->name);
if (!domain)
return;
+ if (info->has_new_version && mono_assembly_is_problematic_version (info->name, info->new_version.major, info->new_version.minor, info->new_version.build, info->new_version.revision)) {
+ mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Discarding assembly binding to problematic version %s v%d.%d.%d.%d",
+ info->name, info->new_version.major, info->new_version.minor, info->new_version.build, info->new_version.revision);
+ return;
+ }
+
for (tmp = domain->assembly_bindings; tmp; tmp = tmp->next) {
info_tmp = (MonoAssemblyBindingInfo *)tmp->data;
if (strcmp (info->name, info_tmp->name) == 0 && info_versions_equal (info, info_tmp))
if (strstr (aname->name, ".dll")) {
len = strlen (filename) - 4;
name = (gchar *)g_malloc (len + 1);
- strncpy (name, aname->name, len);
+ memcpy (name, aname->name, len);
name[len] = 0;
} else {
name = g_strdup (aname->name);
paths = extra_gac_paths;
while (!result && *paths) {
fullpath = g_build_path (G_DIR_SEPARATOR_S, *paths, "lib", "mono", "gac", subpath, NULL);
- result = mono_assembly_open_full (fullpath, status, refonly);
+ result = mono_assembly_open_predicate (fullpath, refonly, FALSE, NULL, NULL, status);
g_free (fullpath);
paths++;
}
fullpath = g_build_path (G_DIR_SEPARATOR_S, mono_assembly_getrootdir (),
"mono", "gac", subpath, NULL);
- result = mono_assembly_open_full (fullpath, status, refonly);
+ result = mono_assembly_open_predicate (fullpath, refonly, FALSE, NULL, NULL, status);
g_free (fullpath);
if (result)
// This unusual directory layout can occur if mono is being built and run out of its own source repo
if (assemblies_path) { // Custom assemblies path set via MONO_PATH or mono_set_assemblies_path
- corlib = load_in_path ("mscorlib.dll", (const char**)assemblies_path, status, FALSE);
+ corlib = load_in_path ("mscorlib.dll", (const char**)assemblies_path, status, FALSE, NULL, NULL);
if (corlib)
goto return_corlib_and_facades;
}
/* Normal case: Load corlib from mono/<version> */
corlib_file = g_build_filename ("mono", runtime->framework_version, "mscorlib.dll", NULL);
if (assemblies_path) { // Custom assemblies path
- corlib = load_in_path (corlib_file, (const char**)assemblies_path, status, FALSE);
+ corlib = load_in_path (corlib_file, (const char**)assemblies_path, status, FALSE, NULL, NULL);
if (corlib) {
g_free (corlib_file);
goto return_corlib_and_facades;
}
}
- corlib = load_in_path (corlib_file, default_path, status, FALSE);
+ corlib = load_in_path (corlib_file, default_path, status, FALSE, NULL, NULL);
g_free (corlib_file);
return_corlib_and_facades:
prevent_reference_assembly_from_running (MonoAssembly* candidate, gboolean refonly)
{
MonoError refasm_error;
- mono_error_init (&refasm_error);
+ error_init (&refasm_error);
if (candidate && !refonly && mono_assembly_has_reference_assembly_attribute (candidate, &refasm_error)) {
candidate = NULL;
}
return candidate;
}
+gboolean
+mono_assembly_candidate_predicate_sn_same_name (MonoAssembly *candidate, gpointer ud)
+{
+ MonoAssemblyName *wanted_name = (MonoAssemblyName*)ud;
+ MonoAssemblyName *candidate_name = &candidate->aname;
+
+ g_assert (wanted_name != NULL);
+ g_assert (candidate_name != NULL);
+
+ if (mono_trace_is_traced (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY)) {
+ char * s = mono_stringify_assembly_name (wanted_name);
+ mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Predicate: wanted = %s\n", s);
+ g_free (s);
+ s = mono_stringify_assembly_name (candidate_name);
+ mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Predicate: candidate = %s\n", s);
+ g_free (s);
+ }
+
+ /* No wanted token, bail. */
+ if (0 == wanted_name->public_key_token [0]) {
+ mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Predicate: wanted has no token, returning TRUE\n");
+ return TRUE;
+ }
+
+ if (0 == candidate_name->public_key_token [0]) {
+ mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Predicate: candidate has no token, returning FALSE\n");
+ return FALSE;
+ }
+
+
+ gboolean result = mono_assembly_names_equal (wanted_name, candidate_name);
+
+ mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Predicate: candidate and wanted names %s\n",
+ result ? "match, returning TRUE" : "don't match, returning FALSE");
+ return result;
+
+}
+
MonoAssembly*
mono_assembly_load_full_nosearch (MonoAssemblyName *aname,
int len;
aname = mono_assembly_remap_version (aname, &maped_aname);
-
+
/* Reflection only assemblies don't get assembly binding */
if (!refonly)
aname = mono_assembly_apply_binding (aname, &maped_name_pp);
if (basedir) {
fullpath = g_build_filename (basedir, filename, NULL);
- result = mono_assembly_open_full (fullpath, status, refonly);
+ result = mono_assembly_open_predicate (fullpath, refonly, FALSE, NULL, NULL, status);
g_free (fullpath);
if (result) {
result->in_gac = FALSE;
}
}
- result = load_in_path (filename, default_path, status, refonly);
+ result = load_in_path (filename, default_path, status, refonly, NULL, NULL);
if (result)
result->in_gac = FALSE;
g_free (filename);