initial verifier
authorRodrigo Kumpera <kumpera@gmail.com>
Fri, 9 Jan 2009 13:36:29 +0000 (13:36 -0000)
committerRodrigo Kumpera <kumpera@gmail.com>
Fri, 9 Jan 2009 13:36:29 +0000 (13:36 -0000)
svn path=/trunk/mono/; revision=122883

mono/metadata/Makefile.am
mono/metadata/metadata-verify.c [new file with mode: 0644]
mono/metadata/pedump.c
mono/metadata/verify-internals.h

index b3e2aa8c49a6e08a9d6a77c1217f56cb94071444..83f8532369beaa4032d7a8e7fd81240d5a4268ac 100644 (file)
@@ -140,7 +140,8 @@ libmonoruntime_la_SOURCES = \
        mono-perfcounters-def.h \
        debug-helpers.c \
        generic-sharing.c       \
-       mempool-internals.h
+       mempool-internals.h     \
+       metadata-verify.c
 
 libmonoruntime_static_la_SOURCES = $(libmonoruntime_la_SOURCES)
 
diff --git a/mono/metadata/metadata-verify.c b/mono/metadata/metadata-verify.c
new file mode 100644 (file)
index 0000000..f1fef13
--- /dev/null
@@ -0,0 +1,67 @@
+#include <mono/metadata/object-internals.h>
+#include <mono/metadata/verify.h>
+#include <mono/metadata/verify-internals.h>
+#include <mono/metadata/opcodes.h>
+#include <mono/metadata/tabledefs.h>
+#include <mono/metadata/reflection.h>
+#include <mono/metadata/debug-helpers.h>
+#include <mono/metadata/mono-endian.h>
+#include <mono/metadata/metadata.h>
+#include <mono/metadata/metadata-internals.h>
+#include <mono/metadata/class-internals.h>
+#include <mono/metadata/tokentype.h>
+#include <string.h>
+#include <signal.h>
+#include <ctype.h>
+
+typedef struct {
+       const char *data;
+       guint32 size;
+       GSList *errors;
+       int valid;
+} VerifyContext;
+
+#define ADD_VERIFY_INFO(__ctx, __msg, __status, __exception)   \
+       do {    \
+               MonoVerifyInfoExtended *vinfo = g_new (MonoVerifyInfoExtended, 1);      \
+               vinfo->info.status = __status;  \
+               vinfo->info.message = ( __msg); \
+               vinfo->exception_type = (__exception);  \
+               (__ctx)->errors = g_slist_prepend ((__ctx)->errors, vinfo);     \
+       } while (0)
+
+
+#define ADD_ERROR(__ctx, __msg)        \
+       do {    \
+               ADD_VERIFY_INFO(__ctx, __msg, MONO_VERIFY_ERROR, MONO_EXCEPTION_INVALID_PROGRAM); \
+               (__ctx)->valid = 0; \
+       } while (0)
+
+#define CHECK_STATE() do { if (!ctx.valid) goto cleanup; } while (0)
+
+static void
+verify_msdos_header (VerifyContext *ctx)
+{
+       if (ctx->size < 128) {
+               ADD_ERROR (ctx, g_strdup ("Not enough space for the MS-DOS header"));
+               return;
+       }
+       if (ctx->data [0] != 0x4d || ctx->data [1] != 0x5a)
+               ADD_ERROR (ctx,  g_strdup ("Invalid MS-DOS watermark"));
+}
+
+GSList*
+mono_image_verify (const char *data, guint32 size)
+{
+       VerifyContext ctx;
+       memset (&ctx, 0, sizeof (VerifyContext));
+       ctx.data = data;
+       ctx.size = size;
+       ctx.valid = 1;
+
+       verify_msdos_header (&ctx);
+       CHECK_STATE();
+
+cleanup:
+       return ctx.errors;
+}
index 331230b5c974930976db5d112e5ef033e989a43d..81917005b4bc94934fb8f8fdc4bf014e969fc5d1 100644 (file)
 #include <mono/metadata/class-internals.h>
 #include <mono/metadata/verify-internals.h>
 #include "mono/utils/mono-digest.h"
+#include <mono/utils/mono-mmap.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
 
 gboolean dump_data = TRUE;
 gboolean verify_pe = FALSE;
@@ -398,12 +404,65 @@ dump_verify_info (MonoImage *image, int flags)
 static void
 usage (void)
 {
-       printf ("Usage is: pedump [--verify error,warn,cls,all,code,fail-on-verifiable,non-strict,valid-only] file.exe\n");
+       printf ("Usage is: pedump [--verify error,warn,cls,all,code,fail-on-verifiable,non-strict,valid-only,metadata] file.exe\n");
        exit (1);
 }
 
+static int
+verify_image_file (const char *fname)
+{
+       FILE *filed;
+       struct stat stat_buf;
+       void *raw_data_handle;
+       char *raw_data;
+       GSList *errors, *tmp;
+       int count = 0;
+       const char* desc [] = {
+               "Ok", "Error", "Warning", NULL, "CLS", NULL, NULL, NULL, "Not Verifiable"
+       };
+
+       if ((filed = fopen (fname, "rb")) == NULL) {
+               fprintf (stderr, "Cannot open file %s\n", fname);
+               exit (1);
+       }
+
+       if (fstat (fileno (filed), &stat_buf)) {
+               fclose (filed);
+               fprintf (stderr, "Cannot stat file %s\n", fname);
+               exit (1);
+       }
+
+       raw_data = mono_file_map (stat_buf.st_size, MONO_MMAP_READ|MONO_MMAP_PRIVATE, fileno (filed), 0, &raw_data_handle);
+
+       if (!raw_data) {
+               fprintf (stderr, "Could not mmap file %s\n", fname);
+               exit (1);
+       }
+       fclose (filed);
+
+       errors = mono_image_verify (raw_data, stat_buf.st_size);
+       mono_file_unmap (raw_data, raw_data_handle);
+
+       if (!errors)
+               return 0;
+
+       for (tmp = errors; tmp; tmp = tmp->next) {
+               MonoVerifyInfo *info = tmp->data;
+               g_print ("%s: %s\n", desc [info->status], info->message);
+               if (info->status == MONO_VERIFY_ERROR)
+                       count++;
+       }
+       mono_free_verify_list (errors);
+       if (count)
+               g_print ("Error count: %d\n", count);
+
+       return count > 0 ? 1 : 0;
+}
+
 #define VALID_ONLY_FLAG 0x08000000
 #define VERIFY_CODE_ONLY MONO_VERIFY_ALL + 1 
+#define VERIFY_METADATA_ONLY VERIFY_CODE_ONLY + 1
+
 int
 main (int argc, char *argv [])
 {
@@ -411,9 +470,9 @@ main (int argc, char *argv [])
        char *file = NULL;
        char *flags = NULL;
        MiniVerifierMode verifier_mode = MONO_VERIFIER_MODE_VERIFIABLE;
-       const char *flag_desc [] = {"error", "warn", "cls", "all", "code", "fail-on-verifiable", "non-strict", "valid-only", NULL};
-       guint flag_vals [] = {MONO_VERIFY_ERROR, MONO_VERIFY_WARNING, MONO_VERIFY_CLS, MONO_VERIFY_ALL, VERIFY_CODE_ONLY, MONO_VERIFY_FAIL_FAST, MONO_VERIFY_NON_STRICT, VALID_ONLY_FLAG, 0};
-       int i;
+       const char *flag_desc [] = {"error", "warn", "cls", "all", "code", "fail-on-verifiable", "non-strict", "valid-only", "metadata", NULL};
+       guint flag_vals [] = {MONO_VERIFY_ERROR, MONO_VERIFY_WARNING, MONO_VERIFY_CLS, MONO_VERIFY_ALL, VERIFY_CODE_ONLY, MONO_VERIFY_FAIL_FAST, MONO_VERIFY_NON_STRICT, VALID_ONLY_FLAG, VERIFY_METADATA_ONLY, 0};
+       int i, verify_flags = MONO_VERIFY_REPORT_ALL_ERRORS, run_new_metadata_verifier = 0;
        
        for (i = 1; i < argc; i++){
                if (argv [i][0] != '-'){
@@ -442,18 +501,9 @@ main (int argc, char *argv [])
        mono_assemblies_init ();
        mono_loader_init ();
  
-       image = mono_image_open (file, NULL);
-       if (!image){
-               fprintf (stderr, "Can not open image %s\n", file);
-               exit (1);
-       }
-
-       if (dump_data)
-               dump_dotnet_iinfo (image);
        if (verify_pe) {
-               int f = MONO_VERIFY_REPORT_ALL_ERRORS;
                char *tok = strtok (flags, ",");
-               MonoAssembly *assembly;
+
                verify_metadata = 1;
                verify_code = 0;
                while (tok) {
@@ -462,12 +512,16 @@ main (int argc, char *argv [])
                                        if (flag_vals [i] == VERIFY_CODE_ONLY) {
                                                verify_metadata = 0;
                                                verify_code = 1;
-                                       } else if(flag_vals [i] == MONO_VERIFY_ALL)
+                                       } else if(flag_vals [i] == MONO_VERIFY_ALL) {
                                                verify_code = 1;
+                                       } else if(flag_vals [i] == VERIFY_METADATA_ONLY) {
+                                               verify_metadata = 0;
+                                               run_new_metadata_verifier = 1;
+                                       }
                                        if (flag_vals [i] == VALID_ONLY_FLAG)
                                                verifier_mode = MONO_VERIFIER_MODE_VALID;
                                        else
-                                               f |= flag_vals [i];
+                                               verify_flags |= flag_vals [i];
                                        break;
                                }
                        }
@@ -477,6 +531,23 @@ main (int argc, char *argv [])
                }
 
                mono_verifier_set_mode (verifier_mode);
+               /**/
+       }
+
+       if (run_new_metadata_verifier)
+               return verify_image_file (file);
+
+       image = mono_image_open (file, NULL);
+       if (!image){
+               fprintf (stderr, "Cannot open image %s\n", file);
+               exit (1);
+       }
+
+       if (dump_data)
+               dump_dotnet_iinfo (image);
+       if (verify_pe) {
+               MonoAssembly *assembly;
+
                mono_init_from_assembly (file, file);
                assembly = mono_assembly_open (file, NULL);
 
@@ -485,7 +556,7 @@ main (int argc, char *argv [])
                        return 4;
                }
 
-               return dump_verify_info (assembly->image, f);
+               return dump_verify_info (assembly->image, verify_flags);
        } else
                mono_image_close (image);
        
index 189a90098d815ba56dc615c266d7fdc6291d7180..a169e4743d18c28a9ec66ef46f50b748d6a0f581 100644 (file)
@@ -24,6 +24,9 @@ gboolean mono_verifier_is_class_full_trust (MonoClass *klass) MONO_INTERNAL;
 gboolean mono_verifier_verify_class (MonoClass *klass) MONO_INTERNAL;
 
 GSList* mono_method_verify_with_current_settings (MonoMethod *method, gboolean skip_visibility) MONO_INTERNAL;
+
+GSList* mono_image_verify (const char *data, guint32 size) MONO_INTERNAL;
+
 G_END_DECLS
 
 #endif  /* __MONO_METADATA_VERIFY_INTERNAL_H__ */