+static int
+verify_image_file (const char *fname)
+{
+ GSList *errors = NULL, *tmp;
+ MonoImage *image;
+ MonoTableInfo *table;
+ MonoAssembly *assembly;
+ MonoImageOpenStatus status;
+ int i, count = 0;
+ const char* desc [] = {
+ "Ok", "Error", "Warning", NULL, "CLS", NULL, NULL, NULL, "Not Verifiable"
+ };
+
+ image = mono_image_open_raw (fname, &status);
+ if (!image) {
+ printf ("Could not open %s\n", fname);
+ return 1;
+ }
+
+ if (!mono_verifier_verify_pe_data (image, &errors))
+ goto invalid_image;
+
+ if (!mono_image_load_pe_data (image)) {
+ printf ("Could not load pe data for assembly %s\n", fname);
+ return 1;
+ }
+
+ if (!mono_verifier_verify_cli_data (image, &errors))
+ goto invalid_image;
+
+ if (!mono_image_load_cli_data (image)) {
+ printf ("Could not load cli data for assembly %s\n", fname);
+ return 1;
+ }
+
+ if (!mono_verifier_verify_table_data (image, &errors))
+ goto invalid_image;
+
+ mono_image_load_names (image);
+
+ if (!mono_verifier_verify_full_table_data (image, &errors))
+ goto invalid_image;
+
+
+ /*fake an assembly for class loading to work*/
+ assembly = g_new0 (MonoAssembly, 1);
+ assembly->in_gac = FALSE;
+ assembly->image = image;
+ image->assembly = assembly;
+
+ table = &image->tables [MONO_TABLE_TYPEDEF];
+ for (i = 1; i <= table->rows; ++i) {
+ guint32 token = i | MONO_TOKEN_TYPE_DEF;
+ MonoClass *class = mono_class_get (image, token);
+ if (!class) {
+ printf ("Could not load class with token %x\n", token);
+ continue;
+ }
+ mono_class_init (class);
+ if (class->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ()) {
+ printf ("Error verifying class(0x%08x) %s.%s a type load error happened\n", token, class->name_space, class->name);
+ mono_loader_clear_error ();
+ ++count;
+ }
+ }
+ if (count)
+ return 1;
+ return 0;
+
+invalid_image:
+ 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 1;
+}
+
+static gboolean
+try_load_from (MonoAssembly **assembly, const gchar *path1, const gchar *path2,
+ const gchar *path3, const gchar *path4, gboolean refonly)
+{
+ gchar *fullpath;
+
+ *assembly = NULL;
+ fullpath = g_build_filename (path1, path2, path3, path4, NULL);
+ if (g_file_test (fullpath, G_FILE_TEST_IS_REGULAR))
+ *assembly = mono_assembly_open_full (fullpath, NULL, refonly);
+
+ g_free (fullpath);
+ return (*assembly != NULL);
+}
+
+static MonoAssembly *
+real_load (gchar **search_path, const gchar *culture, const gchar *name, gboolean refonly)
+{
+ MonoAssembly *result = NULL;
+ gchar **path;
+ gchar *filename;
+ const gchar *local_culture;
+ gint len;
+
+ if (!culture || *culture == '\0') {
+ local_culture = "";
+ } else {
+ local_culture = culture;
+ }
+
+ filename = g_strconcat (name, ".dll", NULL);
+ len = strlen (filename);
+
+ for (path = search_path; *path; path++) {
+ if (**path == '\0')
+ continue; /* Ignore empty ApplicationBase */
+
+ /* See test cases in bug #58992 and bug #57710 */
+ /* 1st try: [culture]/[name].dll (culture may be empty) */
+ strcpy (filename + len - 4, ".dll");
+ if (try_load_from (&result, *path, local_culture, "", filename, refonly))
+ break;
+
+ /* 2nd try: [culture]/[name].exe (culture may be empty) */
+ strcpy (filename + len - 4, ".exe");
+ if (try_load_from (&result, *path, local_culture, "", filename, refonly))
+ break;
+
+ /* 3rd try: [culture]/[name]/[name].dll (culture may be empty) */
+ strcpy (filename + len - 4, ".dll");
+ if (try_load_from (&result, *path, local_culture, name, filename, refonly))
+ break;
+
+ /* 4th try: [culture]/[name]/[name].exe (culture may be empty) */
+ strcpy (filename + len - 4, ".exe");
+ if (try_load_from (&result, *path, local_culture, name, filename, refonly))
+ break;
+ }
+
+ g_free (filename);
+ return result;
+}
+
+/*
+ * Try to load referenced assemblies from assemblies_path.
+ */
+static MonoAssembly *
+pedump_preload (MonoAssemblyName *aname,
+ gchar **assemblies_path,
+ gpointer user_data)
+{
+ MonoAssembly *result = NULL;
+ gboolean refonly = GPOINTER_TO_UINT (user_data);
+
+ if (assemblies_path && assemblies_path [0] != NULL) {
+ result = real_load (assemblies_path, aname->culture, aname->name, refonly);
+ }
+
+ return result;
+}
+
+static GList *loaded_assemblies = NULL;
+
+static void
+pedump_assembly_load_hook (MonoAssembly *assembly, gpointer user_data)
+{
+ loaded_assemblies = g_list_prepend (loaded_assemblies, assembly);
+}
+
+static MonoAssembly *
+pedump_assembly_search_hook (MonoAssemblyName *aname, gpointer user_data)
+{
+ GList *tmp;
+
+ for (tmp = loaded_assemblies; tmp; tmp = tmp->next) {
+ MonoAssembly *ass = tmp->data;
+ if (mono_assembly_names_equal (aname, &ass->aname))
+ return ass;
+ }
+ return NULL;
+}
+
+#define VALID_ONLY_FLAG 0x08000000
+#define VERIFY_CODE_ONLY MONO_VERIFY_ALL + 1
+#define VERIFY_METADATA_ONLY VERIFY_CODE_ONLY + 1
+