#include <mono/metadata/profiler-private.h>
#include <mono/metadata/class-internals.h>
#include <mono/metadata/domain-internals.h>
+#include <mono/metadata/reflection-internals.h>
#include <mono/metadata/mono-endian.h>
#include <mono/metadata/mono-debug.h>
#include <mono/io-layer/io-layer.h>
#include <mach-o/dyld.h>
#endif
-/* AssemblyVersionMap: an assembly name and the assembly version set on which it is based */
+/* AssemblyVersionMap: an assembly name, the assembly version set on which it is based, the assembly name it is replaced with and whether only versions lower than the current runtime version should be remapped */
typedef struct {
const char* assembly_name;
guint8 version_set_index;
+ const char* new_assembly_name;
+ gboolean only_lower_versions;
} AssemblyVersionMap;
/* the default search path is empty, the first slot is replaced with the computed value */
{"I18N.Other", 0},
{"I18N.Rare", 0},
{"I18N.West", 0},
- {"Microsoft.Build.Engine", 2},
- {"Microsoft.Build.Framework", 2},
+ {"Microsoft.Build.Engine", 2, NULL, TRUE},
+ {"Microsoft.Build.Framework", 2, NULL, TRUE},
+ {"Microsoft.Build.Tasks", 2, "Microsoft.Build.Tasks.v4.0"},
+ {"Microsoft.Build.Tasks.v3.5", 2, "Microsoft.Build.Tasks.v4.0"},
+ {"Microsoft.Build.Utilities", 2, "Microsoft.Build.Utilities.v4.0"},
+ {"Microsoft.Build.Utilities.v3.5", 2, "Microsoft.Build.Utilities.v4.0"},
{"Microsoft.VisualBasic", 1},
{"Microsoft.VisualC", 1},
{"Mono.Cairo", 0},
{"Mono.Security.Win32", 0},
{"Mono.Xml.Ext", 0},
{"Novell.Directory.Ldap", 0},
- {"Npgsql", 0},
{"PEAPI", 0},
{"System", 0},
{"System.ComponentModel.Composition", 2},
/* Loaded assembly binding info */
static GSList *loaded_assembly_bindings = NULL;
+/* Class lazy loading functions */
+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*
config = g_build_filename (base, "etc", NULL);
lib = g_build_filename (base, "lib", NULL);
- mono = g_build_filename (lib, "mono/2.0", NULL);
+ mono = g_build_filename (lib, "mono/4.5", NULL); // FIXME: stop hardcoding 4.5 here
if (stat (mono, &buf) == -1)
fallback ();
else {
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",
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;
return aname;
}
-/*
+/**
* mono_assembly_get_assemblyref:
+ * @image: pointer to the MonoImage to extract the information from.
+ * @index: index to the assembly reference in the image.
+ * @aname: pointer to a `MonoAssemblyName` that will hold the returned value.
*
- * Fill out ANAME with the assembly name of the INDEXth assembly reference in IMAGE.
+ * Fills out the @aname with the assembly name of the @index assembly reference in @image.
*/
void
mono_assembly_get_assemblyref (MonoImage *image, int index, MonoAssemblyName *aname)
}
}
+/**
+ * mono_assembly_load_references:
+ * @image:
+ * @status:
+ * @deprecated: There is no reason to use this method anymore, it does nothing
+ *
+ * This method is now a no-op, it does nothing other than setting the @status to #MONO_IMAGE_OK
+ */
void
mono_assembly_load_references (MonoImage *image, MonoImageOpenStatus *status)
{
/**
* mono_assembly_open_from_bundle:
* @filename: Filename requested
- * @status: return value
+ * @status: return status code
*
* This routine tries to open the assembly specified by `filename' from the
* defined bundles, if found, returns the MonoImage for it, if not found
return NULL;
}
+/**
+ * mono_assemblies_open_full:
+ * @filename: the file to load
+ * @status: return status code
+ * @refonly: Whether this assembly is being opened in "reflection-only" mode.
+*
+ * This loads an assembly from the specified @filename. The @filename allows
+ * a local URL (starting with a file:// prefix). If a file prefix is used, the
+ * filename is interpreted as a URL, and the filename is URL-decoded. Otherwise the file
+ * is treated as a local path.
+ *
+ * First, an attempt is made to load the assembly from the bundled executable (for those
+ * deployments that have been done with the `mkbundle` tool or for scenarios where the
+ * assembly has been registered as an embedded assembly). If this is not the case, then
+ * the assembly is loaded from disk using `api:mono_image_open_full`.
+ *
+ * If the pointed assembly does not live in the Global Assembly Cache, a shadow copy of
+ * the assembly is made.
+ *
+ * If @refonly is set to true, then the assembly is loaded purely for inspection with
+ * the `System.Reflection` API.
+ *
+ * Returns: NULL on error, with the @status set to an error code, or a pointer
+ * to the assembly.
+ */
MonoAssembly *
mono_assembly_open_full (const char *filename, MonoImageOpenStatus *status, gboolean refonly)
{
g_free (val);
}
-/*
+/**
* mono_assembly_load_friends:
* @ass: an assembly
*
* names in custom attributes.
*
* This is an internal method, we need this because when we load mscorlib
- * we do not have the mono_defaults.internals_visible_class loaded yet,
+ * we do not have the internals visible cattr loaded yet,
* so we need to load these after we initialize the runtime.
*
* LOCKING: Acquires the assemblies lock plus the loader lock.
void
mono_assembly_load_friends (MonoAssembly* ass)
{
+ MonoError error;
int i;
MonoCustomAttrInfo* attrs;
GSList *list;
if (ass->friend_assembly_names_inited)
return;
- attrs = mono_custom_attrs_from_assembly (ass);
+ attrs = mono_custom_attrs_from_assembly_checked (ass, &error);
+ mono_error_assert_ok (&error);
if (!attrs) {
mono_assemblies_lock ();
ass->friend_assembly_names_inited = TRUE;
MonoAssemblyName *aname;
const gchar *data;
/* Do some sanity checking */
- if (!attr->ctor || attr->ctor->klass != mono_defaults.internals_visible_class)
+ if (!attr->ctor || attr->ctor->klass != mono_class_try_get_internals_visible_class ())
continue;
if (attr->data_size < 4)
continue;
/**
* mono_assembly_open:
* @filename: Opens the assembly pointed out by this name
- * @status: where a status code can be returned
+ * @status: return status code
*
- * mono_assembly_open opens the PE-image pointed by @filename, and
- * loads any external assemblies referenced by it.
+ * This loads an assembly from the specified @filename. The @filename allows
+ * a local URL (starting with a file:// prefix). If a file prefix is used, the
+ * filename is interpreted as a URL, and the filename is URL-decoded. Otherwise the file
+ * is treated as a local path.
+ *
+ * First, an attempt is made to load the assembly from the bundled executable (for those
+ * deployments that have been done with the `mkbundle` tool or for scenarios where the
+ * assembly has been registered as an embedded assembly). If this is not the case, then
+ * the assembly is loaded from disk using `api:mono_image_open_full`.
+ *
+ * If the pointed assembly does not live in the Global Assembly Cache, a shadow copy of
+ * the assembly is made.
*
* Return: a pointer to the MonoAssembly if @filename contains a valid
* assembly or NULL on error. Details about the error are stored in the
return mono_assembly_open_full (filename, status, FALSE);
}
+/**
+ * mono_assembly_load_from_full:
+ * @image: Image to load the assembly from
+ * @fname: assembly name to associate with the assembly
+ * @status: returns the status condition
+ * @refonly: Whether this assembly is being opened in "reflection-only" mode.
+ *
+ * If the provided @image has an assembly reference, it will process the given
+ * image as an assembly with the given name.
+ *
+ * Most likely you want to use the `api:mono_assembly_load_full` method instead.
+ *
+ * Returns: A valid pointer to a `MonoAssembly*` on success and the @status will be
+ * set to #MONO_IMAGE_OK; or NULL on error.
+ *
+ * If there is an error loading the assembly the @status will indicate the
+ * reason with @status being set to `MONO_IMAGE_INVALID` if the
+ * image did not contain an assembly reference table.
+ */
MonoAssembly *
mono_assembly_load_from_full (MonoImage *image, const char*fname,
MonoImageOpenStatus *status, gboolean refonly)
return ass;
}
+/**
+ * mono_assembly_load_from:
+ * @image: Image to load the assembly from
+ * @fname: assembly name to associate with the assembly
+ * @status: return status code
+ *
+ * If the provided @image has an assembly reference, it will process the given
+ * image as an assembly with the given name.
+ *
+ * Most likely you want to use the `api:mono_assembly_load_full` method instead.
+ *
+ * This is equivalent to calling `api:mono_assembly_load_from_full` with the
+ * @refonly parameter set to FALSE.
+ * Returns: A valid pointer to a `MonoAssembly*` on success and the @status will be
+ * set to #MONO_IMAGE_OK; or NULL on error.
+ *
+ * If there is an error loading the assembly the @status will indicate the
+ * reason with @status being set to `MONO_IMAGE_INVALID` if the
+ * image did not contain an assembly reference table.
+
+ */
MonoAssembly *
mono_assembly_load_from (MonoImage *image, const char *fname,
MonoImageOpenStatus *status)
* Parses an assembly qualified type name and assigns the name,
* version, culture and token to the provided assembly name object.
*
- * Returns: true if the name could be parsed.
+ * Returns: TRUE if the name could be parsed.
*/
gboolean
mono_assembly_name_parse (const char *name, MonoAssemblyName *aname)
}
}
+/**
+ * mono_assembly_load_with_partial_name:
+ * @name: an assembly name that is then parsed by `api:mono_assembly_name_parse`.
+ * @status: return status code
+ *
+ * Loads a Mono Assembly from a name. The name is parsed using `api:mono_assembly_name_parse`,
+ * so it might contain a qualified type name, version, culture and token.
+ *
+ * This will load the assembly from the file whose name is derived from the assembly name
+ * by appending the .dll extension.
+ *
+ * The assembly is loaded from either one of the extra Global Assembly Caches specified
+ * by the extra GAC paths (specified by the `MONO_GAC_PREFIX` environment variable) or
+ * if that fails from the GAC.
+ *
+ * Returns: NULL on failure, or a pointer to a MonoAssembly on success.
+ */
MonoAssembly*
mono_assembly_load_with_partial_name (const char *name, MonoImageOpenStatus *status)
{
+ MonoError error;
MonoAssembly *res;
MonoAssemblyName *aname, base_name;
MonoAssemblyName mapped_aname;
res->in_gac = TRUE;
else {
MonoDomain *domain = mono_domain_get ();
- MonoReflectionAssembly *refasm = mono_try_assembly_resolve (domain, mono_string_new (domain, name), NULL, FALSE);
+ MonoReflectionAssembly *refasm;
+
+ refasm = mono_try_assembly_resolve (domain, mono_string_new (domain, name), NULL, FALSE, &error);
+ if (!mono_error_ok (&error)) {
+ g_free (fullname);
+ mono_assembly_name_free (aname);
+ mono_error_raise_exception (&error); /* FIXME don't raise here */
+ }
+
if (refasm)
res = refasm->assembly;
}
if (strstr (aname->name, ".dll")) {
len = strlen (aname->name) - 4;
- name = (gchar *)g_malloc (len);
+ name = (gchar *)g_malloc (len + 1);
strncpy (name, aname->name, len);
+ name[len] = 0;
} else
name = g_strdup (aname->name);
if (strstr (aname->name, ".dll")) {
len = strlen (filename) - 4;
- name = (gchar *)g_malloc (len);
+ name = (gchar *)g_malloc (len + 1);
strncpy (name, aname->name, len);
+ name[len] = 0;
} else {
name = g_strdup (aname->name);
}
mono_assembly_name_free (aname);
g_free (aname);
if (corlib != NULL)
- return corlib;
+ goto return_corlib_and_facades;
// 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);
if (corlib)
- return corlib;
+ goto return_corlib_and_facades;
}
/* Normal case: Load corlib from mono/<version> */
corlib = load_in_path (corlib_file, (const char**)assemblies_path, status, FALSE);
if (corlib) {
g_free (corlib_file);
- return corlib;
+ goto return_corlib_and_facades;
}
}
corlib = load_in_path (corlib_file, default_path, status, FALSE);
g_free (corlib_file);
-
- if (corlib && !strcmp (runtime->framework_version, "4.5"))
- default_path [1] = g_strdup_printf ("%s/mono/4.5/Facades", default_path [0]);
+
+return_corlib_and_facades:
+ if (corlib && !strcmp (runtime->framework_version, "4.5")) // FIXME: stop hardcoding 4.5 here
+ default_path [1] = g_strdup_printf ("%s/Facades", corlib->basedir);
return corlib;
}
return mono_assembly_load_full_internal (aname, NULL, basedir, status, FALSE);
}
+/**
+ * mono_assembly_loaded_full:
+ * @aname: an assembly to look for.
+ * @refonly: Whether this assembly is being opened in "reflection-only" mode.
+ *
+ * This is used to determine if the specified assembly has been loaded
+ * Returns: NULL If the given @aname assembly has not been loaded, or a pointer to
+ * a `MonoAssembly` that matches the `MonoAssemblyName` specified.
+ */
MonoAssembly*
mono_assembly_loaded_full (MonoAssemblyName *aname, gboolean refonly)
{
* mono_assembly_loaded:
* @aname: an assembly to look for.
*
+ * This is used to determine if the specified assembly has been loaded
+
* Returns: NULL If the given @aname assembly has not been loaded, or a pointer to
- * a MonoAssembly that matches the MonoAssemblyName specified.
+ * a `MonoAssembly` that matches the `MonoAssemblyName` specified.
*/
MonoAssembly*
mono_assembly_loaded (MonoAssemblyName *aname)
return mono_image_load_file_for_image (assembly->image, idx);
}
+/**
+ * mono_assembly_foreach:
+ * @func: function to invoke for each assembly loaded
+ * @user_data: data passed to the callback
+ *
+ * Invokes the provided @func callback for each assembly loaded into
+ * the runtime. The first parameter passed to the callback is the
+ * `MonoAssembly*`, and the second parameter is the @user_data.
+ *
+ * This is done for all assemblies loaded in the runtime, not just
+ * those loaded in the current application domain.
+ */
void
mono_assembly_foreach (GFunc func, gpointer user_data)
{