#include <mono/io-layer/io-layer.h>
#include <mono/utils/mono-uri.h>
#include <mono/metadata/mono-config.h>
+#include <mono/metadata/mono-config-dirs.h>
#include <mono/utils/mono-digest.h>
#include <mono/utils/mono-logger-internal.h>
#include <mono/utils/mono-path.h>
static GSList *loaded_assembly_bindings = NULL;
static MonoAssembly*
-mono_assembly_invoke_search_hook_internal (MonoAssemblyName *aname, gboolean refonly, gboolean postload);
+mono_assembly_invoke_search_hook_internal (MonoAssemblyName *aname, MonoAssembly *requesting, gboolean refonly, gboolean postload);
+static MonoAssembly*
+mono_assembly_load_full_internal (MonoAssemblyName *aname, MonoAssembly *requesting, const char *basedir, MonoImageOpenStatus *status, gboolean refonly);
static MonoBoolean
mono_assembly_is_in_gac (const gchar *filanem);
void
mono_set_dirs (const char *assembly_dir, const char *config_dir)
{
-#if defined (MONO_ASSEMBLIES)
if (assembly_dir == NULL)
- assembly_dir = MONO_ASSEMBLIES;
-#endif
-#if defined (MONO_CFG_DIR)
+ assembly_dir = mono_config_get_assemblies_dir ();
if (config_dir == NULL)
- config_dir = MONO_CFG_DIR;
-#endif
+ config_dir = mono_config_get_cfg_dir ();
mono_assembly_setrootdir (assembly_dir);
mono_set_config_dir (config_dir);
}
static void
fallback (void)
{
- mono_set_dirs (MONO_ASSEMBLIES, MONO_CFG_DIR);
+ mono_set_dirs (mono_config_get_assemblies_dir (), mono_config_get_cfg_dir ());
}
static G_GNUC_UNUSED void
char *base;
char *config, *lib, *mono;
struct stat buf;
+ const char *bindir;
/*
* Only /usr prefix is treated specially
*/
- if (strncmp (exe, MONO_BINDIR, strlen (MONO_BINDIR)) == 0 || (base = compute_base (exe)) == NULL){
+ bindir = mono_config_get_bin_dir ();
+ g_assert (bindir);
+ if (strncmp (exe, bindir, strlen (bindir)) == 0 || (base = compute_base (exe)) == NULL){
fallback ();
return;
}
if (image->assembly && image->assembly->ref_only) {
/* We use the loaded corlib */
if (!strcmp (aname.name, "mscorlib"))
- reference = mono_assembly_load_full (&aname, image->assembly->basedir, &status, FALSE);
+ reference = mono_assembly_load_full_internal (&aname, image->assembly, image->assembly->basedir, &status, FALSE);
else {
reference = mono_assembly_loaded_full (&aname, TRUE);
if (!reference)
/* Try a postload search hook */
- reference = mono_assembly_invoke_search_hook_internal (&aname, TRUE, TRUE);
+ reference = mono_assembly_invoke_search_hook_internal (&aname, image->assembly, TRUE, TRUE);
}
/*
* The second load attempt has the basedir set to keep compatibility with the old mono behavior, for
* example bug-349190.2.cs and who knows how much more code in the wild.
*/
- reference = mono_assembly_load (&aname, NULL, &status);
+ reference = mono_assembly_load_full_internal (&aname, image->assembly, NULL, &status, FALSE);
if (!reference && image->assembly)
- reference = mono_assembly_load (&aname, image->assembly->basedir, &status);
+ reference = mono_assembly_load_full_internal (&aname, image->assembly, image->assembly->basedir, &status, FALSE);
}
if (reference == NULL){
AssemblySearchHook *assembly_search_hook = NULL;
static MonoAssembly*
-mono_assembly_invoke_search_hook_internal (MonoAssemblyName *aname, gboolean refonly, gboolean postload)
+mono_assembly_invoke_search_hook_internal (MonoAssemblyName *aname, MonoAssembly *requesting, gboolean refonly, gboolean postload)
{
AssemblySearchHook *hook;
for (hook = assembly_search_hook; hook; hook = hook->next) {
if ((hook->refonly == refonly) && (hook->postload == postload)) {
- MonoAssembly *ass = hook->func (aname, hook->user_data);
+ MonoAssembly *ass;
+ /**
+ * A little explanation is in order here.
+ *
+ * The default postload search hook needs to know the requesting assembly to report it to managed code.
+ * The embedding API exposes a search hook that doesn't take such argument.
+ *
+ * The original fix would call the default search hook before all the registered ones and pass
+ * the requesting assembly to it. It works but broke a very suddle embedding API aspect that some users
+ * rely on. Which is the ordering between user hooks and the default runtime hook.
+ *
+ * Registering the hook after mono_jit_init would let your hook run before the default one and
+ * when using it to handle non standard app layouts this could save your app from a massive amount
+ * of syscalls that the default hook does when probing all sorts of places. Slow targets with horrible IO
+ * are all using this trick and if we broke this assumption they would be very disapointed at us.
+ *
+ * So what's the fix? We register the default hook using regular means and special case it when iterating
+ * over the registered hooks. This preserves ordering and enables managed resolve hooks to get the requesting
+ * assembly.
+ */
+ if (hook->func == (void*)mono_domain_assembly_postload_search)
+ ass = mono_domain_assembly_postload_search (aname, requesting, refonly);
+ else
+ ass = hook->func (aname, hook->user_data);
if (ass)
return ass;
}
MonoAssembly*
mono_assembly_invoke_search_hook (MonoAssemblyName *aname)
{
- return mono_assembly_invoke_search_hook_internal (aname, FALSE, FALSE);
+ return mono_assembly_invoke_search_hook_internal (aname, NULL, FALSE, FALSE);
}
static void
MonoCustomAttrEntry *attr = &attrs->attrs [i];
MonoAssemblyName *aname;
const gchar *data;
- guint slen;
/* Do some sanity checking */
if (!attr->ctor || attr->ctor->klass != mono_defaults.internals_visible_class)
continue;
/* 0xFF means null string, see custom attr format */
if (data [0] != 1 || data [1] != 0 || (data [2] & 0xFF) == 0xFF)
continue;
- slen = mono_metadata_decode_value (data + 2, &data);
+ mono_metadata_decode_value (data + 2, &data);
aname = g_new0 (MonoAssemblyName, 1);
/*g_print ("friend ass: %s\n", data);*/
if (mono_assembly_name_parse_full (data, aname, TRUE, NULL, NULL)) {
* assemblies lock.
*/
if (ass->aname.name) {
- ass2 = mono_assembly_invoke_search_hook_internal (&ass->aname, refonly, FALSE);
+ ass2 = mono_assembly_invoke_search_hook_internal (&ass->aname, NULL, refonly, FALSE);
if (ass2) {
g_free (ass);
g_free (base_dir);
res->in_gac = TRUE;
else {
MonoDomain *domain = mono_domain_get ();
- MonoReflectionAssembly *refasm = mono_try_assembly_resolve (domain, mono_string_new (domain, name), FALSE);
+ MonoReflectionAssembly *refasm = mono_try_assembly_resolve (domain, mono_string_new (domain, name), NULL, FALSE);
if (refasm)
res = refasm->assembly;
}
return result;
}
+MonoAssembly*
+mono_assembly_load_full_internal (MonoAssemblyName *aname, MonoAssembly *requesting, const char *basedir, MonoImageOpenStatus *status, gboolean refonly)
+{
+ MonoAssembly *result = mono_assembly_load_full_nosearch (aname, basedir, status, refonly);
+
+ if (!result)
+ /* Try a postload search hook */
+ result = mono_assembly_invoke_search_hook_internal (aname, requesting, refonly, TRUE);
+ return result;
+}
+
/**
* mono_assembly_load_full:
* @aname: A MonoAssemblyName with the assembly name to load.
MonoAssembly*
mono_assembly_load_full (MonoAssemblyName *aname, const char *basedir, MonoImageOpenStatus *status, gboolean refonly)
{
- MonoAssembly *result = mono_assembly_load_full_nosearch (aname, basedir, status, refonly);
-
- if (!result)
- /* Try a postload search hook */
- result = mono_assembly_invoke_search_hook_internal (aname, refonly, TRUE);
- return result;
+ return mono_assembly_load_full_internal (aname, NULL, basedir, status, refonly);
}
/**
MonoAssembly*
mono_assembly_load (MonoAssemblyName *aname, const char *basedir, MonoImageOpenStatus *status)
{
- return mono_assembly_load_full (aname, basedir, status, FALSE);
+ return mono_assembly_load_full_internal (aname, NULL, basedir, status, FALSE);
}
-
+
MonoAssembly*
mono_assembly_loaded_full (MonoAssemblyName *aname, gboolean refonly)
{
aname = mono_assembly_remap_version (aname, &maped_aname);
- res = mono_assembly_invoke_search_hook_internal (aname, refonly, FALSE);
+ res = mono_assembly_invoke_search_hook_internal (aname, NULL, refonly, FALSE);
return res;
}