* Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
* Copyright 2004-2009 Novell, Inc (http://www.novell.com)
* Copyright 2012 Xamarin Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
*/
#include <config.h>
#ifdef HAVE_ALLOCA_H
done:
/* Generic case, should be avoided for when a better error is possible. */
if (!res && mono_error_ok (error)) {
- if (mono_loader_get_last_error ()) { /*FIXME plug the above to not leak errors*/
- mono_error_set_from_loader_error (error);
- } else {
- char *name = mono_class_name_from_token (image, type_token);
- char *assembly = mono_assembly_name_from_token (image, type_token);
- mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
- }
+ char *name = mono_class_name_from_token (image, type_token);
+ char *assembly = mono_assembly_name_from_token (image, type_token);
+ mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
}
- mono_loader_assert_no_error ();
return res;
}
result->sre_method = FALSE;
result->signature = NULL;
- if (!context->method_inst) {
+ if (iresult->context.method_inst) {
/* Set the generic_container of the result to the generic_container of method */
MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
- if (generic_container) {
+ if (generic_container && iresult->context.method_inst == generic_container->context.method_inst) {
result->is_generic = 1;
mono_method_set_generic_container (result, generic_container);
}
mono_error_set_type_load_class (error, klass, "Could not find base type");
fail:
- mono_loader_assert_no_error ();
return NULL;
}
}
}
+void
+mono_error_set_for_class_failure (MonoError *oerror, MonoClass *klass)
+{
+ gpointer exception_data = mono_class_get_exception_data (klass);
+
+ switch (mono_class_get_failure(klass)) {
+ case MONO_EXCEPTION_TYPE_LOAD: {
+ mono_error_set_type_load_class (oerror, klass, "Error Loading class");
+ return;
+ }
+ case MONO_EXCEPTION_MISSING_METHOD: {
+ char *class_name = (char *)exception_data;
+ char *member_name = class_name + strlen (class_name) + 1;
+
+ mono_error_set_method_load (oerror, klass, member_name, "Error Loading Method");
+ return;
+ }
+ case MONO_EXCEPTION_MISSING_FIELD: {
+ char *class_name = (char *)exception_data;
+ char *member_name = class_name + strlen (class_name) + 1;
+
+ mono_error_set_field_load (oerror, klass, member_name, "Error Loading Field");
+ return;
+ }
+ case MONO_EXCEPTION_FILE_NOT_FOUND: {
+ char *msg_format = (char *)exception_data;
+ char *assembly_name = msg_format + strlen (msg_format) + 1;
+ char *msg = g_strdup_printf (msg_format, assembly_name);
+
+ mono_error_set_assembly_load (oerror, assembly_name, msg);
+ return;
+ }
+ case MONO_EXCEPTION_BAD_IMAGE: {
+ mono_error_set_bad_image (oerror, NULL, (const char *)exception_data);
+ return;
+ }
+ case MONO_EXCEPTION_INVALID_PROGRAM: {
+ mono_error_set_invalid_program (oerror, (const char *)exception_data);
+ return;
+ }
+ default: {
+ g_assert_not_reached ();
+ }
+ }
+}
+
+
/*
* mono_class_alloc:
*
int i, blittable = TRUE;
guint32 real_size = 0;
guint32 packing_size = 0;
+ int instance_size;
gboolean explicit_size;
MonoClassField *field;
MonoGenericContainer *container = NULL;
}
}
- klass->instance_size = 0;
+ instance_size = 0;
if (!klass->rank)
klass->sizes.class_size = 0;
return;
}
}
- klass->instance_size += klass->parent->instance_size;
+ instance_size += klass->parent->instance_size;
klass->min_align = klass->parent->min_align;
/* we use |= since it may have been set already */
klass->has_references |= klass->parent->has_references;
blittable = klass->parent->blittable;
} else {
- klass->instance_size = sizeof (MonoObject);
+ instance_size = sizeof (MonoObject);
klass->min_align = 1;
}
return;
}
klass->packing_size = packing_size;
- real_size += klass->instance_size;
+ real_size += instance_size;
}
if (!top) {
if (explicit_size && real_size) {
- klass->instance_size = MAX (real_size, klass->instance_size);
+ instance_size = MAX (real_size, instance_size);
}
klass->blittable = blittable;
+ if (!klass->instance_size)
+ klass->instance_size = instance_size;
mono_memory_barrier ();
klass->size_inited = 1;
klass->fields_inited = 1;
return;
}
if (explicit_size && real_size) {
- klass->instance_size = MAX (real_size, klass->instance_size);
+ instance_size = MAX (real_size, instance_size);
}
if (mono_class_has_failure (klass))
return;
- mono_class_layout_fields (klass);
+ mono_class_layout_fields (klass, instance_size);
/*valuetypes can't be neither bigger than 1Mb or empty. */
if (klass->valuetype && (klass->instance_size <= 0 || klass->instance_size > (0x100000 + sizeof (MonoObject))))
/*
* mono_class_layout_fields:
* @class: a class
+ * @instance_size: base instance size
*
* Compute the placement of fields inside an object or struct, according to
* the layout rules and set the following fields in @class:
* LOCKING: this is supposed to be called with the loader lock held.
*/
void
-mono_class_layout_fields (MonoClass *klass)
+mono_class_layout_fields (MonoClass *klass, int instance_size)
{
int i;
const int top = klass->field.count;
/*
* Compute field layout and total size (not considering static fields)
*/
-
switch (layout) {
case TYPE_ATTRIBUTE_AUTO_LAYOUT:
case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
real_size = field->offset + size;
}
- klass->instance_size = MAX (real_size, klass->instance_size);
+ instance_size = MAX (real_size, instance_size);
- if (klass->instance_size & (klass->min_align - 1)) {
- klass->instance_size += klass->min_align - 1;
- klass->instance_size &= ~(klass->min_align - 1);
+ if (instance_size & (klass->min_align - 1)) {
+ instance_size += klass->min_align - 1;
+ instance_size &= ~(klass->min_align - 1);
}
}
break;
g_free (ref_bitmap);
}
- klass->instance_size = MAX (real_size, klass->instance_size);
- if (klass->instance_size & (klass->min_align - 1)) {
- klass->instance_size += klass->min_align - 1;
- klass->instance_size &= ~(klass->min_align - 1);
+ instance_size = MAX (real_size, instance_size);
+ if (instance_size & (klass->min_align - 1)) {
+ instance_size += klass->min_align - 1;
+ instance_size &= ~(klass->min_align - 1);
}
break;
}
* unaligned accesses otherwise. See #78990 for a testcase.
*/
if (mono_align_small_structs) {
- if (klass->instance_size <= sizeof (MonoObject) + sizeof (gpointer))
- klass->min_align = MAX (klass->min_align, klass->instance_size - sizeof (MonoObject));
+ if (instance_size <= sizeof (MonoObject) + sizeof (gpointer))
+ klass->min_align = MAX (klass->min_align, instance_size - sizeof (MonoObject));
}
}
+ if (klass->instance_size && !klass->image->dynamic) {
+ /* Might be already set using cached info */
+ g_assert (klass->instance_size == instance_size);
+ } else {
+ klass->instance_size = instance_size;
+ }
mono_memory_barrier ();
klass->size_inited = 1;
static void
mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup)
{
+ MonoError error;
MonoMethod **overrides;
MonoGenericContext *context;
guint32 type_token;
* This is true since we don't do layout all over again for them, we simply inflate
* the layout of the parent.
*/
- mono_reflection_get_dynamic_overrides (klass, &overrides, &onum);
+ mono_reflection_get_dynamic_overrides (klass, &overrides, &onum, &error);
+ if (!is_ok (&error)) {
+ mono_loader_unlock ();
+ g_list_remove (in_setup, klass);
+ mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf("Could not load list of method overrides due to %s", mono_error_get_message (&error)));
+ mono_error_cleanup (&error);
+ return;
+ }
} else {
/* The following call fails if there are missing methods in the type */
/* FIXME it's probably a good idea to avoid this for generic instances. */
return s;
}
-static void
-set_failure_from_loader_error (MonoClass *klass, MonoLoaderError *error)
-{
- gpointer exception_data = NULL;
-
- switch (error->exception_type) {
- case MONO_EXCEPTION_TYPE_LOAD:
- exception_data = concat_two_strings_with_zero (klass->image, error->class_name, error->assembly_name);
- break;
-
- case MONO_EXCEPTION_MISSING_METHOD:
- exception_data = concat_two_strings_with_zero (klass->image, error->class_name, error->member_name);
- break;
-
- case MONO_EXCEPTION_MISSING_FIELD: {
- const char *name_space = error->klass->name_space ? error->klass->name_space : NULL;
- const char *class_name;
-
- if (name_space)
- class_name = g_strdup_printf ("%s.%s", name_space, error->klass->name);
- else
- class_name = error->klass->name;
-
- exception_data = concat_two_strings_with_zero (klass->image, class_name, error->member_name);
-
- if (name_space)
- g_free ((void*)class_name);
- break;
- }
-
- case MONO_EXCEPTION_FILE_NOT_FOUND: {
- const char *msg;
-
- if (error->ref_only)
- msg = "Cannot resolve dependency to assembly '%s' because it has not been preloaded. When using the ReflectionOnly APIs, dependent assemblies must be pre-loaded or loaded on demand through the ReflectionOnlyAssemblyResolve event.";
- else
- msg = "Could not load file or assembly '%s' or one of its dependencies.";
-
- exception_data = concat_two_strings_with_zero (klass->image, msg, error->assembly_name);
- break;
- }
-
- case MONO_EXCEPTION_BAD_IMAGE:
- exception_data = error->msg;
- break;
-
- default :
- g_assert_not_reached ();
- }
-
- mono_class_set_failure (klass, error->exception_type, exception_data);
-}
-
/**
* mono_class_init:
* @class: the class to initialize
else
if (!klass->size_inited){
mono_class_setup_fields (klass);
- if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
+ if (mono_class_has_failure (klass))
goto leave;
}
mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
goto leave;
}
- if (mono_loader_get_last_error ())
- goto leave;
if (!klass->parent->vtable_size) {
/* FIXME: Get rid of this somehow */
mono_class_setup_vtable (klass->parent);
mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
goto leave;
}
- if (mono_loader_get_last_error ())
- goto leave;
}
first_iface_slot = klass->parent->vtable_size;
if (mono_class_need_stelemref_method (klass))
if (mono_security_core_clr_enabled ())
mono_security_core_clr_check_inheritance (klass);
- if (mono_loader_get_last_error ()) {
- if (!mono_class_has_failure (klass)) {
- set_failure_from_loader_error (klass, mono_loader_get_last_error ());
- }
- mono_loader_clear_error ();
- }
-
if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass))
mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Invalid generic instantiation"));
* ignores overrides.
*/
mono_class_setup_vtable (klass);
- if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
+ if (mono_class_has_failure (klass))
cmethod = NULL;
else
cmethod = klass->vtable [finalize_slot];
if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
- mono_loader_assert_no_error ();
return NULL;
}
if ((klass = (MonoClass *)mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
mono_loader_unlock ();
- mono_loader_assert_no_error ();
return klass;
}
mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
mono_loader_unlock ();
mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
- mono_loader_assert_no_error ();
return NULL;
}
}
mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
mono_loader_unlock ();
mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
- mono_loader_assert_no_error ();
return NULL;
}
klass->cast_class = klass->element_class = mono_class_from_mono_type (enum_basetype);
mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Could not load generic parameter constrains due to %s", mono_error_get_message (error)));
mono_loader_unlock ();
mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
- mono_loader_assert_no_error ();
return NULL;
}
mono_loader_unlock ();
mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
- mono_loader_assert_no_error ();
return klass;
mono_class_setup_mono_type (klass);
mono_loader_unlock ();
mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
- mono_loader_assert_no_error ();
return NULL;
}
MonoType *inflated = inflate_generic_type (NULL, t, context, error);
if (!mono_error_ok (error)) {
- mono_loader_assert_no_error ();
return NULL;
}
mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
return NULL;
}
- klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, NULL); /*FIXME proper error handling*/
+ klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, NULL, error);
goto done;
}
mono_error_init (error);
//FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
- if (image_is_dynamic (image))
- return mono_class_get_type ((MonoClass *)mono_lookup_dynamic_token (image, type_token, context));
+ if (image_is_dynamic (image)) {
+ MonoClass *klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, context, error);
+ return_val_if_nok (error, NULL);
+ return mono_class_get_type (klass);
+ }
if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
MonoClass *klass = mono_class_get_checked (image, type_token, error);
if (!klass) {
- mono_loader_assert_no_error ();
return NULL;
}
type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
if (!type) {
- mono_loader_assert_no_error ();
return NULL;
}
mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
gboolean check_interfaces)
{
-/*FIXME test for interfaces with variant generic arguments*/
+ /* FIXME test for interfaces with variant generic arguments */
+ mono_class_init (klass);
+ mono_class_init (klassc);
if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
gboolean
mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
{
+ MonoError error;
/*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
if (!klass->inited)
mono_class_init (klass);
}
/* interface_offsets might not be set for dynamic classes */
- if (oklass->ref_info_handle && !oklass->interface_bitmap)
+ if (oklass->ref_info_handle && !oklass->interface_bitmap) {
/*
* oklass might be a generic type parameter but they have
* interface_offsets set.
*/
- return mono_reflection_call_is_assignable_to (oklass, klass);
+ gboolean result = mono_reflection_call_is_assignable_to (oklass, klass, &error);
+ if (!is_ok (&error)) {
+ mono_error_cleanup (&error);
+ return FALSE;
+ }
+ return result;
+ }
if (!oklass->interface_bitmap)
/* Happens with generic instances of not-yet created dynamic types */
return FALSE;
return TRUE;
if (mono_class_has_variant_generic_params (klass)) {
- MonoError error;
int i;
mono_class_setup_interfaces (oklass, &error);
if (!mono_error_ok (&error)) {
if (image_is_dynamic (image)) {
MonoClass *tmp_handle_class;
- gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context);
+ gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context, error);
+ mono_error_assert_ok (error);
g_assert (tmp_handle_class);
if (handle_class)
*handle_class = tmp_handle_class;
return NULL;
}
-/**
- * This function might need to call runtime functions so it can't be part
- * of the metadata library.
- */
-static MonoLookupDynamicToken lookup_dynamic = NULL;
-
-void
-mono_install_lookup_dynamic_token (MonoLookupDynamicToken func)
-{
- lookup_dynamic = func;
-}
-
gpointer
-mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context)
+mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context, MonoError *error)
{
MonoClass *handle_class;
-
- return lookup_dynamic (image, token, TRUE, &handle_class, context);
+ mono_error_init (error);
+ return mono_reflection_lookup_dynamic_token (image, token, TRUE, &handle_class, context, error);
}
gpointer
-mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
+mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
{
- return lookup_dynamic (image, token, valid_token, handle_class, context);
+ return mono_reflection_lookup_dynamic_token (image, token, valid_token, handle_class, context, error);
}
static MonoGetCachedClassInfo get_cached_class_info = NULL;
return mono_exception_from_name_msg (mono_defaults.corlib, "System", "InvalidProgramException", "");
}
default: {
- MonoLoaderError *error;
- MonoException *ex;
-
- error = mono_loader_get_last_error ();
- if (error != NULL){
- ex = mono_loader_error_prepare_exception (error);
- return ex;
- }
-
/* TODO - handle other class related failures */
- return NULL;
+ return mono_get_exception_execution_engine ("Unknown class failure");
}
}
}