2 * pedump.c: Dumps the contents of an extended PE/COFF file
5 * Miguel de Icaza (miguel@ximian.com)
7 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
15 #include <mono/metadata/image.h>
17 #include <mono/metadata/cil-coff.h>
18 #include <mono/metadata/mono-endian.h>
19 #include <mono/metadata/verify.h>
20 #include <mono/metadata/class.h>
21 #include <mono/metadata/debug-helpers.h>
22 #include <mono/metadata/tokentype.h>
23 #include <mono/metadata/appdomain.h>
24 #include <mono/metadata/assembly-internals.h>
25 #include <mono/metadata/metadata-internals.h>
26 #include <mono/metadata/class-internals.h>
27 #include <mono/metadata/class-init.h>
28 #include <mono/metadata/verify-internals.h>
29 #include <mono/metadata/marshal.h>
30 #include <mono/metadata/w32handle.h>
31 #include "mono/utils/mono-digest.h"
32 #include <mono/utils/mono-mmap.h>
33 #include <mono/utils/mono-counters.h>
34 #include <mono/utils/mono-error-internals.h>
35 #include <sys/types.h>
41 gboolean dump_data
= TRUE
;
42 gboolean verify_pe
= FALSE
;
43 gboolean verify_metadata
= FALSE
;
44 gboolean verify_code
= FALSE
;
45 gboolean verify_partial_md
= FALSE
;
47 static char *assembly_directory
[2];
49 static MonoAssembly
*pedump_preload (MonoAssemblyLoadContext
*alc
, MonoAssemblyName
*aname
, char **assemblies_path
, gboolean refonly
, gpointer user_data
, MonoError
*error
);
50 static void pedump_assembly_load_hook (MonoAssemblyLoadContext
*alc
, MonoAssembly
*assembly
, gpointer user_data
, MonoError
*error
);
51 static MonoAssembly
*pedump_assembly_search_hook (MonoAssemblyLoadContext
*alc
, MonoAssembly
*requesting
, MonoAssemblyName
*aname
, gboolean refonly
, gboolean postload
, gpointer user_data
, MonoError
*error
);
55 hex_dump (const char *buffer, int base, int count)
59 for (i = 0; i < count; i++){
61 printf ("\n0x%08x: ", (unsigned char) base + i);
63 printf ("%02x ", (unsigned char) (buffer [i]));
69 hex8 (const char *label
, unsigned char x
)
71 printf ("\t%s: 0x%02x\n", label
, (unsigned char) x
);
75 hex16 (const char *label
, guint16 x
)
77 printf ("\t%s: 0x%04x\n", label
, x
);
81 hex32 (const char *label
, guint32 x
)
83 printf ("\t%s: 0x%08x\n", label
, x
);
87 dump_coff_header (MonoCOFFHeader
*coff
)
89 printf ("\nCOFF Header:\n");
90 hex16 (" Machine", coff
->coff_machine
);
91 hex16 (" Sections", coff
->coff_sections
);
92 hex32 (" Time stamp", coff
->coff_time
);
93 hex32 ("Pointer to Symbol Table", coff
->coff_symptr
);
94 hex32 (" Symbol Count", coff
->coff_symcount
);
95 hex16 (" Optional Header Size", coff
->coff_opt_header_size
);
96 hex16 (" Characteristics", coff
->coff_attributes
);
101 dump_pe_header (MonoPEHeader
*pe
)
103 printf ("\nPE Header:\n");
104 hex16 (" Magic (0x010b)", pe
->pe_magic
);
105 hex8 (" LMajor (6)", pe
->pe_major
);
106 hex8 (" LMinor (0)", pe
->pe_minor
);
107 hex32 (" Code Size", pe
->pe_code_size
);
108 hex32 (" Initialized Data Size", pe
->pe_data_size
);
109 hex32 ("Uninitialized Data Size", pe
->pe_uninit_data_size
);
110 hex32 (" Entry Point RVA", pe
->pe_rva_entry_point
);
111 hex32 (" Code Base RVA", pe
->pe_rva_code_base
);
112 hex32 (" Data Base RVA", pe
->pe_rva_data_base
);
117 dump_nt_header (MonoPEHeaderNT
*nt
)
119 printf ("\nNT Header:\n");
121 hex32 (" Image Base (0x400000)", nt
->pe_image_base
);
122 hex32 ("Section Alignment (8192)", nt
->pe_section_align
);
123 hex32 (" File Align (512/4096)", nt
->pe_file_alignment
);
124 hex16 (" OS Major (4)", nt
->pe_os_major
);
125 hex16 (" OS Minor (0)", nt
->pe_os_minor
);
126 hex16 (" User Major (0)", nt
->pe_user_major
);
127 hex16 (" User Minor (0)", nt
->pe_user_minor
);
128 hex16 (" Subsys major (4)", nt
->pe_subsys_major
);
129 hex16 (" Subsys minor (0)", nt
->pe_subsys_minor
);
130 hex32 (" Reserverd", nt
->pe_reserved_1
);
131 hex32 (" Image Size", nt
->pe_image_size
);
132 hex32 (" Header Size", nt
->pe_header_size
);
133 hex32 (" Checksum (0)", nt
->pe_checksum
);
134 hex16 (" Subsystem", nt
->pe_subsys_required
);
135 hex16 (" DLL Flags (0)", nt
->pe_dll_flags
);
136 hex32 (" Stack Reserve Size (1M)", nt
->pe_stack_reserve
);
137 hex32 ("Stack commit Size (4096)", nt
->pe_stack_commit
);
138 hex32 (" Heap Reserve Size (1M)", nt
->pe_heap_reserve
);
139 hex32 (" Heap Commit Size (4096)", nt
->pe_heap_commit
);
140 hex32 (" Loader flags (0x1)", nt
->pe_loader_flags
);
141 hex32 (" Data Directories (16)", nt
->pe_data_dir_count
);
145 dent (const char *label
, MonoPEDirEntry de
)
147 printf ("\t%s: 0x%08x [0x%08x]\n", label
, de
.rva
, de
.size
);
151 dump_blob (const char *desc
, const char* p
, guint32 size
)
161 for (i
= 0; i
< size
; ++i
) {
164 printf (" %02X", p
[i
] & 0xFF);
170 dump_public_key (MonoImage
*m
)
175 p
= mono_image_get_public_key (m
, &size
);
176 dump_blob ("\nPublic key:", p
, size
);
180 dump_strong_name (MonoImage
*m
)
185 p
= mono_image_get_strong_name (m
, &size
);
186 dump_blob ("\nStrong name:", p
, size
);
190 dump_datadir (MonoPEDatadir
*dd
)
192 printf ("\nData directories:\n");
193 dent (" Export Table", dd
->pe_export_table
);
194 dent (" Import Table", dd
->pe_import_table
);
195 dent (" Resource Table", dd
->pe_resource_table
);
196 dent (" Exception Table", dd
->pe_exception_table
);
197 dent ("Certificate Table", dd
->pe_certificate_table
);
198 dent (" Reloc Table", dd
->pe_reloc_table
);
199 dent (" Debug", dd
->pe_debug
);
200 dent (" Copyright", dd
->pe_copyright
);
201 dent (" Global Ptr", dd
->pe_global_ptr
);
202 dent (" TLS Table", dd
->pe_tls_table
);
203 dent ("Load Config Table", dd
->pe_load_config_table
);
204 dent (" Bound Import", dd
->pe_bound_import
);
205 dent (" IAT", dd
->pe_iat
);
206 dent ("Delay Import Desc", dd
->pe_delay_import_desc
);
207 dent (" CLI Header", dd
->pe_cli_header
);
211 dump_dotnet_header (MonoDotNetHeader
*header
)
213 dump_coff_header (&header
->coff
);
214 dump_pe_header (&header
->pe
);
215 dump_nt_header (&header
->nt
);
216 dump_datadir (&header
->datadir
);
220 dump_section_table (MonoSectionTable
*st
)
222 guint32 flags
= st
->st_flags
;
224 printf ("\n\tName: %s\n", st
->st_name
);
225 hex32 (" Virtual Size", st
->st_virtual_size
);
226 hex32 ("Virtual Address", st
->st_virtual_address
);
227 hex32 (" Raw Data Size", st
->st_raw_data_size
);
228 hex32 (" Raw Data Ptr", st
->st_raw_data_ptr
);
229 hex32 (" Reloc Ptr", st
->st_reloc_ptr
);
230 hex32 (" LineNo Ptr", st
->st_lineno_ptr
);
231 hex16 (" Reloc Count", st
->st_reloc_count
);
232 hex16 (" Line Count", st
->st_line_count
);
234 printf ("\tFlags: %s%s%s%s%s%s%s%s%s%s\n",
235 (flags
& SECT_FLAGS_HAS_CODE
) ? "code, " : "",
236 (flags
& SECT_FLAGS_HAS_INITIALIZED_DATA
) ? "data, " : "",
237 (flags
& SECT_FLAGS_HAS_UNINITIALIZED_DATA
) ? "bss, " : "",
238 (flags
& SECT_FLAGS_MEM_DISCARDABLE
) ? "discard, " : "",
239 (flags
& SECT_FLAGS_MEM_NOT_CACHED
) ? "nocache, " : "",
240 (flags
& SECT_FLAGS_MEM_NOT_PAGED
) ? "nopage, " : "",
241 (flags
& SECT_FLAGS_MEM_SHARED
) ? "shared, " : "",
242 (flags
& SECT_FLAGS_MEM_EXECUTE
) ? "exec, " : "",
243 (flags
& SECT_FLAGS_MEM_READ
) ? "read, " : "",
244 (flags
& SECT_FLAGS_MEM_WRITE
) ? "write" : "");
248 dump_sections (MonoCLIImageInfo
*iinfo
)
250 const int top
= iinfo
->cli_header
.coff
.coff_sections
;
253 for (i
= 0; i
< top
; i
++)
254 dump_section_table (&iinfo
->cli_section_tables
[i
]);
258 dump_cli_header (MonoCLIHeader
*ch
)
261 printf (" CLI header size: %d\n", ch
->ch_size
);
262 printf (" Runtime required: %d.%d\n", ch
->ch_runtime_major
, ch
->ch_runtime_minor
);
263 printf (" Flags: %s, %s, %s, %s\n",
264 (ch
->ch_flags
& CLI_FLAGS_ILONLY
? "ilonly" : "contains native"),
265 (ch
->ch_flags
& CLI_FLAGS_32BITREQUIRED
? "32bits" : "32/64"),
266 (ch
->ch_flags
& CLI_FLAGS_TRACKDEBUGDATA
? "trackdebug" : "no-trackdebug"),
267 (ch
->ch_flags
& CLI_FLAGS_STRONGNAMESIGNED
? "strongnamesigned" : "notsigned"));
268 dent (" Metadata", ch
->ch_metadata
);
269 hex32 ("Entry Point Token", ch
->ch_entry_point
);
270 dent (" Resources at", ch
->ch_resources
);
271 dent (" Strong Name at", ch
->ch_strong_name
);
272 dent (" Code Manager at", ch
->ch_code_manager_table
);
273 dent (" VTableFixups at", ch
->ch_vtable_fixups
);
274 dent (" EAT jumps at", ch
->ch_export_address_table_jumps
);
278 dsh (const char *label
, MonoImage
*meta
, MonoStreamHeader
*sh
)
280 printf ("%s: 0x%08x - 0x%08x [%d == 0x%08x]\n",
282 (int)(sh
->data
- meta
->raw_metadata
), (int)(sh
->data
+ sh
->size
- meta
->raw_metadata
),
287 dump_metadata_header (MonoImage
*meta
)
289 printf ("\nMetadata header:\n");
290 printf (" Version: %d.%d\n", meta
->md_version_major
, meta
->md_version_minor
);
291 printf (" Version string: %s\n", meta
->version
);
295 dump_metadata_ptrs (MonoImage
*meta
)
297 printf ("\nMetadata pointers:\n");
298 dsh ("\tTables (#~)", meta
, &meta
->heap_tables
);
299 dsh ("\t Strings", meta
, &meta
->heap_strings
);
300 dsh ("\t Blob", meta
, &meta
->heap_blob
);
301 dsh ("\tUser string", meta
, &meta
->heap_us
);
302 dsh ("\t GUID", meta
, &meta
->heap_guid
);
306 dump_metadata (MonoImage
*meta
)
310 dump_metadata_header (meta
);
312 dump_metadata_ptrs (meta
);
315 for (table
= 0; table
< MONO_TABLE_NUM
; table
++){
316 if (meta
->tables
[table
].rows
== 0)
318 printf ("Table %s: %d records (%d bytes, at %x)\n",
319 mono_meta_table_name (table
),
320 meta
->tables
[table
].rows
,
321 meta
->tables
[table
].row_size
,
322 (unsigned int)(meta
->tables
[table
].base
- meta
->raw_data
)
328 dump_methoddef (MonoImage
*metadata
, guint32 token
)
334 loc
= mono_metadata_locate_token (metadata
, token
);
336 printf ("RVA for Entry Point: 0x%08x\n", read32 (loc
));
340 dump_dotnet_iinfo (MonoImage
*image
)
342 MonoCLIImageInfo
*iinfo
= (MonoCLIImageInfo
*)image
->image_info
;
344 dump_dotnet_header (&iinfo
->cli_header
);
345 dump_sections (iinfo
);
346 dump_cli_header (&iinfo
->cli_cli_header
);
347 dump_strong_name (image
);
348 dump_public_key (image
);
349 dump_metadata (image
);
351 dump_methoddef (image
, iinfo
->cli_cli_header
.ch_entry_point
);
355 dump_verify_info (MonoImage
*image
, int flags
, gboolean valid_only
)
357 GSList
*errors
, *tmp
;
358 int count
= 0, verifiable
= 0;
359 const char* desc
[] = {
360 "Ok", "Error", "Warning", NULL
, "CLS", NULL
, NULL
, NULL
, "Not Verifiable"
363 if (verify_code
) { /* verify code */
365 MonoTableInfo
*m
= &image
->tables
[MONO_TABLE_METHOD
];
367 for (i
= 0; i
< m
->rows
; ++i
) {
371 method
= mono_get_method_checked (image
, MONO_TOKEN_METHOD_DEF
| (i
+1), NULL
, NULL
, error
);
373 g_print ("Warning: Cannot lookup method with token 0x%08x due to %s\n", i
+ 1, mono_error_get_message (error
));
374 mono_error_cleanup (error
);
377 errors
= mono_method_verify (method
, flags
);
379 MonoClass
*klass
= mono_method_get_class (method
);
380 char *name
= mono_type_full_name (m_class_get_byval_arg (klass
));
381 if (mono_method_signature_internal (method
) == NULL
) {
382 g_print ("In method: %s::%s(ERROR)\n", name
, mono_method_get_name (method
));
385 sig
= mono_signature_get_desc (mono_method_signature_internal (method
), FALSE
);
386 g_print ("In method: %s::%s(%s)\n", name
, mono_method_get_name (method
), sig
);
392 for (tmp
= errors
; tmp
; tmp
= tmp
->next
) {
393 MonoVerifyInfo
*info
= (MonoVerifyInfo
*)tmp
->data
;
394 if (info
->status
== MONO_VERIFY_NOT_VERIFIABLE
&& valid_only
)
397 g_print ("%s: %s\n", desc
[info
->status
], info
->message
);
398 if (info
->status
== MONO_VERIFY_ERROR
) {
402 if(info
->status
== MONO_VERIFY_NOT_VERIFIABLE
) {
407 mono_free_verify_list (errors
);
412 g_print ("Error count: %d\n", count
);
419 printf ("Usage is: pedump [--verify error,warn,cls,all,code,fail-on-verifiable,non-strict,valid-only,metadata] file.exe\n");
424 verify_image_file (const char *fname
)
429 MonoTableInfo
*table
;
430 MonoAssembly
*assembly
;
431 MonoImageOpenStatus status
;
434 if (!strstr (fname
, "mscorlib.dll")) {
435 image
= mono_image_open_raw (mono_domain_default_alc (mono_get_root_domain ()), fname
, &status
);
437 printf ("Could not open %s\n", fname
);
441 if (!mono_verifier_verify_pe_data (image
, error
))
444 if (!mono_image_load_pe_data (image
)) {
445 printf ("Could not load pe data for assembly %s\n", fname
);
449 if (!mono_verifier_verify_cli_data (image
, error
))
452 if (!mono_image_load_cli_data (image
)) {
453 printf ("Could not load cli data for assembly %s\n", fname
);
457 if (!mono_verifier_verify_table_data (image
, error
))
460 mono_image_load_names (image
);
462 /*fake an assembly for class loading to work*/
463 assembly
= g_new0 (MonoAssembly
, 1);
464 assembly
->in_gac
= FALSE
;
465 assembly
->image
= image
;
466 image
->assembly
= assembly
;
467 mono_assembly_fill_assembly_name (image
, &assembly
->aname
);
469 /*Finish initializing the runtime*/
470 mono_install_assembly_load_hook_v2 (pedump_assembly_load_hook
, NULL
, FALSE
);
471 mono_install_assembly_search_hook_v2 (pedump_assembly_search_hook
, NULL
, FALSE
, FALSE
, FALSE
);
473 mono_init_version ("pedump", image
->version
);
475 mono_install_assembly_preload_hook_v2 (pedump_preload
, GUINT_TO_POINTER (FALSE
), FALSE
, FALSE
);
478 mono_marshal_init ();
480 /*Finish initializing the runtime*/
481 mono_install_assembly_load_hook_v2 (pedump_assembly_load_hook
, NULL
, FALSE
);
482 mono_install_assembly_search_hook_v2 (pedump_assembly_search_hook
, NULL
, FALSE
, FALSE
, FALSE
);
484 mono_init_version ("pedump", NULL
);
486 mono_install_assembly_preload_hook_v2 (pedump_preload
, GUINT_TO_POINTER (FALSE
), FALSE
, FALSE
);
489 mono_marshal_init ();
490 image
= mono_get_corlib ();
492 if (!mono_verifier_verify_pe_data (image
, error
))
495 if (!mono_image_load_pe_data (image
)) {
496 printf ("Could not load pe data for assembly %s\n", fname
);
500 if (!mono_verifier_verify_cli_data (image
, error
))
503 if (!mono_image_load_cli_data (image
)) {
504 printf ("Could not load cli data for assembly %s\n", fname
);
508 if (!mono_verifier_verify_table_data (image
, error
))
512 if (!verify_partial_md
&& !mono_verifier_verify_full_table_data (image
, error
))
516 table
= &image
->tables
[MONO_TABLE_TYPEDEF
];
517 for (i
= 1; i
<= table
->rows
; ++i
) {
519 guint32 token
= i
| MONO_TOKEN_TYPE_DEF
;
520 MonoClass
*klass
= mono_class_get_checked (image
, token
, error
);
522 printf ("Could not load class with token %x due to %s\n", token
, mono_error_get_message (error
));
523 mono_error_cleanup (error
);
526 mono_class_init_internal (klass
);
527 if (mono_class_has_failure (klass
)) {
528 ERROR_DECL (type_load_error
);
529 mono_error_set_for_class_failure (type_load_error
, klass
);
530 printf ("Could not initialize class(0x%08x) %s.%s due to %s\n", token
, m_class_get_name_space (klass
), m_class_get_name (klass
), mono_error_get_message (type_load_error
));
531 mono_error_cleanup (type_load_error
);
535 mono_class_setup_vtable (klass
);
536 if (mono_class_has_failure (klass
)) {
537 ERROR_DECL (type_load_error
);
538 mono_error_set_for_class_failure (type_load_error
, klass
);
539 printf ("Could not initialize vtable of class(0x%08x) %s.%s due to %s\n", token
, m_class_get_name_space (klass
), m_class_get_name (klass
), mono_error_get_message (type_load_error
));
540 mono_error_cleanup (type_load_error
);
549 if (!is_ok (error
)) {
550 g_print ("FAIL: %s\n", mono_error_get_message (error
));
551 mono_error_cleanup (error
);
555 g_print ("Error count: %d\n", count
);
560 try_load_from (MonoAssembly
**assembly
, const gchar
*path1
, const gchar
*path2
,
561 const gchar
*path3
, const gchar
*path4
,
562 const MonoAssemblyOpenRequest
*req
)
567 fullpath
= g_build_filename (path1
, path2
, path3
, path4
, NULL
);
568 if (g_file_test (fullpath
, G_FILE_TEST_IS_REGULAR
))
569 *assembly
= mono_assembly_request_open (fullpath
, req
, NULL
);
572 return (*assembly
!= NULL
);
575 static MonoAssembly
*
576 real_load (gchar
**search_path
, const gchar
*culture
, const gchar
*name
, const MonoAssemblyOpenRequest
*req
)
578 MonoAssembly
*result
= NULL
;
581 const gchar
*local_culture
;
584 if (!culture
|| *culture
== '\0') {
587 local_culture
= culture
;
590 filename
= g_strconcat (name
, ".dll", NULL
);
591 len
= strlen (filename
);
593 for (path
= search_path
; *path
; path
++) {
595 continue; /* Ignore empty ApplicationBase */
597 /* See test cases in bug #58992 and bug #57710 */
598 /* 1st try: [culture]/[name].dll (culture may be empty) */
599 strcpy (filename
+ len
- 4, ".dll");
600 if (try_load_from (&result
, *path
, local_culture
, "", filename
, req
))
603 /* 2nd try: [culture]/[name].exe (culture may be empty) */
604 strcpy (filename
+ len
- 4, ".exe");
605 if (try_load_from (&result
, *path
, local_culture
, "", filename
, req
))
608 /* 3rd try: [culture]/[name]/[name].dll (culture may be empty) */
609 strcpy (filename
+ len
- 4, ".dll");
610 if (try_load_from (&result
, *path
, local_culture
, name
, filename
, req
))
613 /* 4th try: [culture]/[name]/[name].exe (culture may be empty) */
614 strcpy (filename
+ len
- 4, ".exe");
615 if (try_load_from (&result
, *path
, local_culture
, name
, filename
, req
))
624 * Try to load referenced assemblies from assemblies_path.
626 static MonoAssembly
*
627 pedump_preload (MonoAssemblyLoadContext
*alc
,
628 MonoAssemblyName
*aname
,
629 gchar
**assemblies_path
,
634 MonoAssembly
*result
= NULL
;
635 MonoAssemblyOpenRequest req
;
636 mono_assembly_request_prepare_open (&req
, refonly
? MONO_ASMCTX_REFONLY
: MONO_ASMCTX_DEFAULT
, alc
);
638 if (assemblies_path
&& assemblies_path
[0] != NULL
) {
639 result
= real_load (assemblies_path
, aname
->culture
, aname
->name
, &req
);
642 result
= real_load (assembly_directory
, aname
->culture
, aname
->name
, &req
);
647 static GList
*loaded_assemblies
= NULL
;
650 pedump_assembly_load_hook (MonoAssemblyLoadContext
*alc
, MonoAssembly
*assembly
, gpointer user_data
, MonoError
*error
)
652 loaded_assemblies
= g_list_prepend (loaded_assemblies
, assembly
);
655 static MonoAssembly
*
656 pedump_assembly_search_hook (MonoAssemblyLoadContext
*alc
, MonoAssembly
*requesting
, MonoAssemblyName
*aname
,
657 gboolean refonly
, gboolean postload
, gpointer user_data
, MonoError
*error
)
661 for (tmp
= loaded_assemblies
; tmp
; tmp
= tmp
->next
) {
662 MonoAssembly
*ass
= (MonoAssembly
*)tmp
->data
;
663 if (mono_assembly_check_name_match (aname
, &ass
->aname
))
670 thread_state_init (MonoThreadUnwindState
*ctx
)
674 #define VALID_ONLY_FLAG 0x08000000
675 #define VERIFY_CODE_ONLY MONO_VERIFY_ALL + 1
676 #define VERIFY_METADATA_ONLY VERIFY_CODE_ONLY + 1
677 #define VERIFY_PARTIAL_METADATA VERIFY_CODE_ONLY + 2
680 main (int argc
, char *argv
[])
682 int image_result
= 0;
686 MiniVerifierMode verifier_mode
= MONO_VERIFIER_MODE_VERIFIABLE
;
687 const char *flag_desc
[] = {"error", "warn", "cls", "all", "code", "fail-on-verifiable", "non-strict", "valid-only", "metadata", "partial-md", NULL
};
688 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
, VERIFY_PARTIAL_METADATA
, 0};
689 int i
, verify_flags
= MONO_VERIFY_REPORT_ALL_ERRORS
, run_new_metadata_verifier
= 0;
690 MonoThreadInfoRuntimeCallbacks ticallbacks
;
692 for (i
= 1; i
< argc
; i
++){
693 if (argv
[i
][0] != '-'){
698 if (strcmp (argv
[i
], "--help") == 0)
700 else if (strcmp (argv
[i
], "--verify") == 0) {
713 //We have to force the runtime to load the corlib under verification as its own corlib so core types are properly populated in mono_defaults.
714 if (strstr (file
, "mscorlib.dll"))
715 g_setenv ("MONO_PATH", g_path_get_dirname (file
), 1);
716 assembly_directory
[0] = g_path_get_dirname (file
);
717 assembly_directory
[1] = NULL
;
719 #ifndef DISABLE_PERFCOUNTERS
720 mono_perfcounters_init ();
722 mono_counters_init ();
723 mono_tls_init_runtime_keys ();
724 memset (&ticallbacks
, 0, sizeof (ticallbacks
));
725 ticallbacks
.thread_state_init
= thread_state_init
;
727 mono_w32handle_init ();
729 mono_thread_info_runtime_init (&ticallbacks
);
731 mono_metadata_init ();
733 mono_assemblies_init ();
738 char *tok
= strtok (flags
, ",");
743 for (i
= 0; flag_desc
[i
]; ++i
) {
744 if (strcmp (tok
, flag_desc
[i
]) == 0) {
745 if (flag_vals
[i
] == VERIFY_CODE_ONLY
) {
748 } else if(flag_vals
[i
] == MONO_VERIFY_ALL
) {
750 } else if(flag_vals
[i
] == VERIFY_METADATA_ONLY
) {
752 run_new_metadata_verifier
= 1;
753 } else if(flag_vals
[i
] == VERIFY_PARTIAL_METADATA
) {
754 verify_partial_md
= 1;
756 if (flag_vals
[i
] == VALID_ONLY_FLAG
)
757 verifier_mode
= MONO_VERIFIER_MODE_VALID
;
759 verify_flags
|= flag_vals
[i
];
764 g_print ("Unknown verify flag %s\n", tok
);
765 tok
= strtok (NULL
, ",");
768 mono_verifier_set_mode (verifier_mode
);
772 if (verify_pe
|| run_new_metadata_verifier
) {
773 run_new_metadata_verifier
= 1;
776 if (run_new_metadata_verifier
) {
777 mono_verifier_set_mode (verifier_mode
);
779 image_result
= verify_image_file (file
);
780 if (image_result
== 1 || !verify_code
)
784 image
= mono_image_open (file
, NULL
);
786 fprintf (stderr
, "Cannot open image %s\n", file
);
791 dump_dotnet_iinfo (image
);
793 MonoAssemblyOpenRequest req
;
794 MonoAssembly
*assembly
;
796 MonoImageOpenStatus status
;
799 mono_verifier_set_mode (verifier_mode
);
801 mono_assembly_request_prepare_open (&req
, MONO_ASMCTX_DEFAULT
, mono_domain_default_alc (mono_get_root_domain ()));
802 assembly
= mono_assembly_request_open (file
, &req
, NULL
);
803 /*fake an assembly for netmodules so the verifier works*/
804 if (!assembly
&& (image
= mono_image_open (file
, &status
)) && image
->tables
[MONO_TABLE_ASSEMBLY
].rows
== 0) {
805 assembly
= g_new0 (MonoAssembly
, 1);
806 assembly
->in_gac
= FALSE
;
807 assembly
->image
= image
;
808 image
->assembly
= assembly
;
812 g_print ("Could not open assembly %s\n", file
);
816 code_result
= dump_verify_info (assembly
->image
, verify_flags
, verifier_mode
== MONO_VERIFIER_MODE_VALID
);
817 return code_result
? code_result
: image_result
;
819 mono_image_close (image
);