#include <string.h>
#include <stdlib.h>
#include "assembly.h"
+#include "assembly-internals.h"
#include "image.h"
+#include "image-internals.h"
#include "object-internals.h"
#include <mono/metadata/loader.h>
#include <mono/metadata/tabledefs.h>
/* Class lazy loading functions */
static GENERATE_TRY_GET_CLASS_WITH_CACHE (internals_visible, System.Runtime.CompilerServices, InternalsVisibleToAttribute)
+static GENERATE_TRY_GET_CLASS_WITH_CACHE (reference_assembly, System.Runtime.CompilerServices, ReferenceAssemblyAttribute)
static MonoAssembly*
mono_assembly_invoke_search_hook_internal (MonoAssemblyName *aname, MonoAssembly *requesting, gboolean refonly, gboolean postload);
static MonoBoolean
mono_assembly_is_in_gac (const gchar *filanem);
+static MonoAssembly*
+prevent_reference_assembly_from_running (MonoAssembly* candidate, gboolean refonly);
+
static gchar*
encode_public_tok (const guchar *token, gint32 len)
{
return default_path [0];
}
+/**
+ * mono_native_getrootdir:
+ *
+ * Obtains the root directory used for looking up native libs (.so, .dylib).
+ *
+ * Returns: a string with the directory, this string should be freed by
+ * the caller.
+ */
+gchar *
+mono_native_getrootdir (void)
+{
+ gchar* fullpath = g_build_path (G_DIR_SEPARATOR_S, mono_assembly_getrootdir (), mono_config_get_reloc_lib_dir(), NULL);
+ return fullpath;
+}
+
/**
* mono_set_dirs:
* @assembly_dir: the base directory for assemblies
#define WINFX_KEY "31bf3856ad364e35"
#define ECMA_KEY "b77a5c561934e089"
#define MSFINAL_KEY "b03f5f7f11d50a3a"
+#define COMPACTFRAMEWORK_KEY "969db8053d3322ac"
typedef struct {
const char *name;
} KeyRemapEntry;
static KeyRemapEntry key_remap_table[] = {
+ { "CustomMarshalers", COMPACTFRAMEWORK_KEY, MSFINAL_KEY },
{ "Microsoft.CSharp", WINFX_KEY, MSFINAL_KEY },
+ { "Microsoft.VisualBasic", COMPACTFRAMEWORK_KEY, MSFINAL_KEY },
{ "System", SILVERLIGHT_KEY, ECMA_KEY },
+ { "System", COMPACTFRAMEWORK_KEY, ECMA_KEY },
{ "System.ComponentModel.Composition", WINFX_KEY, ECMA_KEY },
{ "System.ComponentModel.DataAnnotations", "ddd0da4d3e678217", WINFX_KEY },
{ "System.Core", SILVERLIGHT_KEY, ECMA_KEY },
+ { "System.Core", COMPACTFRAMEWORK_KEY, ECMA_KEY },
+ { "System.Data", COMPACTFRAMEWORK_KEY, ECMA_KEY },
+ { "System.Data.DataSetExtensions", COMPACTFRAMEWORK_KEY, ECMA_KEY },
+ { "System.Drawing", COMPACTFRAMEWORK_KEY, MSFINAL_KEY },
+ { "System.Messaging", COMPACTFRAMEWORK_KEY, MSFINAL_KEY },
// FIXME: MS uses MSFINAL_KEY for .NET 4.5
{ "System.Net", SILVERLIGHT_KEY, MSFINAL_KEY },
{ "System.Numerics", WINFX_KEY, ECMA_KEY },
{ "System.Runtime.Serialization", SILVERLIGHT_KEY, ECMA_KEY },
+ { "System.Runtime.Serialization", COMPACTFRAMEWORK_KEY, ECMA_KEY },
{ "System.ServiceModel", WINFX_KEY, ECMA_KEY },
+ { "System.ServiceModel", COMPACTFRAMEWORK_KEY, ECMA_KEY },
{ "System.ServiceModel.Web", SILVERLIGHT_KEY, WINFX_KEY },
+ { "System.Web.Services", COMPACTFRAMEWORK_KEY, MSFINAL_KEY },
{ "System.Windows", SILVERLIGHT_KEY, MSFINAL_KEY },
+ { "System.Windows.Forms", COMPACTFRAMEWORK_KEY, ECMA_KEY },
{ "System.Xml", SILVERLIGHT_KEY, ECMA_KEY },
+ { "System.Xml", COMPACTFRAMEWORK_KEY, ECMA_KEY },
{ "System.Xml.Linq", WINFX_KEY, ECMA_KEY },
+ { "System.Xml.Linq", COMPACTFRAMEWORK_KEY, ECMA_KEY },
{ "System.Xml.Serialization", WINFX_KEY, ECMA_KEY }
};
aname.major, aname.minor, aname.build, aname.revision,
strlen ((char*)aname.public_key_token) == 0 ? "(none)" : (char*)aname.public_key_token, extra_msg);
g_free (extra_msg);
+
}
mono_assemblies_lock ();
{
int i;
char *name;
+ gchar *lowercase_filename;
MonoImage *image = NULL;
-
+ gboolean is_satellite = FALSE;
/*
* we do a very simple search for bundled assemblies: it's not a general
* purpose assembly loading mechanism.
if (!bundles)
return NULL;
+ lowercase_filename = g_utf8_strdown (filename, -1);
+ is_satellite = g_str_has_suffix (lowercase_filename, ".resources.dll");
+ g_free (lowercase_filename);
name = g_path_get_basename (filename);
-
mono_assemblies_lock ();
for (i = 0; !image && bundles [i]; ++i) {
- if (strcmp (bundles [i]->name, name) == 0) {
+ if (strcmp (bundles [i]->name, is_satellite ? filename : name) == 0) {
image = mono_image_open_from_data_with_name ((char*)bundles [i]->data, bundles [i]->size, FALSE, status, refonly, name);
break;
}
mono_assemblies_unlock ();
if (image) {
mono_image_addref (image);
- mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Assembly Loader loaded assembly from bundle: '%s'.", name);
+ mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Assembly Loader loaded assembly from bundle: '%s'.", is_satellite ? filename : name);
g_free (name);
return image;
}
mono_assemblies_unlock ();
}
+
+/**
+ * mono_assembly_has_reference_assembly_attribute:
+ * @assembly: a MonoAssembly
+ * @error: set on error.
+ *
+ * Returns TRUE if @assembly has the System.Runtime.CompilerServices.ReferenceAssemblyAttribute set.
+ * On error returns FALSE and sets @error.
+ */
+gboolean
+mono_assembly_has_reference_assembly_attribute (MonoAssembly *assembly, MonoError *error)
+{
+ mono_error_init (error);
+
+/* TODO: mono_custom_attrs_from_assembly_checked returns NULL if a
+ * single assembly is missing. The custom attr we want is from
+ * corlib, however, so we need a more robust version that doesn't care
+ * about missing attributes.
+ */
+#if 0
+ MonoCustomAttrInfo *attrs = mono_custom_attrs_from_assembly_checked (assembly, error);
+ return_val_if_nok (error, FALSE);
+ if (!attrs)
+ return FALSE;
+ MonoClass *ref_asm_class = mono_class_try_get_reference_assembly_class ();
+ g_assert (ref_asm_class != NULL && ref_asm_class != mono_defaults.object_class && !strcmp(ref_asm_class->name, "ReferenceAssemblyAttribute") );
+ gboolean result = mono_custom_attrs_has_attr (attrs, ref_asm_class);
+ mono_custom_attrs_free (attrs);
+ return result;
+#else
+ return FALSE;
+#endif
+}
+
/**
* mono_assembly_open:
* @filename: Opens the assembly pointed out by this name
return ass2;
}
+ mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Prepared to set up assembly '%s' (%s)", ass->aname.name, image->name);
+
+ /* We need to check for ReferenceAssmeblyAttribute before we
+ * mark the assembly as loaded and before we fire the load
+ * hook. Otherwise mono_domain_fire_assembly_load () in
+ * appdomain.c will cache a mapping from the assembly name to
+ * this image and we won't be able to look for a different
+ * candidate. */
+
+ if (!refonly && strcmp (ass->aname.name, "mscorlib") != 0) {
+ /* Don't check for reference assmebly attribute for
+ * corlib here because if corlib isn't loaded yet,
+ * it's too early to set up the
+ * ReferenceAssemblyAttribute class. We check that
+ * we're not running with a reference corlib in
+ * mono_init_internal().
+ */
+ MonoError refasm_error;
+ if (mono_assembly_has_reference_assembly_attribute (ass, &refasm_error)) {
+ mono_assemblies_unlock ();
+ mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Image for assembly '%s' (%s) has ReferenceAssemblyAttribute, skipping", ass->aname.name, image->name);
+ g_free (ass);
+ g_free (base_dir);
+ mono_image_close (image);
+ *status = MONO_IMAGE_IMAGE_INVALID;
+ return NULL;
+ }
+ mono_error_cleanup (&refasm_error);
+ }
+
image->assembly = ass;
loaded_assemblies = g_list_prepend (loaded_assemblies, ass);
g_free ((void *) aname->name);
g_free ((void *) aname->culture);
g_free ((void *) aname->hash_value);
+ g_free ((guint8*) aname->public_key);
}
static gboolean
if (!g_ascii_strcasecmp (retargetable, "yes")) {
flags |= ASSEMBLYREF_RETARGETABLE_FLAG;
} else if (g_ascii_strcasecmp (retargetable, "no")) {
- free (retargetable_uq);
+ g_free (retargetable_uq);
goto cleanup_and_fail;
}
- free (retargetable_uq);
+ g_free (retargetable_uq);
tmp++;
continue;
}
else if (!g_ascii_strcasecmp (procarch, "AMD64"))
arch = MONO_PROCESSOR_ARCHITECTURE_AMD64;
else {
- free (procarch_uq);
+ g_free (procarch_uq);
goto cleanup_and_fail;
}
- free (procarch_uq);
+ g_free (procarch_uq);
tmp++;
continue;
}
key_uq == NULL ? key : key_uq,
flags, arch, aname, save_public_key);
- free (dllname_uq);
- free (version_uq);
- free (culture_uq);
- free (token_uq);
- free (key_uq);
+ g_free (dllname_uq);
+ g_free (version_uq);
+ g_free (culture_uq);
+ g_free (token_uq);
+ g_free (key_uq);
g_strfreev (parts);
return res;
mono_domain_lock (domain);
if (!domain->assembly_bindings_parsed) {
gchar *domain_config_file_name = mono_string_to_utf8_checked (domain->setup->configuration_file, &error);
- mono_error_raise_exception (&error); /* FIXME don't raise here */
+ /* expect this to succeed because mono_domain_set_options_from_config () did
+ * the same thing when the domain was created. */
+ mono_error_assert_ok (&error);
gchar *domain_config_file_path = mono_portability_find_file (domain_config_file_name, TRUE);
return corlib;
}
+static MonoAssembly*
+prevent_reference_assembly_from_running (MonoAssembly* candidate, gboolean refonly)
+{
+ MonoError refasm_error;
+ mono_error_init (&refasm_error);
+ if (candidate && !refonly && mono_assembly_has_reference_assembly_attribute (candidate, &refasm_error)) {
+ candidate = NULL;
+ }
+ mono_error_cleanup (&refasm_error);
+ return candidate;
+}
+
+
MonoAssembly*
mono_assembly_load_full_nosearch (MonoAssemblyName *aname,
const char *basedir,
{
MonoAssembly *result = mono_assembly_load_full_nosearch (aname, basedir, status, refonly);
- if (!result)
+ if (!result) {
/* Try a postload search hook */
result = mono_assembly_invoke_search_hook_internal (aname, requesting, refonly, TRUE);
+ result = prevent_reference_assembly_from_running (result, refonly);
+ }
return result;
}
MonoImage*
mono_assembly_load_module (MonoAssembly *assembly, guint32 idx)
{
- return mono_image_load_file_for_image (assembly->image, idx);
+ MonoError error;
+ MonoImage *result = mono_assembly_load_module_checked (assembly, idx, &error);
+ mono_error_assert_ok (&error);
+ return result;
+}
+
+MONO_API MonoImage*
+mono_assembly_load_module_checked (MonoAssembly *assembly, uint32_t idx, MonoError *error)
+{
+ return mono_image_load_file_for_image_checked (assembly->image, idx, error);
}
+
/**
* mono_assembly_foreach:
* @func: function to invoke for each assembly loaded