Fix the matching of exceptions in llvmonly mode. Add a new AOT_JIT_INFO patch type...
[mono.git] / mono / metadata / verify.c
index 95bde8efbc5433a93c092b52b3d363ee63b859b5..68fe0688774e03bdf70e4f80f566f1e98cc3abf8 100644 (file)
 #include <mono/metadata/tokentype.h>
 #include <mono/metadata/mono-basic-block.h>
 #include <mono/metadata/attrdefs.h>
+#include <mono/metadata/class-internals.h>
 #include <mono/utils/mono-counters.h>
 #include <mono/utils/monobitset.h>
 #include <string.h>
-#include <signal.h>
 #include <ctype.h>
 
 static MiniVerifierMode verifier_mode = MONO_VERIFIER_MODE_OFF;
@@ -531,6 +531,8 @@ mono_type_is_valid_type_in_context_full (MonoType *type, MonoGenericContext *con
                        return FALSE;
                break;
        }
+       default:
+               break;
        }
        return TRUE;
 }
@@ -934,6 +936,7 @@ mono_method_is_valid_in_context (VerifyContext *ctx, MonoMethod *method)
        
 static MonoClassField*
 verifier_load_field (VerifyContext *ctx, int token, MonoClass **out_klass, const char *opcode) {
+       MonoError error;
        MonoClassField *field;
        MonoClass *klass = NULL;
 
@@ -946,12 +949,12 @@ verifier_load_field (VerifyContext *ctx, int token, MonoClass **out_klass, const
                        return NULL;
                }
 
-               field = mono_field_from_token (ctx->image, token, &klass, ctx->generic_context);
+               field = mono_field_from_token_checked (ctx->image, token, &klass, ctx->generic_context, &error);
+               mono_error_cleanup (&error); /*FIXME don't swallow the error */
        }
 
-       if (!field || !field->parent || !klass || mono_loader_get_last_error ()) {
+       if (!field || !field->parent || !klass) {
                ADD_VERIFY_ERROR2 (ctx, g_strdup_printf ("Cannot load field from token 0x%08x for %s at 0x%04x", token, opcode, ctx->ip_offset), MONO_EXCEPTION_BAD_IMAGE);
-               mono_loader_clear_error ();
                return NULL;
        }
 
@@ -973,20 +976,22 @@ static MonoMethod*
 verifier_load_method (VerifyContext *ctx, int token, const char *opcode) {
        MonoMethod* method;
 
+
        if (ctx->method->wrapper_type != MONO_WRAPPER_NONE) {
                method = mono_method_get_wrapper_data (ctx->method, (guint32)token);
        } else {
+               MonoError error;
                if (!IS_METHOD_DEF_OR_REF_OR_SPEC (token) || !token_bounds_check (ctx->image, token)) {
                        ADD_VERIFY_ERROR2 (ctx, g_strdup_printf ("Invalid method token 0x%08x for %s at 0x%04x", token, opcode, ctx->ip_offset), MONO_EXCEPTION_BAD_IMAGE);
                        return NULL;
                }
 
-               method = mono_get_method_full (ctx->image, token, NULL, ctx->generic_context);
+               method = mono_get_method_checked (ctx->image, token, NULL, ctx->generic_context, &error);
+               mono_error_cleanup (&error); /* FIXME don't swallow this error */
        }
 
-       if (!method || mono_loader_get_last_error ()) {
+       if (!method) {
                ADD_VERIFY_ERROR2 (ctx, g_strdup_printf ("Cannot load method from token 0x%08x for %s at 0x%04x", token, opcode, ctx->ip_offset), MONO_EXCEPTION_BAD_IMAGE);
-               mono_loader_clear_error ();
                return NULL;
        }
        
@@ -1446,6 +1451,8 @@ is_valid_bool_arg (ILStackDesc *arg)
                         * is it a "class Foo<T>" or a "struct Foo<T>"?
                         */
                        return !arg->type->data.generic_class->container_class->valuetype;
+               default:
+                       return FALSE;
                }
        default:
                return FALSE;
@@ -2982,6 +2989,12 @@ stack_slot_is_complex_type_not_reference_type (ILStackDesc *slot)
        return stack_slot_get_type (slot) == TYPE_COMPLEX && !MONO_TYPE_IS_REFERENCE (slot->type) && !stack_slot_is_boxed_value (slot);
 }
 
+static gboolean
+stack_slot_is_reference_value (ILStackDesc *slot)
+{
+       return stack_slot_get_type (slot) == TYPE_COMPLEX && (MONO_TYPE_IS_REFERENCE (slot->type) || stack_slot_is_boxed_value (slot));
+}
+
 static void
 do_branch_op (VerifyContext *ctx, signed int delta, const unsigned char table [TYPE_MAX][TYPE_MAX])
 {
@@ -3055,7 +3068,8 @@ do_cmp_op (VerifyContext *ctx, const unsigned char table [TYPE_MAX][TYPE_MAX], g
        a = stack_pop (ctx);
 
        if (opcode == CEE_CGT_UN) {
-               if (stack_slot_get_type (a) == TYPE_COMPLEX && stack_slot_get_type (b) == TYPE_COMPLEX) {
+               if ((stack_slot_is_reference_value (a) && stack_slot_is_null_literal (b)) ||
+                       (stack_slot_is_reference_value (b) && stack_slot_is_null_literal (a))) {
                        stack_push_val (ctx, TYPE_I4, &mono_defaults.int32_class->byval_arg);
                        return;
                }
@@ -3078,7 +3092,11 @@ do_cmp_op (VerifyContext *ctx, const unsigned char table [TYPE_MAX][TYPE_MAX], g
        }
 
        if(res == TYPE_INV) {
-               CODE_NOT_VERIFIABLE (ctx, g_strdup_printf("Compare instruction applyed to ill formed stack (%s x %s) at 0x%04x", stack_slot_get_name (a), stack_slot_get_name (b), ctx->ip_offset));
+               char *left_type = stack_slot_full_name (a);
+               char *right_type = stack_slot_full_name (b);
+               CODE_NOT_VERIFIABLE (ctx, g_strdup_printf("Compare instruction applyed to ill formed stack (%s x %s) at 0x%04x", left_type, right_type, ctx->ip_offset));
+               g_free (left_type);
+               g_free (right_type);
        } else if (res & NON_VERIFIABLE_RESULT) {
                CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Compare instruction is not verifiable (%s x %s) at 0x%04x", stack_slot_get_name (a), stack_slot_get_name (b), ctx->ip_offset)); 
                res = res & ~NON_VERIFIABLE_RESULT;
@@ -3126,6 +3144,7 @@ do_ret (VerifyContext *ctx)
 static void
 do_invoke_method (VerifyContext *ctx, int method_token, gboolean virtual)
 {
+       MonoError error;
        int param_count, i;
        MonoMethodSignature *sig;
        ILStackDesc *value;
@@ -3155,12 +3174,15 @@ do_invoke_method (VerifyContext *ctx, int method_token, gboolean virtual)
                }
        }
 
-       if (!(sig = mono_method_get_signature_full (method, ctx->image, method_token, ctx->generic_context)))
-               sig = mono_method_get_signature (method, ctx->image, method_token);
+       if (!(sig = mono_method_get_signature_checked (method, ctx->image, method_token, ctx->generic_context, &error))) {
+               mono_error_cleanup (&error);
+               sig = mono_method_get_signature_checked (method, ctx->image, method_token, NULL, &error);
+       }
 
        if (!sig) {
                char *name = mono_type_get_full_name (method->klass);
-               ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Could not resolve signature of %s:%s at 0x%04x", name, method->name, ctx->ip_offset));
+               ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Could not resolve signature of %s:%s at 0x%04x due to: %s", name, method->name, ctx->ip_offset, mono_error_get_message (&error)));
+               mono_error_cleanup (&error);
                g_free (name);
                return;
        }
@@ -3591,6 +3613,7 @@ do_conversion (VerifyContext *ctx, int kind)
 static void
 do_load_token (VerifyContext *ctx, int token) 
 {
+       MonoError error;
        gpointer handle;
        MonoClass *handle_class;
        if (!check_overflow (ctx))
@@ -3620,11 +3643,12 @@ do_load_token (VerifyContext *ctx, int token)
                        return;
                }
 
-               handle = mono_ldtoken (ctx->image, token, &handle_class, ctx->generic_context);
+               handle = mono_ldtoken_checked (ctx->image, token, &handle_class, ctx->generic_context, &error);
        }
 
        if (!handle) {
-               ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Invalid token 0x%x for ldtoken at 0x%04x", token, ctx->ip_offset));
+               ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Invalid token 0x%x for ldtoken at 0x%04x due to %s", token, ctx->ip_offset, mono_error_get_message (&error)));
+               mono_error_cleanup (&error);
                return;
        }
        if (handle_class == mono_defaults.typehandle_class) {
@@ -3882,6 +3906,8 @@ do_cast (VerifyContext *ctx, int token, const char *opcode) {
        case MONO_TYPE_PTR:
        case MONO_TYPE_TYPEDBYREF: 
                CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid value for %s at 0x%04x", opcode, ctx->ip_offset));
+       default:
+               break;
        }
 
        do_box = is_boxed || mono_type_is_generic_argument(type) || mono_class_from_mono_type (type)->valuetype;
@@ -4397,8 +4423,6 @@ do_sizeof (VerifyContext *ctx, int token)
 static void
 do_localloc (VerifyContext *ctx)
 {
-       ILStackDesc *top;
-       
        if (ctx->eval.size != 1) {
                ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Stack must have only size item in localloc at 0x%04x", ctx->ip_offset));
                return;         
@@ -4410,7 +4434,7 @@ do_localloc (VerifyContext *ctx)
        }
 
        /*TODO verify top type*/
-       top = stack_pop (ctx);
+       /* top = */ stack_pop (ctx);
 
        set_stack_value (ctx, stack_push (ctx), &mono_defaults.int_class->byval_arg, FALSE);
        CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Instruction localloc in never verifiable at 0x%04x", ctx->ip_offset));
@@ -4802,7 +4826,7 @@ mono_method_verify (MonoMethod *method, int level)
        MonoSimpleBasicBlock *bb = NULL, *original_bb = NULL;
 
        int i, n, need_merge = 0, start = 0;
-       guint token, ip_offset = 0, prefix = 0;
+       guint ip_offset = 0, prefix = 0;
        MonoGenericContext *generic_context = NULL;
        MonoImage *image;
        VerifyContext ctx;
@@ -5347,7 +5371,7 @@ mono_method_verify (MonoMethod *method, int level)
                        code_bounds_check (5);
                        if (ctx.eval.size)
                                ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Eval stack must be empty in jmp at 0x%04x", ip_offset));
-                       token = read32 (ip + 1);
+                       /* token = read32 (ip + 1); */
                        if (in_any_block (ctx.header, ip_offset))
                                ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("jmp cannot escape exception blocks at 0x%04x", ip_offset));
 
@@ -5366,7 +5390,7 @@ mono_method_verify (MonoMethod *method, int level)
 
                case CEE_CALLI:
                        code_bounds_check (5);
-                       token = read32 (ip + 1);
+                       /* token = read32 (ip + 1); */
                        /*
                         * FIXME: check signature, retval, arguments etc.
                         * FIXME: check requirements for tail call