#include "class.h"
#include "marshal.h"
#include "debug-helpers.h"
+#include "abi-details.h"
#include <mono/utils/mono-error-internals.h>
#include <mono/utils/bsearch.h>
static MonoImageSet *mscorlib_image_set;
/* Protected by image_sets_mutex */
static GPtrArray *image_sets;
-static CRITICAL_SECTION image_sets_mutex;
+static mono_mutex_t image_sets_mutex;
static guint mono_generic_class_hash (gconstpointer data);
for (i = 0; i < NBUILTIN_TYPES (); ++i)
g_hash_table_insert (type_cache, (gpointer) &builtin_types [i], (gpointer) &builtin_types [i]);
- InitializeCriticalSection (&image_sets_mutex);
+ mono_mutex_init_recursive (&image_sets_mutex);
}
/**
type_cache = NULL;
g_ptr_array_free (image_sets, TRUE);
image_sets = NULL;
- DeleteCriticalSection (&image_sets_mutex);
+ mono_mutex_destroy (&image_sets_mutex);
}
/**
MonoMethodSignature*
mono_metadata_parse_signature_full (MonoImage *image, MonoGenericContainer *generic_container, guint32 token)
{
+ MonoError error;
+ MonoMethodSignature *ret;
MonoTableInfo *tables = image->tables;
guint32 idx = mono_metadata_token_index (token);
guint32 sig;
const char *ptr;
- if (image->dynamic)
+ if (image_is_dynamic (image))
return mono_lookup_dynamic_token (image, token, NULL);
g_assert (mono_metadata_token_table(token) == MONO_TABLE_STANDALONESIG);
ptr = mono_metadata_blob_heap (image, sig);
mono_metadata_decode_blob_size (ptr, &ptr);
- return mono_metadata_parse_method_signature_full (image, generic_container, 0, ptr, NULL);
+ ret = mono_metadata_parse_method_signature_full (image, generic_container, 0, ptr, NULL, &error);
+ if (!ret) {
+ mono_loader_set_error_from_mono_error (&error);
+ mono_error_cleanup (&error); /*FIXME don't swallow the error message*/
+ }
+ return ret;
}
/*
*/
MonoMethodSignature *
mono_metadata_parse_method_signature_full (MonoImage *m, MonoGenericContainer *container,
- int def, const char *ptr, const char **rptr)
+ int def, const char *ptr, const char **rptr, MonoError *error)
{
MonoMethodSignature *method;
int i, *pattrs = NULL;
guint32 gen_param_count = 0;
gboolean is_open = FALSE;
+ mono_error_init (error);
+
if (*ptr & 0x10)
gen_param_count = 1;
if (*ptr & 0x20)
if (!method->ret) {
mono_metadata_free_method_signature (method);
g_free (pattrs);
+ if (mono_loader_get_last_error ())
+ mono_error_set_from_loader_error (error);
+ else
+ mono_error_set_bad_image (error, m, "Could not parse return type signature");
return NULL;
}
is_open = mono_class_is_open_constructed_type (method->ret);
for (i = 0; i < method->param_count; ++i) {
if (*ptr == MONO_TYPE_SENTINEL) {
if (method->call_convention != MONO_CALL_VARARG || def) {
- g_warning ("found sentinel for methoddef or no vararg method 0x%08x on image %s", def, m->name);
+ g_assert (!mono_loader_get_last_error ());
+ mono_error_set_bad_image (error, m, "Found sentinel for methoddef or no vararg");
g_free (pattrs);
return NULL;
}
if (method->sentinelpos >= 0) {
- g_warning ("found sentinel twice in the same signature for method 0x%08x on image %s", def, m->name);
+ g_assert (!mono_loader_get_last_error ());
+ mono_error_set_bad_image (error, m, "Found sentinel twice in the same signature.");
g_free (pattrs);
return NULL;
}
}
method->params [i] = mono_metadata_parse_type_full (m, container, MONO_PARSE_PARAM, pattrs ? pattrs [i+1] : 0, ptr, &ptr);
if (!method->params [i]) {
+ if (mono_loader_get_last_error ())
+ mono_error_set_from_loader_error (error);
+ else
+ mono_error_set_bad_image (error, m, "Could not parse type argument %d on method signature", i);
mono_metadata_free_method_signature (method);
g_free (pattrs);
return NULL;
* Add signature to a cache and increase ref count...
*/
+ g_assert (!mono_loader_get_last_error ());
return method;
}
MonoMethodSignature *
mono_metadata_parse_method_signature (MonoImage *m, int def, const char *ptr, const char **rptr)
{
- return mono_metadata_parse_method_signature_full (m, NULL, def, ptr, rptr);
+ MonoError error;
+ MonoMethodSignature *ret;
+ ret = mono_metadata_parse_method_signature_full (m, NULL, def, ptr, rptr, &error);
+ if (!ret) {
+ mono_loader_set_error_from_mono_error (&error);
+ mono_error_cleanup (&error); /*FIXME don't swallow the error message*/
+ }
+ return ret;
}
/*
static inline void
image_sets_lock (void)
{
- EnterCriticalSection (&image_sets_mutex);
+ mono_mutex_lock (&image_sets_mutex);
}
static inline void
image_sets_unlock (void)
{
- LeaveCriticalSection (&image_sets_mutex);
+ mono_mutex_unlock (&image_sets_mutex);
}
/*
set = g_new0 (MonoImageSet, 1);
set->nimages = nimages;
set->images = g_new0 (MonoImage*, nimages);
- InitializeCriticalSection (&set->lock);
+ mono_mutex_init_recursive (&set->lock);
for (i = 0; i < nimages; ++i)
set->images [i] = images [i];
set->gclass_cache = g_hash_table_new_full (mono_generic_class_hash, mono_generic_class_equal, NULL, (GDestroyNotify)free_generic_class);
if (set->mempool)
mono_mempool_destroy (set->mempool);
g_free (set->images);
- DeleteCriticalSection (&set->lock);
+ mono_mutex_destroy (&set->lock);
g_free (set);
}
static void
mono_image_set_lock (MonoImageSet *set)
{
- EnterCriticalSection (&set->lock);
+ mono_mutex_lock (&set->lock);
}
static void
mono_image_set_unlock (MonoImageSet *set)
{
- LeaveCriticalSection (&set->lock);
+ mono_mutex_unlock (&set->lock);
}
gpointer
/*
* Dynamic assemblies have no references, so the images they depend on can be unloaded before them.
*/
- if (m->klass->image->dynamic)
+ if (image_is_dynamic (m->klass->image))
collect_signature_images (mono_method_signature (m), data);
}
*/
ginst_data.image = gclass_data.image = image;
ginst_data.list = gclass_data.list = NULL;
- mono_loader_lock ();
/* Collect the items to delete */
/* delete_image_set () modifies the lists so make a copy */
delete_image_set (set);
}
g_slist_free (set_list);
-
- mono_loader_unlock ();
}
static void
g_free (sig);
}
-/*
- * LOCKING: assumes the loader lock is held.
- */
MonoMethodInflated*
mono_method_inflated_lookup (MonoMethodInflated* method, gboolean cache)
{
collect_data_free (&data);
- if (cache) {
- mono_image_set_lock (set);
+ mono_image_set_lock (set);
+ res = g_hash_table_lookup (set->gmethod_cache, method);
+ if (!res && cache) {
g_hash_table_insert (set->gmethod_cache, method, method);
- mono_image_set_unlock (set);
-
- return method;
- } else {
- mono_image_set_lock (set);
- res = g_hash_table_lookup (set->gmethod_cache, method);
- mono_image_set_unlock (set);
-
- return res;
+ res = method;
}
+
+ mono_image_set_unlock (set);
+ return res;
}
/*
if (type == &type->data.klass->this_arg)
return type;
break;
+ default:
+ break;
}
return NULL;
/* NET 1.1 assemblies might encode string and object in a denormalized way.
* See #675464.
*/
- if (type_type == MONO_TYPE_CLASS && (class_type == MONO_TYPE_STRING || class_type == MONO_TYPE_OBJECT))
+ if (class_type == type_type)
return TRUE;
- return class_type == type_type;
+
+ if (type_type == MONO_TYPE_CLASS)
+ return class_type == MONO_TYPE_STRING || class_type == MONO_TYPE_OBJECT;
+
+ g_assert (type_type == MONO_TYPE_VALUETYPE);
+ switch (class_type) {
+ case MONO_TYPE_BOOLEAN:
+ case MONO_TYPE_CHAR:
+ case MONO_TYPE_I1:
+ case MONO_TYPE_U1:
+ case MONO_TYPE_I2:
+ case MONO_TYPE_U2:
+ case MONO_TYPE_I4:
+ case MONO_TYPE_U4:
+ case MONO_TYPE_I8:
+ case MONO_TYPE_U8:
+ case MONO_TYPE_R4:
+ case MONO_TYPE_R8:
+ case MONO_TYPE_I:
+ case MONO_TYPE_U:
+ return TRUE;
+ default:
+ return FALSE;
+ }
}
/*
case MONO_TYPE_CLASS: {
guint32 token;
MonoClass *class;
+ MonoError error;
token = mono_metadata_parse_typedef_or_ref (m, ptr, &ptr);
- class = mono_class_get (m, token);
+ class = mono_class_get_checked (m, token, &error);
type->data.klass = class;
- if (!class)
+ if (!class) {
+ mono_loader_set_error_from_mono_error (&error);
+ mono_error_cleanup (&error); /*FIXME don't swallow the error message*/
return FALSE;
+ }
if (!compare_type_literals (class->byval_arg.type, type->type))
return FALSE;
break;
if (!type->data.type)
return FALSE;
break;
- case MONO_TYPE_FNPTR:
- type->data.method = mono_metadata_parse_method_signature_full (m, container, 0, ptr, &ptr);
- if (!type->data.method)
+ case MONO_TYPE_FNPTR: {
+ MonoError error;
+ type->data.method = mono_metadata_parse_method_signature_full (m, container, 0, ptr, &ptr, &error);
+ if (!type->data.method) {
+ mono_loader_set_error_from_mono_error (&error);
+ mono_error_cleanup (&error); /*FIXME don't swallow the error message*/
return FALSE;
+ }
break;
+ }
case MONO_TYPE_ARRAY:
type->data.array = mono_metadata_parse_array_internal (m, container, transient, ptr, &ptr);
if (!type->data.array)
case MONO_TYPE_ARRAY:
mono_metadata_free_array (type->data.array);
break;
+ default:
+ break;
}
g_free (type);
parse_section_data (MonoImage *m, int *num_clauses, const unsigned char *ptr)
{
unsigned char sect_data_flags;
- const unsigned char *sptr;
int is_fat;
guint32 sect_data_len;
MonoExceptionClause* clauses = NULL;
while (1) {
/* align on 32-bit boundary */
- sptr = ptr = dword_align (ptr);
+ ptr = dword_align (ptr);
sect_data_flags = *ptr;
ptr++;
sect_data_len = ptr [0];
++ptr;
}
- /*
- g_print ("flags: %02x, len: %d\n", sect_data_flags, sect_data_len);
- hex_dump (sptr, 0, sect_data_len+8);
- g_print ("\nheader: ");
- hex_dump (sptr-4, 0, 4);
- g_print ("\n");
- */
-
+
if (sect_data_flags & METHOD_HEADER_SECTION_EHTABLE) {
const unsigned char *p = dword_align (ptr);
int i;
if (ec->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
ec->data.filter_offset = tof_value;
} else if (ec->flags == MONO_EXCEPTION_CLAUSE_NONE) {
- ec->data.catch_class = tof_value? mono_class_get (m, tof_value): 0;
+ ec->data.catch_class = NULL;
+ if (tof_value) {
+ MonoError error;
+ ec->data.catch_class = mono_class_get_checked (m, tof_value, &error);
+ if (!mono_error_ok (&error)) {
+ mono_error_cleanup (&error); /* FIXME don't swallow the error */
+ g_free (clauses);
+ return NULL;
+ }
+ }
} else {
ec->data.catch_class = NULL;
}
MonoMethodHeader *
mono_metadata_parse_mh_full (MonoImage *m, MonoGenericContainer *container, const char *ptr)
{
- MonoMethodHeader *mh;
+ MonoMethodHeader *mh = NULL;
unsigned char flags = *(const unsigned char *) ptr;
unsigned char format = flags & METHOD_HEADER_FORMAT_MASK;
guint16 fat_flags;
guint32 local_var_sig_tok, max_stack, code_size, init_locals;
const unsigned char *code;
MonoExceptionClause* clauses = NULL;
- int hsize, num_clauses = 0;
+ int num_clauses = 0;
MonoTableInfo *t = &m->tables [MONO_TABLE_STANDALONESIG];
guint32 cols [MONO_STAND_ALONE_SIGNATURE_SIZE];
case METHOD_HEADER_FAT_FORMAT:
fat_flags = read16 (ptr);
ptr += 2;
- hsize = (fat_flags >> 12) & 0xf;
max_stack = read16 (ptr);
ptr += 2;
code_size = read32 (ptr);
if (local_var_sig_tok) {
int idx = (local_var_sig_tok & 0xffffff)-1;
if (idx >= t->rows || idx < 0)
- return NULL;
+ goto fail;
mono_metadata_decode_row (t, idx, cols, 1);
if (!mono_verifier_verify_standalone_signature (m, cols [MONO_STAND_ALONE_SIGNATURE], NULL))
- return NULL;
+ goto fail;
}
if (fat_flags & METHOD_HEADER_MORE_SECTS)
clauses = parse_section_data (m, &num_clauses, (const unsigned char*)ptr);
if (local_var_sig_tok) {
const char *locals_ptr;
- int len=0, i, bsize;
+ int len=0, i;
locals_ptr = mono_metadata_blob_heap (m, cols [MONO_STAND_ALONE_SIGNATURE]);
- bsize = mono_metadata_decode_blob_size (locals_ptr, &locals_ptr);
+ mono_metadata_decode_blob_size (locals_ptr, &locals_ptr);
if (*locals_ptr != 0x07)
g_warning ("wrong signature for locals blob");
locals_ptr++;
for (i = 0; i < len; ++i) {
mh->locals [i] = mono_metadata_parse_type_internal (m, container,
MONO_PARSE_LOCAL, 0, TRUE, locals_ptr, &locals_ptr);
- if (!mh->locals [i]) {
- g_free (clauses);
- g_free (mh);
- return NULL;
- }
+ if (!mh->locals [i])
+ goto fail;
}
} else {
mh = g_malloc0 (MONO_SIZEOF_METHOD_HEADER + num_clauses * sizeof (MonoExceptionClause));
mh->num_clauses = num_clauses;
}
return mh;
+fail:
+ g_free (clauses);
+ g_free (mh);
+ return NULL;
+
}
/*
*
* Decode the method header at @ptr, including pointer to the IL code,
* info about local variables and optional exception tables.
- * This is a Mono runtime internal function.
*
- * Returns: a MonoMethodHeader.
+ * Returns: a transient MonoMethodHeader allocated from the heap.
*/
MonoMethodHeader *
mono_metadata_parse_mh (MonoImage *m, const char *ptr)
{
- MonoMethodHeader *res;
-
- mono_loader_lock ();
-
- res = mono_metadata_parse_mh_full (m, NULL, ptr);
-
- mono_loader_unlock ();
-
- return res;
+ return mono_metadata_parse_mh_full (m, NULL, ptr);
}
/*
* The array of interfaces that the @index typedef token implements is returned in
* @interfaces. The number of elements in the array is returned in @count.
*
- * LOCKING: Assumes the loader lock is held.
- *
+
* Returns: TRUE on success, FALSE on failure.
*/
gboolean
-mono_metadata_interfaces_from_typedef_full (MonoImage *meta, guint32 index, MonoClass ***interfaces, guint *count, gboolean heap_alloc_result, MonoGenericContext *context)
+mono_metadata_interfaces_from_typedef_full (MonoImage *meta, guint32 index, MonoClass ***interfaces, guint *count, gboolean heap_alloc_result, MonoGenericContext *context, MonoError *error)
{
MonoTableInfo *tdef = &meta->tables [MONO_TABLE_INTERFACEIMPL];
locator_t loc;
*interfaces = NULL;
*count = 0;
+ mono_error_init (error);
+
if (!tdef->base)
return TRUE;
mono_metadata_decode_row (tdef, pos, cols, MONO_INTERFACEIMPL_SIZE);
if (cols [MONO_INTERFACEIMPL_CLASS] != loc.idx)
break;
- iface = mono_class_get_full (
- meta, mono_metadata_token_from_dor (cols [MONO_INTERFACEIMPL_INTERFACE]), context);
+ iface = mono_class_get_and_inflate_typespec_checked (
+ meta, mono_metadata_token_from_dor (cols [MONO_INTERFACEIMPL_INTERFACE]), context, error);
if (iface == NULL)
return FALSE;
result [pos - start] = iface;
MonoClass**
mono_metadata_interfaces_from_typedef (MonoImage *meta, guint32 index, guint *count)
{
- MonoClass **interfaces;
+ MonoError error;
+ MonoClass **interfaces = NULL;
gboolean rv;
- mono_loader_lock ();
- rv = mono_metadata_interfaces_from_typedef_full (meta, index, &interfaces, count, TRUE, NULL);
- mono_loader_unlock ();
+ rv = mono_metadata_interfaces_from_typedef_full (meta, index, &interfaces, count, TRUE, NULL, &error);
+ g_assert (mono_error_ok (&error)); /* FIXME dont swallow the error */
if (rv)
return interfaces;
else
}
#endif
-#define abi__alignof__(type) G_STRUCT_OFFSET(struct { char c; type x; }, x)
+static int i8_align;
+
+/*
+ * mono_type_set_alignment:
+ *
+ * Set the alignment used by runtime to layout fields etc. of type TYPE to ALIGN.
+ * This should only be used in AOT mode since the resulting layout will not match the
+ * host abi layout.
+ */
+void
+mono_type_set_alignment (MonoTypeEnum type, int align)
+{
+ /* Support only a few types whose alignment is abi dependent */
+ switch (type) {
+ case MONO_TYPE_I8:
+ i8_align = align;
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+}
/*
* mono_type_size:
int
mono_type_size (MonoType *t, int *align)
{
+ MonoTypeEnum simple_type;
+
if (!t) {
*align = 1;
return 0;
}
if (t->byref) {
- *align = abi__alignof__(gpointer);
+ *align = MONO_ABI_ALIGNOF (gpointer);
return sizeof (gpointer);
}
- switch (t->type){
+ simple_type = t->type;
+ again:
+ switch (simple_type) {
case MONO_TYPE_VOID:
*align = 1;
return 0;
case MONO_TYPE_BOOLEAN:
- *align = abi__alignof__(gint8);
+ *align = MONO_ABI_ALIGNOF (gint8);
return 1;
case MONO_TYPE_I1:
case MONO_TYPE_U1:
- *align = abi__alignof__(gint8);
+ *align = MONO_ABI_ALIGNOF (gint8);
return 1;
case MONO_TYPE_CHAR:
case MONO_TYPE_I2:
case MONO_TYPE_U2:
- *align = abi__alignof__(gint16);
+ *align = MONO_ABI_ALIGNOF (gint16);
return 2;
case MONO_TYPE_I4:
case MONO_TYPE_U4:
- *align = abi__alignof__(gint32);
+ *align = MONO_ABI_ALIGNOF (gint32);
return 4;
case MONO_TYPE_R4:
- *align = abi__alignof__(float);
+ *align = MONO_ABI_ALIGNOF (float);
return 4;
case MONO_TYPE_I8:
case MONO_TYPE_U8:
- *align = abi__alignof__(gint64);
+ *align = MONO_ABI_ALIGNOF (gint64);
return 8;
case MONO_TYPE_R8:
- *align = abi__alignof__(double);
+ *align = MONO_ABI_ALIGNOF (double);
return 8;
case MONO_TYPE_I:
case MONO_TYPE_U:
- *align = abi__alignof__(gpointer);
+ *align = MONO_ABI_ALIGNOF (gpointer);
return sizeof (gpointer);
case MONO_TYPE_STRING:
- *align = abi__alignof__(gpointer);
+ *align = MONO_ABI_ALIGNOF (gpointer);
return sizeof (gpointer);
case MONO_TYPE_OBJECT:
- *align = abi__alignof__(gpointer);
+ *align = MONO_ABI_ALIGNOF (gpointer);
return sizeof (gpointer);
case MONO_TYPE_VALUETYPE: {
if (t->data.klass->enumtype)
case MONO_TYPE_PTR:
case MONO_TYPE_FNPTR:
case MONO_TYPE_ARRAY:
- *align = abi__alignof__(gpointer);
+ *align = MONO_ABI_ALIGNOF (gpointer);
return sizeof (gpointer);
case MONO_TYPE_TYPEDBYREF:
return mono_class_value_size (mono_defaults.typed_reference_class, (guint32*)align);
else
return mono_class_value_size (mono_class_from_mono_type (t), (guint32*)align);
} else {
- *align = abi__alignof__(gpointer);
+ *align = MONO_ABI_ALIGNOF (gpointer);
return sizeof (gpointer);
}
}
case MONO_TYPE_VAR:
case MONO_TYPE_MVAR:
- /* FIXME: Martin, this is wrong. */
- *align = abi__alignof__(gpointer);
- return sizeof (gpointer);
+ if (t->data.generic_param->gshared_constraint == 0 || t->data.generic_param->gshared_constraint == MONO_TYPE_VALUETYPE) {
+ *align = MONO_ABI_ALIGNOF (gpointer);
+ return sizeof (gpointer);
+ } else {
+ /* The gparam can only match types given by gshared_constraint */
+ simple_type = t->data.generic_param->gshared_constraint;
+ goto again;
+ }
default:
g_error ("mono_type_size: type 0x%02x unknown", t->type);
}
mono_type_stack_size_internal (MonoType *t, int *align, gboolean allow_open)
{
int tmp;
+ MonoTypeEnum simple_type;
#if SIZEOF_VOID_P == SIZEOF_REGISTER
int stack_slot_size = sizeof (gpointer);
- int stack_slot_align = abi__alignof__ (gpointer);
+ int stack_slot_align = MONO_ABI_ALIGNOF (gpointer);
#elif SIZEOF_VOID_P < SIZEOF_REGISTER
int stack_slot_size = SIZEOF_REGISTER;
int stack_slot_align = SIZEOF_REGISTER;
return stack_slot_size;
}
- switch (t->type){
+ simple_type = t->type;
+ again:
+ switch (simple_type) {
case MONO_TYPE_BOOLEAN:
case MONO_TYPE_CHAR:
case MONO_TYPE_I1:
case MONO_TYPE_VAR:
case MONO_TYPE_MVAR:
g_assert (allow_open);
- *align = stack_slot_align;
- return stack_slot_size;
+ if (t->data.generic_param->gshared_constraint == 0 || t->data.generic_param->gshared_constraint == MONO_TYPE_VALUETYPE) {
+ *align = stack_slot_align;
+ return stack_slot_size;
+ } else {
+ /* The gparam can only match types given by gshared_constraint */
+ simple_type = t->data.generic_param->gshared_constraint;
+ goto again;
+ }
case MONO_TYPE_TYPEDBYREF:
*align = stack_slot_align;
return stack_slot_size * 3;
case MONO_TYPE_R4:
- *align = abi__alignof__(float);
+ *align = MONO_ABI_ALIGNOF (float);
return sizeof (float);
case MONO_TYPE_I8:
case MONO_TYPE_U8:
- *align = abi__alignof__(gint64);
+ *align = MONO_ABI_ALIGNOF (gint64);
return sizeof (gint64);
case MONO_TYPE_R8:
- *align = abi__alignof__(double);
+ *align = MONO_ABI_ALIGNOF (double);
return sizeof (double);
case MONO_TYPE_VALUETYPE: {
guint32 size;
* This is specially problematic with generic instances since they are
* inserted in a bunch of hash tables before been finished.
*/
- if (class->image->dynamic)
+ if (image_is_dynamic (class->image))
return (t1->byref << 6) | mono_metadata_str_hash (class->name);
return ((hash << 5) - hash) ^ mono_metadata_str_hash (class->name);
}
case MONO_TYPE_VAR:
case MONO_TYPE_MVAR:
return ((hash << 5) - hash) ^ mono_metadata_generic_param_hash (t1->data.generic_param);
+ default:
+ return hash;
}
- return hash;
}
static guint
guint hash;
MonoGenericParamInfo *info;
- hash = (mono_generic_param_num (p) << 2) | p->serial;
+ hash = (mono_generic_param_num (p) << 2) | p->gshared_constraint;
info = mono_generic_param_info (p);
/* Can't hash on the owner klass/method, since those might not be set when this is called */
if (info)
return TRUE;
if (mono_generic_param_num (p1) != mono_generic_param_num (p2))
return FALSE;
- if (p1->serial != p2->serial)
+ if (p1->gshared_constraint != p2->gshared_constraint)
return FALSE;
/*
const char *p;
if ((p = mono_metadata_get_marshal_info (meta, index, TRUE))) {
- *marshal_spec = mono_metadata_parse_marshal_spec_full (alloc_from_image ? meta : NULL, p);
+ *marshal_spec = mono_metadata_parse_marshal_spec_full (alloc_from_image ? meta : NULL, meta, p);
}
}
/**
* @image: context where the image is created
* @type_spec: typespec token
+ * @deprecated use mono_type_create_from_typespec_checked that has proper error handling
*
* Creates a MonoType representing the TypeSpec indexed by the @type_spec
* token.
*/
MonoType *
mono_type_create_from_typespec (MonoImage *image, guint32 type_spec)
+{
+ MonoError error;
+ MonoType *type = mono_type_create_from_typespec_checked (image, type_spec, &error);
+ if (!type)
+ g_error ("Could not create typespec %x due to %s", type_spec, mono_error_get_message (&error));
+ return type;
+}
+
+MonoType *
+mono_type_create_from_typespec_checked (MonoImage *image, guint32 type_spec, MonoError *error)
+
{
guint32 idx = mono_metadata_token_index (type_spec);
MonoTableInfo *t;
guint32 cols [MONO_TYPESPEC_SIZE];
const char *ptr;
- guint32 len;
MonoType *type, *type2;
- mono_loader_lock ();
+ mono_error_init (error);
+ mono_image_lock (image);
type = g_hash_table_lookup (image->typespec_cache, GUINT_TO_POINTER (type_spec));
- if (type) {
- mono_loader_unlock ();
+ mono_image_unlock (image);
+ if (type)
return type;
- }
t = &image->tables [MONO_TABLE_TYPESPEC];
ptr = mono_metadata_blob_heap (image, cols [MONO_TYPESPEC_SIGNATURE]);
if (!mono_verifier_verify_typespec_signature (image, cols [MONO_TYPESPEC_SIGNATURE], type_spec, NULL)) {
- mono_loader_unlock ();
+ mono_error_set_bad_image (error, image, "Could not verify type spec %08x.", type_spec);
return NULL;
}
- len = mono_metadata_decode_value (ptr, &ptr);
+ mono_metadata_decode_value (ptr, &ptr);
type = mono_metadata_parse_type_internal (image, NULL, MONO_PARSE_TYPE, 0, TRUE, ptr, &ptr);
if (!type) {
- mono_loader_unlock ();
+ if (mono_loader_get_last_error ())
+ mono_error_set_from_loader_error (error);
+ else
+ mono_error_set_bad_image (error, image, "Could not parse type spec %08x.", type_spec);
return NULL;
}
- type2 = g_hash_table_lookup (image->typespec_cache, GUINT_TO_POINTER (type_spec));
-
- if (type2) {
- mono_loader_unlock ();
- return type2;
- }
-
type2 = mono_metadata_type_dup (image, type);
- g_hash_table_insert (image->typespec_cache, GUINT_TO_POINTER (type_spec), type2);
mono_metadata_free_type (type);
- mono_loader_unlock ();
+ mono_image_lock (image);
+ type = g_hash_table_lookup (image->typespec_cache, GUINT_TO_POINTER (type_spec));
+ /* We might leak some data in the image mempool if found */
+ if (!type) {
+ g_hash_table_insert (image->typespec_cache, GUINT_TO_POINTER (type_spec), type2);
+ type = type2;
+ }
+ mono_image_unlock (image);
- return type2;
+ return type;
}
MonoMarshalSpec *
mono_metadata_parse_marshal_spec (MonoImage *image, const char *ptr)
{
- return mono_metadata_parse_marshal_spec_full (NULL, ptr);
+ return mono_metadata_parse_marshal_spec_full (NULL, image, ptr);
}
+/*
+ * If IMAGE is non-null, memory will be allocated from its mempool, otherwise it will be allocated using malloc.
+ * PARENT_IMAGE is the image containing the marshal spec.
+ */
MonoMarshalSpec *
-mono_metadata_parse_marshal_spec_full (MonoImage *image, const char *ptr)
+mono_metadata_parse_marshal_spec_full (MonoImage *image, MonoImage *parent_image, const char *ptr)
{
MonoMarshalSpec *res;
int len;
/* read cookie string */
len = mono_metadata_decode_value (ptr, &ptr);
res->data.custom_data.cookie = mono_image_strndup (image, ptr, len);
+ res->data.custom_data.image = parent_image;
}
if (res->native == MONO_NATIVE_SAFEARRAY) {
}
MonoMethod*
-method_from_method_def_or_ref (MonoImage *m, guint32 tok, MonoGenericContext *context)
+method_from_method_def_or_ref (MonoImage *m, guint32 tok, MonoGenericContext *context, MonoError *error)
{
+ MonoMethod *result = NULL;
guint32 idx = tok >> MONO_METHODDEFORREF_BITS;
+ mono_error_init (error);
+
switch (tok & MONO_METHODDEFORREF_MASK) {
case MONO_METHODDEFORREF_METHODDEF:
- return mono_get_method_full (m, MONO_TOKEN_METHOD_DEF | idx, NULL, context);
+ result = mono_get_method_checked (m, MONO_TOKEN_METHOD_DEF | idx, NULL, context, error);
+ break;
case MONO_METHODDEFORREF_METHODREF:
- return mono_get_method_full (m, MONO_TOKEN_MEMBER_REF | idx, NULL, context);
+ result = mono_get_method_checked (m, MONO_TOKEN_MEMBER_REF | idx, NULL, context, error);
+ break;
+ default:
+ mono_error_set_bad_image (error, m, "Invalid MethodDefOfRef token %x", tok);
}
- g_assert_not_reached ();
- return NULL;
+
+ return result;
}
/*
MonoMethod *method;
if (!mono_verifier_verify_methodimpl_row (image, start + i, &error)) {
- mono_error_cleanup (&error);
+ mono_error_cleanup (&error); /* FIXME don't swallow the error */
ok = FALSE;
break;
}
mono_metadata_decode_row (tdef, start + i, cols, MONO_METHODIMPL_SIZE);
method = method_from_method_def_or_ref (
- image, cols [MONO_METHODIMPL_DECLARATION], generic_context);
- if (method == NULL)
+ image, cols [MONO_METHODIMPL_DECLARATION], generic_context, &error);
+ if (method == NULL) {
+ mono_error_cleanup (&error); /* FIXME don't swallow the error */
ok = FALSE;
+ }
result [i * 2] = method;
method = method_from_method_def_or_ref (
- image, cols [MONO_METHODIMPL_BODY], generic_context);
- if (method == NULL)
+ image, cols [MONO_METHODIMPL_BODY], generic_context, &error);
+ if (method == NULL) {
+ mono_error_cleanup (&error); /* FIXME don't swallow the error */
ok = FALSE;
+ }
result [i * 2 + 1] = method;
}
}
static gboolean
-get_constraints (MonoImage *image, int owner, MonoClass ***constraints, MonoGenericContainer *container)
+get_constraints (MonoImage *image, int owner, MonoClass ***constraints, MonoGenericContainer *container, MonoError *error)
{
MonoTableInfo *tdef = &image->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
guint32 cols [MONO_GENPARCONSTRAINT_SIZE];
GSList *cons = NULL, *tmp;
MonoGenericContext *context = &container->context;
+ mono_error_init (error);
+
*constraints = NULL;
found = 0;
for (i = 0; i < tdef->rows; ++i) {
mono_metadata_decode_row (tdef, i, cols, MONO_GENPARCONSTRAINT_SIZE);
if (cols [MONO_GENPARCONSTRAINT_GENERICPAR] == owner) {
token = mono_metadata_token_from_dor (cols [MONO_GENPARCONSTRAINT_CONSTRAINT]);
- klass = mono_class_get_full (image, token, context);
+ klass = mono_class_get_and_inflate_typespec_checked (image, token, context, error);
if (!klass) {
g_slist_free (cons);
return FALSE;
* Memory is allocated from IMAGE's mempool.
*/
gboolean
-mono_metadata_load_generic_param_constraints_full (MonoImage *image, guint32 token,
- MonoGenericContainer *container)
+mono_metadata_load_generic_param_constraints_checked (MonoImage *image, guint32 token,
+ MonoGenericContainer *container, MonoError *error)
{
guint32 start_row, i, owner;
+ mono_error_init (error);
+
if (! (start_row = mono_metadata_get_generic_param_row (image, token, &owner)))
return TRUE;
for (i = 0; i < container->type_argc; i++) {
- if (!get_constraints (image, start_row + i, &mono_generic_container_get_param_info (container, i)->constraints, container))
+ if (!get_constraints (image, start_row + i, &mono_generic_container_get_param_info (container, i)->constraints, container, error)) {
+ g_assert (!mono_loader_get_last_error ());
return FALSE;
+ }
}
return TRUE;
}
-/*
- * mono_metadata_load_generic_param_constraints:
- *
- * @image: metadata context
- * @token: metadata token to load the contraints, can be methodef or typedef.
- * @container: generic container to load into.
- *
- * Load the generic parameter constraints for the newly created generic type or method
- * represented by @token and @container. The @container is the new container which has
- * been returned by a call to mono_metadata_load_generic_params() with this @token.
- * Memory is allocated from IMAGE's mempool.
- */
-void
-mono_metadata_load_generic_param_constraints (MonoImage *image, guint32 token,
- MonoGenericContainer *container)
-{
- mono_metadata_load_generic_param_constraints_full (image, token, container);
- /*FIXME this function can potentially exit with a pending loader error and cause all sort of havok */
-}
-
/*
* mono_metadata_load_generic_params:
*