* TODO:
* This should keep track of the assembly versions that we are loading.
*
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
*/
#include <config.h>
#include <glib.h>
}
/* FIXME: This needs a cache, especially for generic instances, since
- * mono_metadata_parse_type () allocates everything from a mempool.
+ * we ask mono_metadata_parse_type_checked () to allocates everything from a mempool.
+ * FIXME part2, mono_metadata_parse_type_checked actually allows for a transient type instead.
+ * FIXME part3, transient types are not 100% transient, so we need to take care of that first.
*/
sig_type = (MonoType *)find_cached_memberref_sig (image, cols [MONO_MEMBERREF_SIGNATURE]);
if (!sig_type) {
- sig_type = mono_metadata_parse_type (image, MONO_PARSE_TYPE, 0, ptr, &ptr);
+ MonoError inner_error;
+ sig_type = mono_metadata_parse_type_checked (image, NULL, 0, FALSE, ptr, &ptr, &inner_error);
if (sig_type == NULL) {
- mono_error_set_field_load (error, klass, fname, "Could not parse field '%s' signature %08x", fname, token);
+ mono_error_set_field_load (error, klass, fname, "Could not parse field '%s' signature %08x due to: %s", fname, token, mono_error_get_message (&inner_error));
+ mono_error_cleanup (&inner_error);
return NULL;
}
sig_type = (MonoType *)cache_memberref_sig (image, cols [MONO_MEMBERREF_SIGNATURE], sig_type);
MonoClass *handle_class;
*retklass = NULL;
- result = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, TRUE, &handle_class, context);
+ MonoError inner_error;
+ result = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, TRUE, &handle_class, context, &inner_error);
+ mono_error_cleanup (&inner_error);
// This checks the memberref type as well
if (!result || handle_class != mono_defaults.fieldhandle_class) {
mono_error_set_bad_image (error, image, "Bad field token 0x%08x", token);
See mono/tests/generic-type-load-exception.2.il
FIXME we should better report this error to the caller
*/
- if (!klass->methods || klass->exception_type) {
+ if (!klass->methods || mono_class_has_failure (klass)) {
mono_error_set_type_load_class (error, klass, "Could not find method due to a type load error"); //FIXME get the error from the class
return NULL;
}
static MonoMethodHeader*
-inflate_generic_header (MonoMethodHeader *header, MonoGenericContext *context)
+inflate_generic_header (MonoMethodHeader *header, MonoGenericContext *context, MonoError *error)
{
- MonoMethodHeader *res;
- int i;
- res = (MonoMethodHeader *)g_malloc0 (MONO_SIZEOF_METHOD_HEADER + sizeof (gpointer) * header->num_locals);
+ size_t locals_size = sizeof (gpointer) * header->num_locals;
+ size_t clauses_size = header->num_clauses * sizeof (MonoExceptionClause);
+ size_t header_size = MONO_SIZEOF_METHOD_HEADER + locals_size + clauses_size;
+ MonoMethodHeader *res = (MonoMethodHeader *)g_malloc0 (header_size);
+ res->num_locals = header->num_locals;
+ res->clauses = (MonoExceptionClause *) &res->locals [res->num_locals] ;
+ memcpy (res->clauses, header->clauses, clauses_size);
+
res->code = header->code;
res->code_size = header->code_size;
res->max_stack = header->max_stack;
res->num_clauses = header->num_clauses;
res->init_locals = header->init_locals;
- res->num_locals = header->num_locals;
- res->clauses = header->clauses;
- for (i = 0; i < header->num_locals; ++i)
- res->locals [i] = mono_class_inflate_generic_type (header->locals [i], context);
+
+ res->is_transient = TRUE;
+
+ mono_error_init (error);
+
+ for (int i = 0; i < header->num_locals; ++i) {
+ res->locals [i] = mono_class_inflate_generic_type_checked (header->locals [i], context, error);
+ if (!is_ok (error))
+ goto fail;
+ }
if (res->num_clauses) {
- res->clauses = (MonoExceptionClause *)g_memdup (header->clauses, sizeof (MonoExceptionClause) * res->num_clauses);
- for (i = 0; i < header->num_clauses; ++i) {
+ for (int i = 0; i < header->num_clauses; ++i) {
MonoExceptionClause *clause = &res->clauses [i];
if (clause->flags != MONO_EXCEPTION_CLAUSE_NONE)
continue;
- clause->data.catch_class = mono_class_inflate_generic_class (clause->data.catch_class, context);
+ clause->data.catch_class = mono_class_inflate_generic_class_checked (clause->data.catch_class, context, error);
+ if (!is_ok (error))
+ goto fail;
}
}
return res;
+fail:
+ g_free (res);
+ return NULL;
}
/*
{
MonoError error;
MonoMethodSignature *res = mono_method_get_signature_checked (method, image, token, context, &error);
- g_assert (mono_error_ok (&error));
+ mono_error_cleanup (&error);
return res;
}
if (table == MONO_TABLE_METHODSPEC) {
/* the verifier (do_invoke_method) will turn the NULL into a verifier error */
- if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) || !method->is_inflated)
+ if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) || !method->is_inflated) {
+ mono_error_set_bad_image (error, image, "Method is a pinvoke or open generic");
return NULL;
+ }
return mono_method_signature_checked (method, error);
}
{
MonoError error;
MonoMethodSignature *res = mono_method_get_signature_checked (method, image, token, NULL, &error);
- g_assert (mono_error_ok (&error));
+ mono_error_cleanup (&error);
return res;
}
int i;
mono_class_setup_methods (klass);
- g_assert (!klass->exception_type); /*FIXME this should not fail, right?*/
+ g_assert (!mono_class_has_failure (klass)); /*FIXME this should not fail, right?*/
for (i = 0; i < klass->method.count; ++i) {
MonoMethod *method = klass->methods [i];
if (strcmp (method->name, name) == 0 && sig->param_count == method->signature->param_count)
if (image_is_dynamic (image)) {
MonoClass *handle_class;
- result = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, TRUE, &handle_class, context);
+ result = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, TRUE, &handle_class, context, error);
+ mono_error_assert_ok (error);
mono_loader_assert_no_error ();
// This checks the memberref type as well
MonoMethod *
mono_get_method (MonoImage *image, guint32 token, MonoClass *klass)
{
- return mono_get_method_full (image, token, klass, NULL);
+ MonoError error;
+ MonoMethod *result = mono_get_method_checked (image, token, klass, NULL, &error);
+ mono_error_cleanup (&error);
+ return result;
}
MonoMethod *
{
MonoError error;
MonoMethod *result = mono_get_method_checked (image, token, klass, context, &error);
- mono_loader_assert_no_error ();
- if (!mono_error_ok (&error)) {
- mono_loader_set_error_from_mono_error (&error);
- mono_error_cleanup (&error);
- }
+ mono_error_cleanup (&error);
return result;
}
{
MonoError error;
MonoMethod *result = mono_get_method_constrained_checked (image, token, constrained_class, context, cil_method, &error);
-
- mono_loader_assert_no_error ();
- if (!mono_error_ok (&error)) {
- mono_loader_set_error_from_mono_error (&error);
- mono_error_cleanup (&error);
- }
+ mono_error_cleanup (&error);
return result;
}
}
MonoMethodHeader*
-mono_method_get_header (MonoMethod *method)
+mono_method_get_header_checked (MonoMethod *method, MonoError *error)
{
int idx;
guint32 rva;
MonoImage* img;
gpointer loc;
- MonoMethodHeader *header;
MonoGenericContainer *container;
- if ((method->flags & METHOD_ATTRIBUTE_ABSTRACT) || (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) || (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) || (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
- return NULL;
-
+ mono_error_init (error);
img = method->klass->image;
+ if ((method->flags & METHOD_ATTRIBUTE_ABSTRACT) || (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) || (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) || (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)) {
+ mono_error_set_bad_image (error, img, "Method has no body");
+ return NULL;
+ }
+
if (method->is_inflated) {
MonoMethodInflated *imethod = (MonoMethodInflated *) method;
MonoMethodHeader *header, *iheader;
- header = mono_method_get_header (imethod->declaring);
+ header = mono_method_get_header_checked (imethod->declaring, error);
if (!header)
return NULL;
- iheader = inflate_generic_header (header, mono_method_get_context (method));
+ iheader = inflate_generic_header (header, mono_method_get_context (method), error);
mono_metadata_free_mh (header);
-
- mono_image_lock (img);
-
- if (imethod->header) {
- mono_metadata_free_mh (iheader);
- mono_image_unlock (img);
- return imethod->header;
+ if (!iheader) {
+ return NULL;
}
- mono_memory_barrier ();
- imethod->header = iheader;
-
- mono_image_unlock (img);
-
- return imethod->header;
+ return iheader;
}
if (method->wrapper_type != MONO_WRAPPER_NONE || method->sre_method) {
idx = mono_metadata_token_index (method->token);
rva = mono_metadata_decode_row_col (&img->tables [MONO_TABLE_METHOD], idx - 1, MONO_METHOD_RVA);
- if (!mono_verifier_verify_method_header (img, rva, NULL))
+ if (!mono_verifier_verify_method_header (img, rva, NULL)) {
+ mono_error_set_bad_image (error, img, "Invalid method header, failed verification");
return NULL;
+ }
loc = mono_image_rva_map (img, rva);
- if (!loc)
+ if (!loc) {
+ mono_error_set_bad_image (error, img, "Method has zero rva");
return NULL;
+ }
/*
* When parsing the types of local variables, we must pass any container available
container = mono_method_get_generic_container (method);
if (!container)
container = method->klass->generic_container;
- header = mono_metadata_parse_mh_full (img, container, (const char *)loc);
+ return mono_metadata_parse_mh_full (img, container, (const char *)loc, error);
+}
+MonoMethodHeader*
+mono_method_get_header (MonoMethod *method)
+{
+ MonoError error;
+ MonoMethodHeader *header = mono_method_get_header_checked (method, &error);
+ mono_error_cleanup (&error);
return header;
}
+
guint32
mono_method_get_flags (MonoMethod *method, guint32 *iflags)
{
return mono_metadata_token_index (method->token);
mono_class_setup_methods (klass);
- if (klass->exception_type)
+ if (mono_class_has_failure (klass))
return 0;
for (i = 0; i < klass->method.count; ++i) {
if (method == klass->methods [i]) {