#include "object-internals.h"
#include <mono/metadata/loader.h>
#include <mono/metadata/tabledefs.h>
+#include <mono/metadata/custom-attrs-internals.h>
#include <mono/metadata/metadata-internals.h>
#include <mono/metadata/profiler-private.h>
#include <mono/metadata/class-internals.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 MonoAssembly*
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
}
gboolean
-mono_assembly_fill_assembly_name (MonoImage *image, MonoAssemblyName *aname)
+mono_assembly_fill_assembly_name_full (MonoImage *image, MonoAssemblyName *aname, gboolean copyBlobs)
{
MonoTableInfo *t = &image->tables [MONO_TABLE_ASSEMBLY];
guint32 cols [MONO_ASSEMBLY_SIZE];
aname->hash_len = 0;
aname->hash_value = NULL;
aname->name = mono_metadata_string_heap (image, cols [MONO_ASSEMBLY_NAME]);
+ if (copyBlobs)
+ aname->name = g_strdup (aname->name);
aname->culture = mono_metadata_string_heap (image, cols [MONO_ASSEMBLY_CULTURE]);
+ if (copyBlobs)
+ aname->culture = g_strdup (aname->culture);
aname->flags = cols [MONO_ASSEMBLY_FLAGS];
aname->major = cols [MONO_ASSEMBLY_MAJOR_VERSION];
aname->minor = cols [MONO_ASSEMBLY_MINOR_VERSION];
if (cols [MONO_ASSEMBLY_PUBLIC_KEY]) {
aname->public_key = (guchar*)mono_metadata_blob_heap (image, cols [MONO_ASSEMBLY_PUBLIC_KEY]);
+ if (copyBlobs) {
+ const gchar *pkey_end;
+ int len = mono_metadata_decode_blob_size ((const gchar*) aname->public_key, &pkey_end);
+ pkey_end += len; /* move to end */
+ size_t size = pkey_end - (const gchar*)aname->public_key;
+ guchar *tmp = g_new (guchar, size);
+ memcpy (tmp, aname->public_key, size);
+ aname->public_key = tmp;
+ }
+
}
else
aname->public_key = 0;
return TRUE;
}
+gboolean
+mono_assembly_fill_assembly_name (MonoImage *image, MonoAssemblyName *aname)
+{
+ return mono_assembly_fill_assembly_name_full (image, aname, FALSE);
+}
+
/**
* mono_stringify_assembly_name:
* @aname: the assembly name.
strlen ((char*)aname.public_key_token) == 0 ? "(none)" : (char*)aname.public_key_token, extra_msg);
g_free (extra_msg);
- } else if (!image->assembly->ref_only) {
- MonoError error;
- if (mono_assembly_get_reference_assembly_attribute (reference, &error)) {
- mono_trace (G_LOG_LEVEL_WARNING, MONO_TRACE_ASSEMBLY, "The following reference assembly assembly referenced from %s was not loaded. Reference assemblies should not be loaded for execution. They can only be loaded in the Reflection-only loader context:\n"
- " Assembly: %s (assemblyref_index=%d)\n"
- " Version: %d.%d.%d.%d\n"
- " Public Key: %s\n",
- image->name, aname.name, index,
- aname.major, aname.minor, aname.build, aname.revision,
- strlen ((char*)aname.public_key_token) == 0 ? "(none)" : (char*)aname.public_key_token);
- reference = NULL; /* don't load reference assemblies for execution */
- }
- if (!is_ok (&error)) {
- reference = NULL;
- mono_error_cleanup (&error);
- }
}
mono_assemblies_lock ();
image->assembly->aname.name, image->assembly, reference->aname.name, reference, reference->ref_count);
} else {
if (image->assembly)
- mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Failed to load assembly %s[%p]\n",
+ mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Failed to load assembly %s[%p].",
image->assembly->aname.name, image->assembly);
}
{
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;
}
if (ass->friend_assembly_names_inited)
return;
- attrs = mono_custom_attrs_from_assembly_checked (ass, &error);
+ attrs = mono_custom_attrs_from_assembly_checked (ass, FALSE, &error);
mono_error_assert_ok (&error);
if (!attrs) {
mono_assemblies_lock ();
mono_assemblies_unlock ();
}
+struct HasReferenceAssemblyAttributeIterData {
+ gboolean has_attr;
+};
+
+static gboolean
+has_reference_assembly_attribute_iterator (MonoImage *image, guint32 typeref_scope_token, const char *nspace, const char *name, guint32 method_token, gpointer user_data)
+{
+ gboolean stop_scanning = FALSE;
+ struct HasReferenceAssemblyAttributeIterData *iter_data = (struct HasReferenceAssemblyAttributeIterData*)user_data;
+
+ if (!strcmp (name, "ReferenceAssemblyAttribute") && !strcmp (nspace, "System.Runtime.CompilerServices")) {
+ /* Note we don't check the assembly name, same as coreCLR. */
+ iter_data->has_attr = TRUE;
+ stop_scanning = TRUE;
+ }
+
+ return stop_scanning;
+}
/**
- * mono_assembly_get_reference_assembly_attribute:
+ * mono_assembly_has_reference_assembly_attribute:
* @assembly: a MonoAssembly
* @error: set on error.
*
* On error returns FALSE and sets @error.
*/
gboolean
-mono_assembly_get_reference_assembly_attribute (MonoAssembly *assembly, MonoError *error)
+mono_assembly_has_reference_assembly_attribute (MonoAssembly *assembly, MonoError *error)
{
mono_error_init (error);
- 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 ();
- gboolean result = FALSE;
- for (int i = 0; i < attrs->num_attrs; ++i) {
- MonoCustomAttrEntry *attr = &attrs->attrs [i];
- if (attr->ctor && attr->ctor->klass && attr->ctor->klass == ref_asm_class) {
- result = TRUE;
- break;
- }
- }
- mono_custom_attrs_free (attrs);
- return result;
+ /*
+ * This might be called during assembly loading, so do everything using the low-level
+ * metadata APIs.
+ */
+
+ struct HasReferenceAssemblyAttributeIterData iter_data = { FALSE };
+
+ mono_assembly_metadata_foreach_custom_attr (assembly, &has_reference_assembly_attribute_iterator, &iter_data);
+
+ return iter_data.has_attr;
}
/**
}
}
+ /* 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) {
+ MonoError refasm_error;
+ if (mono_assembly_has_reference_assembly_attribute (ass, &refasm_error)) {
+ 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);
+ }
+
mono_assemblies_lock ();
if (image->assembly) {
- /*
+ /*
* This means another thread has already loaded the assembly, but not yet
* called the load hooks so the search hook can't find the assembly.
*/
return ass2;
}
+ mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Prepared to set up assembly '%s' (%s)", ass->aname.name, image->name);
+
image->assembly = ass;
loaded_assemblies = g_list_prepend (loaded_assemblies, ass);
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*