Thu Nov 13 16:12:09 CET 2003 Paolo Molaro <lupus@ximian.com>
[mono.git] / mono / dis / dump.c
1 /*
2  * dump.c: Dumping routines for the disassembler.
3  *
4  * Author:
5  *   Miguel de Icaza (miguel@ximian.com)
6  *
7  * (C) 2001 Ximian, Inc.
8  */
9 #include <config.h>
10 #include <stdio.h>
11 #include <string.h>
12 #include <glib.h>
13 #include "meta.h"
14 #include "util.h"
15 #include "dump.h"
16 #include "get.h"
17 #include "mono/metadata/loader.h"
18 #include "mono/metadata/class.h"
19
20 void
21 dump_table_assembly (MonoImage *m)
22 {
23         MonoTableInfo *t = &m->tables [MONO_TABLE_ASSEMBLY];
24         guint32 cols [MONO_ASSEMBLY_SIZE];
25         const char *ptr;
26         int len;
27
28         fprintf (output, "Assembly Table\n");
29
30         if (!t->rows)
31                 return;
32
33         mono_metadata_decode_row (t, 0, cols, MONO_ASSEMBLY_SIZE);
34
35         fprintf (output, "Name:          %s\n", mono_metadata_string_heap (m, cols [MONO_ASSEMBLY_NAME]));
36         fprintf (output, "Hash Algoritm: 0x%08x\n", cols [MONO_ASSEMBLY_HASH_ALG]);
37         fprintf (output, "Version:       %d.%d.%d.%d\n", cols [MONO_ASSEMBLY_MAJOR_VERSION], 
38                                         cols [MONO_ASSEMBLY_MINOR_VERSION], 
39                                         cols [MONO_ASSEMBLY_BUILD_NUMBER], 
40                                         cols [MONO_ASSEMBLY_REV_NUMBER]);
41         fprintf (output, "Flags:         0x%08x\n", cols [MONO_ASSEMBLY_FLAGS]);
42         fprintf (output, "PublicKey:     BlobPtr (0x%08x)\n", cols [MONO_ASSEMBLY_PUBLIC_KEY]);
43
44         ptr = mono_metadata_blob_heap (m, cols [MONO_ASSEMBLY_PUBLIC_KEY]);
45         len = mono_metadata_decode_value (ptr, &ptr);
46         if (len > 0){
47                 fprintf (output, "\tDump:");
48                 hex_dump (ptr, 0, len);
49                 fprintf (output, "\n");
50         } else
51                 fprintf (output, "\tZero sized public key\n");
52         
53         fprintf (output, "Culture:       %s\n", mono_metadata_string_heap (m, cols [MONO_ASSEMBLY_CULTURE]));
54         fprintf (output, "\n");
55 }
56
57 void
58 dump_table_typeref (MonoImage *m)
59 {
60         MonoTableInfo *t = &m->tables [MONO_TABLE_TYPEREF];
61         int i;
62
63         fprintf (output, "Typeref Table\n");
64         
65         for (i = 1; i <= t->rows; i++){
66                 char *s = get_typeref (m, i);
67                 
68                 fprintf (output, "%d: %s\n", i, s);
69                 g_free (s);
70         }
71         fprintf (output, "\n");
72 }
73
74 void
75 dump_table_typedef (MonoImage *m)
76 {
77         MonoTableInfo *t = &m->tables [MONO_TABLE_TYPEDEF];
78         int i;
79
80         fprintf (output, "Typedef Table\n");
81         
82         for (i = 1; i <= t->rows; i++){
83                 char *s = get_typedef (m, i);
84                 guint32 cols [MONO_TYPEDEF_SIZE];
85
86                 mono_metadata_decode_row (&m->tables [MONO_TABLE_TYPEDEF], i - 1, cols, MONO_TYPEDEF_SIZE);
87
88                 fprintf (output, "%d: %s (flist=%d, mlist=%d, flags=0x%x, extends=0x%x)\n", i, s, 
89                                         cols [MONO_TYPEDEF_FIELD_LIST], cols [MONO_TYPEDEF_METHOD_LIST],
90                                         cols [MONO_TYPEDEF_FLAGS], cols [MONO_TYPEDEF_EXTENDS]);
91                 g_free (s);
92         }
93         fprintf (output, "\n");
94 }
95
96 void
97 dump_table_assemblyref (MonoImage *m)
98 {
99         MonoTableInfo *t = &m->tables [MONO_TABLE_ASSEMBLYREF];
100         int i;
101
102         fprintf (output, "AssemblyRef Table\n");
103         
104         for (i = 0; i < t->rows; i++){
105                 const char *ptr;
106                 int len;
107                 guint32 cols [MONO_ASSEMBLYREF_SIZE];
108
109                 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
110                 fprintf (output, "%d: Version=%d.%d.%d.%d\n\tName=%s\n", i + 1,
111                          cols [MONO_ASSEMBLYREF_MAJOR_VERSION], 
112                          cols [MONO_ASSEMBLYREF_MINOR_VERSION], 
113                          cols [MONO_ASSEMBLYREF_BUILD_NUMBER], 
114                          cols [MONO_ASSEMBLYREF_REV_NUMBER],
115                          mono_metadata_string_heap (m, cols [MONO_ASSEMBLYREF_NAME]));
116                 ptr = mono_metadata_blob_heap (m, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
117                 len = mono_metadata_decode_value (ptr, &ptr);
118                 if (len > 0){
119                         fprintf (output, "\tPublic Key:");
120                         hex_dump (ptr, 0, len);
121                         fprintf (output, "\n");
122                 } else
123                         fprintf (output, "\tZero sized public key\n");
124                 
125         }
126         fprintf (output, "\n");
127 }
128
129 void
130 dump_table_param (MonoImage *m)
131 {
132         MonoTableInfo *t = &m->tables [MONO_TABLE_PARAM];
133         int i;
134
135         fprintf (output, "Param Table\n");
136         
137         for (i = 0; i < t->rows; i++){
138                 guint32 cols [MONO_PARAM_SIZE];
139
140                 mono_metadata_decode_row (t, i, cols, MONO_PARAM_SIZE);
141                 fprintf (output, "%d: 0x%04x %d %s\n",
142                          i + 1,
143                          cols [MONO_PARAM_FLAGS], cols [MONO_PARAM_SEQUENCE], 
144                          mono_metadata_string_heap (m, cols [MONO_PARAM_NAME]));
145         }
146         fprintf (output, "\n");
147 }
148
149 void
150 dump_table_field (MonoImage *m)
151 {
152         MonoTableInfo *t = &m->tables [MONO_TABLE_FIELD];
153         MonoTableInfo *td = &m->tables [MONO_TABLE_TYPEDEF];
154         MonoTableInfo *fl = &m->tables [MONO_TABLE_FIELDLAYOUT];
155         MonoTableInfo *rva = &m->tables [MONO_TABLE_FIELDRVA];
156         int i, current_type, offset_row, rva_row;
157         guint32 first_m, last_m;
158
159         fprintf (output, "Field Table (1..%d)\n", t->rows);
160         
161         rva_row = offset_row = current_type = 1;
162         last_m = first_m = 1;
163         for (i = 1; i <= t->rows; i++){
164                 guint32 cols [MONO_FIELD_SIZE];
165                 char *sig, *flags;
166
167                 /*
168                  * Find the next type.
169                  */
170                 while (current_type <= td->rows && i >= (last_m = mono_metadata_decode_row_col (td, current_type - 1, MONO_TYPEDEF_FIELD_LIST))) {
171                         current_type++;
172                 }
173                 if (i == first_m) {
174                         fprintf (output, "########## %s.%s\n",
175                                 mono_metadata_string_heap (m, mono_metadata_decode_row_col (td, current_type - 2, MONO_TYPEDEF_NAMESPACE)),
176                                 mono_metadata_string_heap (m, mono_metadata_decode_row_col (td, current_type - 2, MONO_TYPEDEF_NAME)));
177                         first_m = last_m;
178                 }
179                 mono_metadata_decode_row (t, i - 1, cols, MONO_FIELD_SIZE);
180                 sig = get_field_signature (m, cols [MONO_FIELD_SIGNATURE]);
181                 flags = field_flags (cols [MONO_FIELD_FLAGS]);
182                 fprintf (output, "%d: %s %s: %s\n",
183                          i,
184                          sig,
185                          mono_metadata_string_heap (m, cols [MONO_FIELD_NAME]),
186                          flags);
187                 g_free (sig);
188                 g_free (flags);
189                 if (offset_row <= fl->rows && (mono_metadata_decode_row_col (fl, offset_row - 1, MONO_FIELD_LAYOUT_FIELD) == i)) {
190                         fprintf (output, "\texplicit offset: %d\n", mono_metadata_decode_row_col (fl, offset_row - 1, MONO_FIELD_LAYOUT_OFFSET));
191                         offset_row ++;
192                 }
193                 if (rva_row <= rva->rows && (mono_metadata_decode_row_col (rva, rva_row - 1, MONO_FIELD_RVA_FIELD) == i)) {
194                         fprintf (output, "\trva: %d\n", mono_metadata_decode_row_col (rva, rva_row - 1, MONO_FIELD_RVA_RVA));
195                         rva_row ++;
196                 }
197         }
198         fprintf (output, "\n");
199 }
200
201 void
202 dump_table_memberref (MonoImage *m)
203 {
204         MonoTableInfo *t = &m->tables [MONO_TABLE_MEMBERREF];
205         int i, kind, idx;
206         char *x, *xx;
207         char *sig;
208         const char *blob, *ks;
209
210         fprintf (output, "MemberRef Table (1..%d)\n", t->rows);
211
212         for (i = 0; i < t->rows; i++){
213                 guint32 cols [MONO_MEMBERREF_SIZE];
214
215                 mono_metadata_decode_row (t, i, cols, MONO_MEMBERREF_SIZE);
216                 
217                 kind = cols [MONO_MEMBERREF_CLASS] & 7;
218                 idx = cols [MONO_MEMBERREF_CLASS] >> 3;
219
220                 x = g_strdup ("UNHANDLED CASE");
221                 
222                 switch (kind){
223                 case 0:
224                         ks = "TypeDef"; break;
225                 case 1:
226                         ks = "TypeRef";
227                         xx = get_typeref (m, idx);
228                         x = g_strconcat (xx, ".", mono_metadata_string_heap (m, cols [MONO_MEMBERREF_NAME]), NULL);
229                         g_free (xx);
230                         break;
231                 case 2:
232                         ks = "ModuleRef"; break;
233                 case 3:
234                         ks = "MethodDef"; break;
235                 case 4:
236                         ks = "TypeSpec";
237                         xx = get_typespec (m, idx);
238                         x = g_strconcat (xx, ".", mono_metadata_string_heap (m, cols [MONO_MEMBERREF_NAME]), NULL);
239                         g_free (xx);
240                         break;
241                 default:
242                         g_error ("Unknown tag: %d\n", kind);
243                 }
244                 blob = mono_metadata_blob_heap (m, cols [MONO_MEMBERREF_SIGNATURE]);
245                 mono_metadata_decode_blob_size (blob, &blob);
246                 if (*blob == 0x6) { /* it's a field */
247                         sig = get_field_signature (m, cols [MONO_MEMBERREF_SIGNATURE]);
248                 } else {
249                         sig = get_methodref_signature (m, cols [MONO_MEMBERREF_SIGNATURE], NULL);
250                 }
251                 fprintf (output, "%d: %s[%d] %s\n\tResolved: %s\n\tSignature: %s\n\t\n",
252                          i + 1,
253                          ks, idx,
254                          mono_metadata_string_heap (m, cols [MONO_MEMBERREF_NAME]),
255                          x ? x : "",
256                          sig);
257
258                 if (x)
259                         g_free (x);
260                 g_free (sig);
261         }
262 }
263
264 void
265 dump_table_class_layout (MonoImage *m)
266 {
267         MonoTableInfo *t = &m->tables [MONO_TABLE_CLASSLAYOUT];
268         int i;
269         fprintf (output, "ClassLayout Table (1..%d)\n", t->rows);
270
271         for (i = 0; i < t->rows; i++){
272                 guint32 cols [MONO_CLASS_LAYOUT_SIZE];
273                 
274                 mono_metadata_decode_row (t, i, cols, MONO_CLASS_LAYOUT_SIZE);
275
276                 fprintf (output, "%d: PackingSize=%d  ClassSize=%d  Parent=%s\n",
277                          i + 1, cols [MONO_CLASS_LAYOUT_PACKING_SIZE], 
278                          cols [MONO_CLASS_LAYOUT_CLASS_SIZE], 
279                          get_typedef (m, cols [MONO_CLASS_LAYOUT_PARENT]));
280         }
281 }
282
283 void
284 dump_table_constant (MonoImage *m)
285 {
286         MonoTableInfo *t = &m->tables [MONO_TABLE_CONSTANT];
287         int i;
288         const char *desc [] = {
289                 "Field",
290                 "Param",
291                 "Property",
292                 ""
293         };
294         fprintf (output, "Constant Table (1..%d)\n", t->rows);
295
296         for (i = 0; i < t->rows; i++){
297                 guint32 cols [MONO_CONSTANT_SIZE];
298                 const char *parent = desc [cols [MONO_CONSTANT_PARENT] & HASCONSTANT_MASK];
299                 
300                 mono_metadata_decode_row (t, i, cols, MONO_CONSTANT_SIZE);
301
302                 fprintf (output, "%d: Parent= %s: %d %s\n",
303                          i + 1, parent, cols [MONO_CONSTANT_PARENT] >> HASCONSTANT_BITS, 
304                          get_constant (m, (MonoTypeEnum) cols [MONO_CONSTANT_TYPE], cols [MONO_CONSTANT_VALUE]));
305         }
306         
307 }
308
309 void
310 dump_table_property_map (MonoImage *m)
311 {
312         MonoTableInfo *t = &m->tables [MONO_TABLE_PROPERTYMAP];
313         int i;
314         char *s;
315         
316         fprintf (output, "Property Map Table (1..%d)\n", t->rows);
317         
318         for (i = 0; i < t->rows; i++){
319                 guint32 cols [MONO_PROPERTY_MAP_SIZE];
320                 
321                 mono_metadata_decode_row (t, i, cols, MONO_PROPERTY_MAP_SIZE);
322                 s = get_typedef (m, cols [MONO_PROPERTY_MAP_PARENT]);
323                 fprintf (output, "%d: %s (%d) %d\n", i + 1, s, cols [MONO_PROPERTY_MAP_PARENT], cols [MONO_PROPERTY_MAP_PROPERTY_LIST]);
324                 g_free (s);
325         }
326 }
327
328 void
329 dump_table_property (MonoImage *m)
330 {
331         MonoTableInfo *t = &m->tables [MONO_TABLE_PROPERTY];
332         int i, j, pcount;
333         const char *ptr;
334         char flags[128];
335
336         fprintf (output, "Property Table (1..%d)\n", t->rows);
337
338         for (i = 0; i < t->rows; i++){
339                 guint32 cols [MONO_PROPERTY_SIZE];
340                 char *type;
341                 int bsize;
342                 int prop_flags;
343                 
344                 mono_metadata_decode_row (t, i, cols, MONO_PROPERTY_SIZE);
345                 flags [0] = 0;
346                 prop_flags = cols [MONO_PROPERTY_FLAGS];
347                 if (prop_flags & 0x0200)
348                         strcat (flags, "special ");
349                 if (prop_flags & 0x0400)
350                         strcat (flags, "runtime ");
351                 if (prop_flags & 0x1000)
352                         strcat (flags, "hasdefault ");
353
354                 ptr = mono_metadata_blob_heap (m, cols [MONO_PROPERTY_TYPE]);
355                 bsize = mono_metadata_decode_blob_size (ptr, &ptr);
356                 /* ECMA claims 0x08 ... */
357                 if (*ptr != 0x28 && *ptr != 0x08)
358                                 g_warning("incorrect signature in propert blob: 0x%x", *ptr);
359                 ptr++;
360                 pcount = mono_metadata_decode_value (ptr, &ptr);
361                 ptr = get_type (m, ptr, &type);
362                 fprintf (output, "%d: %s %s (",
363                          i + 1, type, mono_metadata_string_heap (m, cols [MONO_PROPERTY_NAME]));
364                 g_free (type);
365
366                 for (j = 0; j < pcount; j++){
367                                 ptr = get_param (m, ptr, &type);
368                                 fprintf (output, "%s%s", j > 0? ", " : "",type);
369                                 g_free (type);
370                 }
371                 fprintf (output, ") %s\n", flags);
372         }
373 }
374
375 void
376 dump_table_event (MonoImage *m)
377 {
378         MonoTableInfo *t = &m->tables [MONO_TABLE_EVENT];
379         int i;
380         fprintf (output, "Event Table (1..%d)\n", t->rows);
381
382         for (i = 0; i < t->rows; i++){
383                 guint32 cols [MONO_EVENT_SIZE];
384                 const char *name;
385                 char *type;
386                 
387                 mono_metadata_decode_row (t, i, cols, MONO_EVENT_SIZE);
388
389                 name = mono_metadata_string_heap (m, cols [MONO_EVENT_NAME]);
390                 type = get_typedef_or_ref (m, cols [MONO_EVENT_TYPE]);
391                 fprintf (output, "%d: %s %s %s\n", i + 1, type, name,
392                          cols [MONO_EVENT_FLAGS] & 0x200 ? "specialname " : "");
393                 g_free (type);
394         }
395         
396 }
397
398 void
399 dump_table_file (MonoImage *m)
400 {
401         MonoTableInfo *t = &m->tables [MONO_TABLE_FILE];
402         int i, j, len;
403         fprintf (output, "File Table (1..%d)\n", t->rows);
404
405         for (i = 0; i < t->rows; i++){
406                 guint32 cols [MONO_FILE_SIZE];
407                 const char *name, *hash;
408                 
409                 mono_metadata_decode_row (t, i, cols, MONO_FILE_SIZE);
410
411                 name = mono_metadata_string_heap (m, cols [MONO_FILE_NAME]);
412                 fprintf (output, "%d: %s %s [", i + 1, name, 
413                                 cols [MONO_FILE_FLAGS] & 0x1 ? "nometadata" : "containsmetadata");
414                 hash = mono_metadata_blob_heap (m, cols [MONO_FILE_HASH_VALUE]);
415                 len = mono_metadata_decode_blob_size (hash, &hash);
416                 for (j = 0; j < len; ++j)
417                         fprintf (output, "%s%02X", j? " ": "", hash [j] & 0xff);
418                 fprintf (output, "]\n");
419         }
420         
421 }
422
423 static char*
424 get_manifest_implementation (MonoImage *m, guint32 idx)
425 {
426         guint32 row;
427         const char* table = "";
428         if (!idx)
429                 return g_strdup ("current module");
430         row = idx >> IMPLEMENTATION_BITS;
431         switch (idx & IMPLEMENTATION_MASK) {
432         case IMPLEMENTATION_FILE:
433                 table = "file";
434                 break;
435         case IMPLEMENTATION_ASSEMBLYREF:
436                 table = "assemblyref";
437                 break;
438         case IMPLEMENTATION_EXP_TYPE:
439                 table = "exportedtype";
440                 break;
441         default:
442                 g_assert_not_reached ();
443         }
444         return g_strdup_printf ("%s %d", table, row);
445 }
446
447 static const char*
448 get_manifest_flags (guint32 mf)
449 {
450         mf &= 3;
451         switch (mf) {
452         case 1: return "public";
453         case 2: return "private";
454         default:
455                 return "";
456         }
457 }
458
459 void
460 dump_table_manifest (MonoImage *m)
461 {
462         MonoTableInfo *t = &m->tables [MONO_TABLE_MANIFESTRESOURCE];
463         int i;
464         fprintf (output, "Manifestresource Table (1..%d)\n", t->rows);
465
466         for (i = 0; i < t->rows; i++){
467                 guint32 cols [MONO_MANIFEST_SIZE];
468                 const char *name, *mf;
469                 char *impl;
470                 
471                 mono_metadata_decode_row (t, i, cols, MONO_MANIFEST_SIZE);
472
473                 name = mono_metadata_string_heap (m, cols [MONO_MANIFEST_NAME]);
474                 mf = get_manifest_flags (cols [MONO_MANIFEST_FLAGS]);
475                 impl = get_manifest_implementation (m, cols [MONO_MANIFEST_IMPLEMENTATION]);
476                 fprintf (output, "%d: %s '%s' at offset %u in %s\n", i + 1, mf, name, cols [MONO_MANIFEST_OFFSET], impl);
477                 g_free (impl);
478         }
479         
480 }
481
482 void
483 dump_table_moduleref (MonoImage *m)
484 {
485         MonoTableInfo *t = &m->tables [MONO_TABLE_MODULEREF];
486         int i;
487         fprintf (output, "ModuleRef Table (1..%d)\n", t->rows);
488
489         for (i = 0; i < t->rows; i++){
490                 guint32 cols [MONO_MODULEREF_SIZE];
491                 const char *name;
492                 
493                 mono_metadata_decode_row (t, i, cols, MONO_MODULEREF_SIZE);
494
495                 name = mono_metadata_string_heap (m, cols [MONO_MODULEREF_NAME]);
496                 fprintf (output, "%d: %s\n", i + 1, name);
497         }
498         
499 }
500
501 void
502 dump_table_module (MonoImage *m)
503 {
504         MonoTableInfo *t = &m->tables [MONO_TABLE_MODULE];
505         int i;
506         fprintf (output, "ModuleRef Table (1..%d)\n", t->rows);
507
508         for (i = 0; i < t->rows; i++){
509                 guint32 cols [MONO_MODULE_SIZE];
510                 const char *name;
511                 char *guid;
512                 
513                 mono_metadata_decode_row (t, i, cols, MONO_MODULE_SIZE);
514
515                 name = mono_metadata_string_heap (m, cols [MONO_MODULE_NAME]);
516                 guid = get_guid (m, cols [MONO_MODULE_MVID]);
517                 fprintf (output, "%d: %s %d %s\n", i + 1, name, cols [MONO_MODULE_MVID], guid);
518         }       
519 }
520
521 void
522 dump_table_method (MonoImage *m)
523 {
524         MonoTableInfo *t = &m->tables [MONO_TABLE_METHOD];
525         MonoTableInfo *td = &m->tables [MONO_TABLE_TYPEDEF];
526         int i, current_type;
527         guint32 first_m, last_m;
528         fprintf (output, "Method Table (1..%d)\n", t->rows);
529
530         current_type = 1;
531         last_m = first_m = 1;
532         for (i = 1; i <= t->rows; i++){
533                 guint32 cols [MONO_METHOD_SIZE];
534                 char *sig;
535                 const char *sigblob;
536                 MonoMethodSignature *method;
537
538                 /*
539                  * Find the next type.
540                  */
541                 while (current_type <= td->rows && i >= (last_m = mono_metadata_decode_row_col (td, current_type - 1, MONO_TYPEDEF_METHOD_LIST))) {
542                         current_type++;
543                 }
544                 if (i == first_m) {
545                         fprintf (output, "########## %s.%s\n",
546                                 mono_metadata_string_heap (m, mono_metadata_decode_row_col (td, current_type - 2, MONO_TYPEDEF_NAMESPACE)),
547                                 mono_metadata_string_heap (m, mono_metadata_decode_row_col (td, current_type - 2, MONO_TYPEDEF_NAME)));
548                         first_m = last_m;
549                 }
550                 mono_metadata_decode_row (t, i - 1, cols, MONO_METHOD_SIZE);
551                 sigblob = mono_metadata_blob_heap (m, cols [MONO_METHOD_SIGNATURE]);
552                 mono_metadata_decode_blob_size (sigblob, &sigblob);
553                 method = mono_metadata_parse_method_signature (m, i, sigblob, &sigblob);
554                 sig = dis_stringify_method_signature (m, method, i, FALSE);
555                 fprintf (output, "%d: %s (param: %d)\n", i, sig, cols [MONO_METHOD_PARAMLIST]);
556                 g_free (sig);
557                 mono_metadata_free_method_signature (method);
558         }
559         
560 }
561
562 static guint32
563 method_dor_to_token (guint32 idx) {
564         switch (idx & METHODDEFORREF_MASK) {
565         case METHODDEFORREF_METHODDEF:
566                 return MONO_TOKEN_METHOD_DEF | (idx >> METHODDEFORREF_BITS);
567         case METHODDEFORREF_METHODREF:
568                 return MONO_TOKEN_MEMBER_REF | (idx >> METHODDEFORREF_BITS);
569         }
570         return -1;
571 }
572
573 void
574 dump_table_methodimpl (MonoImage *m)
575 {
576         MonoTableInfo *t = &m->tables [MONO_TABLE_METHODIMPL];
577         /*MonoTableInfo *td = &m->tables [MONO_TABLE_TYPEDEF];*/
578         int i;
579
580         fprintf (output, "MethodImpl Table (1..%d)\n", t->rows);
581
582         for (i = 1; i <= t->rows; i++){
583                 guint32 cols [MONO_METHODIMPL_SIZE];
584                 char *class, *impl, *decl;
585
586                 mono_metadata_decode_row (t, i - 1, cols, MONO_METHODIMPL_SIZE);
587                 class = get_typedef (m, cols [MONO_METHODIMPL_CLASS]);
588                 impl = get_method (m, method_dor_to_token (cols [MONO_METHODIMPL_BODY]));
589                 decl = get_method (m, method_dor_to_token (cols [MONO_METHODIMPL_DECLARATION]));
590                 fprintf (output, "%d: %s\n\tdecl: %s\n\timpl: %s\n", i, class, decl, impl);
591                 g_free (class);
592                 g_free (impl);
593                 g_free (decl);
594         }
595         
596 }
597
598 static map_t semantics_map [] = {
599                 {1, "setter"},
600                 {2, "getter"},
601                 {4, "other"},
602                 {8, "add-on"},
603                 {0x10, "remove-on"},
604                 {0x20, "fire"},
605                 {0, NULL},
606 };
607
608 void
609 dump_table_methodsem (MonoImage *m)
610 {
611         MonoTableInfo *t = &m->tables [MONO_TABLE_METHODSEMANTICS];
612         int i, is_property, index;
613         const char *semantics;
614         
615         fprintf (output, "Method Semantics Table (1..%d)\n", t->rows);
616         for (i = 1; i <= t->rows; i++){
617                 guint32 cols [MONO_METHOD_SEMA_SIZE];
618                 
619                 mono_metadata_decode_row (t, i - 1, cols, MONO_METHOD_SEMA_SIZE);
620                 semantics = flags (cols [MONO_METHOD_SEMA_SEMANTICS], semantics_map);
621                 is_property = cols [MONO_METHOD_SEMA_ASSOCIATION] & HAS_SEMANTICS_MASK;
622                 index = cols [MONO_METHOD_SEMA_ASSOCIATION] >> HAS_SEMANTICS_BITS;
623                 fprintf (output, "%d: [%d] %s method: %d %s %d\n", i, cols [MONO_METHOD_SEMA_ASSOCIATION], semantics,
624                                                 cols [MONO_METHOD_SEMA_METHOD] - 1, 
625                                                 is_property? "property" : "event",
626                                                 index);
627         }
628 }
629
630 void 
631 dump_table_interfaceimpl (MonoImage *m)
632 {
633         MonoTableInfo *t = &m->tables [MONO_TABLE_INTERFACEIMPL];
634         int i;
635
636         fprintf (output, "Interface Implementation Table (1..%d)\n", t->rows);
637         for (i = 1; i <= t->rows; i++) {
638                 guint32 cols [MONO_INTERFACEIMPL_SIZE];
639                 
640                 mono_metadata_decode_row (t, i - 1, cols, MONO_INTERFACEIMPL_SIZE);
641                 fprintf (output, "%d: %s implements %s\n", i,
642                         get_typedef (m, cols [MONO_INTERFACEIMPL_CLASS]),
643                         get_typedef_or_ref (m, cols [MONO_INTERFACEIMPL_INTERFACE]));
644         }
645 }
646
647 static char*
648 has_cattr_get_table (MonoImage *m, guint32 val)
649 {
650         guint32 t = val & CUSTOM_ATTR_MASK;
651         guint32 index = val >> CUSTOM_ATTR_BITS;
652         const char *table;
653
654         switch (t) {
655         case CUSTOM_ATTR_METHODDEF:
656                 table = "MethodDef";
657                 break;
658         case CUSTOM_ATTR_FIELDDEF:
659                 table = "FieldDef";
660                 break;
661         case CUSTOM_ATTR_TYPEREF:
662                 table = "TypeRef";
663                 break;
664         case CUSTOM_ATTR_TYPEDEF:
665                 table = "TypeDef";
666                 break;
667         case CUSTOM_ATTR_PARAMDEF:
668                 table = "Param";
669                 break;
670         case CUSTOM_ATTR_INTERFACE:
671                 table = "InterfaceImpl";
672                 break;
673         case CUSTOM_ATTR_MEMBERREF:
674                 table = "MemberRef";
675                 break;
676         case CUSTOM_ATTR_MODULE:
677                 table = "Module";
678                 break;
679         case CUSTOM_ATTR_PERMISSION:
680                 table = "DeclSecurity?";
681                 break;
682         case CUSTOM_ATTR_PROPERTY:
683                 table = "Property";
684                 break;
685         case CUSTOM_ATTR_EVENT:
686                 table = "Event";
687                 break;
688         case CUSTOM_ATTR_SIGNATURE:
689                 table = "StandAloneSignature";
690                 break;
691         case CUSTOM_ATTR_MODULEREF:
692                 table = "ModuleRef";
693                 break;
694         case CUSTOM_ATTR_TYPESPEC:
695                 table = "TypeSpec";
696                 break;
697         case CUSTOM_ATTR_ASSEMBLY:
698                 table = "Assembly";
699                 break;
700         case CUSTOM_ATTR_ASSEMBLYREF:
701                 table = "AssemblyRef";
702                 break;
703         case CUSTOM_ATTR_FILE:
704                 table = "File";
705                 break;
706         case CUSTOM_ATTR_EXP_TYPE:
707                 table = "ExportedType";
708                 break;
709         case CUSTOM_ATTR_MANIFEST:
710                 table = "Manifest";
711                 break;
712         default:
713                 table = "Unknown";
714                 break;
715         }
716         /*
717          * FIXME: we should decode the index into something more uman-friendly.
718          */
719         return g_strdup_printf ("%s: %d", table, index);
720 }
721
722 static char*
723 custom_attr_params (MonoImage *m, MonoMethodSignature* sig, const char* value)
724 {
725         int len, i, slen, type;
726         GString *res;
727         char *s;
728         const char *p = value;
729
730         len = mono_metadata_decode_value (p, &p);
731         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
732                 return g_strdup ("");
733
734         /* skip prolog */
735         p += 2;
736         res = g_string_new ("");
737         for (i = 0; i < sig->param_count; ++i) {
738                 if (i != 0)
739                         g_string_append (res, ", ");
740                 type = sig->params [i]->type;
741 handle_enum:
742                 switch (type) {
743                 case MONO_TYPE_U1:
744                         g_string_sprintfa (res, "%d", (unsigned int)*p);
745                         ++p;
746                         break;
747                 case MONO_TYPE_I1:
748                         g_string_sprintfa (res, "%d", *p);
749                         ++p;
750                         break;
751                 case MONO_TYPE_BOOLEAN:
752                         g_string_sprintfa (res, "%s", *p?"true":"false");
753                         ++p;
754                         break;
755                 case MONO_TYPE_CHAR:
756                         g_string_sprintfa (res, "'%c'", read16 (p));
757                         p += 2;
758                         break;
759                 case MONO_TYPE_U2:
760                         g_string_sprintfa (res, "%d", read16 (p));
761                         p += 2;
762                         break;
763                 case MONO_TYPE_I2:
764                         g_string_sprintfa (res, "%d", (gint16)read16 (p));
765                         p += 2;
766                         break;
767                 case MONO_TYPE_U4:
768                         g_string_sprintfa (res, "%d", read32 (p));
769                         p += 4;
770                         break;
771                 case MONO_TYPE_I4:
772                         g_string_sprintfa (res, "%d", (gint32)read32 (p));
773                         p += 4;
774                         break;
775                 case MONO_TYPE_U8:
776                         g_string_sprintfa (res, "%lld", read64 (p));
777                         p += 8;
778                         break;
779                 case MONO_TYPE_I8:
780                         g_string_sprintfa (res, "%lld", (gint64)read64 (p));
781                         p += 8;
782                         break;
783                 case MONO_TYPE_R4: {
784                         float val;
785                         readr4 (p, &val);
786                         g_string_sprintfa (res, "%g", val);
787                         p += 4;
788                         break;
789                 }
790                 case MONO_TYPE_R8: {
791                         double val;
792                         readr8 (p, &val);
793                         g_string_sprintfa (res, "%g", val);
794                         p += 8;
795                         break;
796                 }
797                 case MONO_TYPE_VALUETYPE:
798                         if (sig->params [i]->data.klass->enumtype) {
799                                 type = sig->params [i]->data.klass->enum_basetype->type;
800                                 goto handle_enum;
801                         } else {
802                                 g_warning ("generic valutype not handled in custom attr value decoding");
803                         }
804                         break;
805                 case MONO_TYPE_CLASS: /* It must be a Type: check? */
806                 case MONO_TYPE_STRING:
807                         if (*p == (char)0xff) {
808                                 g_string_append (res, "null");
809                                 p++;
810                                 break;
811                         }
812                         slen = mono_metadata_decode_value (p, &p);
813                         g_string_append_c (res, '"');
814                         g_string_append (res, p);
815                         g_string_append_c (res, '"');
816                         p += slen;
817                         break;
818                 default:
819                         g_warning ("Type %02x not handled in custom attr value decoding", sig->params [i]->type);
820                         break;
821                 }
822         }
823         slen = read16 (p);
824         if (slen) {
825                 g_string_sprintfa (res, " %d named args: (", slen);
826                 slen = len - (p - value) + 1;
827                 for (i = 0; i < slen; ++i) {
828                         g_string_sprintfa (res, " %02X", (p [i] & 0xff));
829                 }
830                 g_string_append_c (res, ')');
831         }
832         s = res->str;
833         g_string_free (res, FALSE);
834         return s;
835 }
836
837 void
838 dump_table_customattr (MonoImage *m)
839 {
840         MonoTableInfo *t = &m->tables [MONO_TABLE_CUSTOMATTRIBUTE];
841         int i;
842
843         fprintf (output, "Custom Attributes Table (1..%d)\n", t->rows);
844         for (i = 1; i <= t->rows; i++) {
845                 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
846                 guint32 mtoken;
847                 char * desc;
848                 char *method;
849                 char *params;
850                 MonoMethod *meth;
851                 
852                 mono_metadata_decode_row (t, i - 1, cols, MONO_CUSTOM_ATTR_SIZE);
853                 desc = has_cattr_get_table (m, cols [MONO_CUSTOM_ATTR_PARENT]);
854                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> CUSTOM_ATTR_TYPE_BITS;
855                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & CUSTOM_ATTR_TYPE_MASK) {
856                 case CUSTOM_ATTR_TYPE_METHODDEF:
857                         mtoken |= MONO_TOKEN_METHOD_DEF;
858                         break;
859                 case CUSTOM_ATTR_TYPE_MEMBERREF:
860                         mtoken |= MONO_TOKEN_MEMBER_REF;
861                         break;
862                 default:
863                         g_warning ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
864                         break;
865                 }
866                 method = get_method (m, mtoken);
867                 meth = mono_get_method (m, mtoken, NULL);
868                 params = custom_attr_params (m, meth->signature, mono_metadata_blob_heap (m, cols [MONO_CUSTOM_ATTR_VALUE]));
869                 fprintf (output, "%d: %s: %s [%s]\n", i, desc, method, params);
870                 g_free (desc);
871                 g_free (method);
872                 g_free (params);
873         }
874 }
875
876 void
877 dump_table_nestedclass (MonoImage *m)
878 {
879         MonoTableInfo *t = &m->tables [MONO_TABLE_NESTEDCLASS];
880         guint32 cols [MONO_NESTED_CLASS_SIZE];
881         int i;
882         char *nested, *nesting;
883         fprintf (output, "NestedClass Table (1..%d)\n", t->rows);
884
885         for (i = 1; i <= t->rows; i++){
886                 mono_metadata_decode_row (t, i - 1, cols, MONO_NESTED_CLASS_SIZE);
887                 nested = get_typedef (m, cols [MONO_NESTED_CLASS_NESTED]);
888                 nesting = get_typedef (m, cols [MONO_NESTED_CLASS_ENCLOSING]);
889                 fprintf (output, "%d: %d %d: %s in %s\n", i,
890                                 cols [MONO_NESTED_CLASS_NESTED], 
891                                 cols [MONO_NESTED_CLASS_ENCLOSING], nested, nesting);
892                 g_free (nested);
893                 g_free (nesting);
894         }
895         
896 }
897
898 void
899 dump_table_exported (MonoImage *m)
900 {
901         MonoTableInfo *t = &m->tables [MONO_TABLE_EXPORTEDTYPE];
902         guint32 cols [MONO_EXP_TYPE_SIZE];
903         int i;
904         const char *name, *nspace;
905         char *impl;
906         fprintf (output, "ExportedType Table (1..%d)\n", t->rows);
907
908         for (i = 1; i <= t->rows; i++) {
909                 mono_metadata_decode_row (t, i - 1, cols, MONO_EXP_TYPE_SIZE);
910                 name = mono_metadata_string_heap (m, cols [MONO_EXP_TYPE_NAME]);
911                 nspace = mono_metadata_string_heap (m, cols [MONO_EXP_TYPE_NAMESPACE]);
912                 impl = get_manifest_implementation (m, cols [MONO_EXP_TYPE_IMPLEMENTATION]);
913                 fprintf (output, "%d: %s.%s is in %s\n", i, nspace, name, impl);
914                 g_free (impl);
915         }
916         
917 }
918
919 void
920 dump_table_field_marshal (MonoImage *m)
921 {
922         MonoTableInfo *t = &m->tables [MONO_TABLE_FIELDMARSHAL];
923         guint32 cols [MONO_FIELD_MARSHAL_SIZE];
924         int i, is_field, idx;
925         const char *blob;
926         char *native;
927         
928         fprintf (output, "FieldMarshal Table (1..%d)\n", t->rows);
929
930         for (i = 1; i <= t->rows; i++) {
931                 mono_metadata_decode_row (t, i - 1, cols, MONO_FIELD_MARSHAL_SIZE);
932                 blob = mono_metadata_blob_heap (m, cols [MONO_FIELD_MARSHAL_NATIVE_TYPE]);
933                 native = get_marshal_info (m, blob);
934                 is_field = (cols [MONO_FIELD_MARSHAL_PARENT] & HAS_FIELD_MARSHAL_MASK) == HAS_FIELD_MARSHAL_FIELDSREF;
935                 idx = cols [MONO_FIELD_MARSHAL_PARENT] >> HAS_FIELD_MARSHAL_BITS;
936                 fprintf (output, "%d: (0x%04x) %s %d: %s\n", i, cols [MONO_FIELD_MARSHAL_PARENT], is_field? "Field" : "Param", idx, native);
937                 g_free (native);
938         }
939         
940 }
941
942 static const char*
943 get_security_action (int val) {
944         static char buf [32];
945
946         switch (val) {
947         case SECURITY_ACTION_DEMAND:
948                 return "Demand";
949         case SECURITY_ACTION_ASSERT:
950                 return "Assert";
951         case SECURITY_ACTION_DENY:
952                 return "Deny";
953         case SECURITY_ACTION_PERMITONLY:
954                 return "PermitOnly";
955         case SECURITY_ACTION_LINKDEMAND:
956                 return "LinkDemand";
957         case SECURITY_ACTION_INHERITDEMAND:
958                 return "InheritanceDemand";
959         case SECURITY_ACTION_REQMIN:
960                 return "RequestMinimum";
961         case SECURITY_ACTION_REQOPT:
962                 return "RequestOptional";
963         case SECURITY_ACTION_REQREFUSE:
964                 return "RequestRefuse";
965         default:
966                 g_snprintf (buf, sizeof (buf), "0x%04X", val);
967                 return buf;
968         }
969 }
970
971 void 
972 dump_table_declsec (MonoImage *m)
973 {
974         MonoTableInfo *t = &m->tables [MONO_TABLE_DECLSECURITY];
975         guint32 cols [MONO_DECL_SECURITY_SIZE];
976         int i, len;
977         guint32 idx;
978         const char *blob, *action;
979         const char* parent[] = {
980                 "TypeDef", "MethodDef", "Assembly", ""
981         };
982         
983         fprintf (output, "DeclSecurity Table (1..%d)\n", t->rows);
984
985         for (i = 1; i <= t->rows; i++) {
986                 mono_metadata_decode_row (t, i - 1, cols, MONO_DECL_SECURITY_SIZE);
987                 blob = mono_metadata_blob_heap (m, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
988                 len = mono_metadata_decode_blob_size (blob, &blob);
989                 action = get_security_action (cols [MONO_DECL_SECURITY_ACTION]);
990                 idx = cols [MONO_DECL_SECURITY_PARENT];
991                 fprintf (output, "%d: %s on %s %d%s", i, action, parent [idx & HAS_DECL_SECURITY_MASK], idx >> HAS_DECL_SECURITY_BITS, len? ":\n\t":"\n");
992                 if (!len)
993                         continue;
994                 for (idx = 0; idx < len; ++idx)
995                         fprintf (output, "%c", blob [idx]);
996                 fprintf (output, "\n");
997         }
998 }
999
1000 void 
1001 dump_table_genericpar (MonoImage *m)
1002 {
1003         MonoTableInfo *t = &m->tables [MONO_TABLE_GENERICPARAM];
1004         guint32 cols [MONO_GENERICPARAM_SIZE];
1005         int i;
1006
1007         fprintf (output, "GenericParameters (1..%d)\n", t->rows);
1008         
1009         for (i = 1; i <= t->rows; i++) {
1010                 char *sig;
1011                 mono_metadata_decode_row (t, i - 1, cols, MONO_GENERICPARAM_SIZE);
1012
1013                 sig = get_type_or_methdef (m, cols [MONO_GENERICPARAM_OWNER]);
1014                 fprintf (output, "%d: %d, flags=%d, owner=%s %s\n", i,
1015                          cols [MONO_GENERICPARAM_NUMBER],
1016                          cols [MONO_GENERICPARAM_FLAGS], sig,
1017                          mono_metadata_string_heap (m, cols [MONO_GENERICPARAM_NAME]));
1018                 g_free (sig);
1019         }
1020 }
1021
1022 void
1023 dump_table_methodspec (MonoImage *m)
1024 {
1025         MonoTableInfo *t = &m->tables [MONO_TABLE_METHODSPEC];
1026         guint32 cols [MONO_METHODSPEC_SIZE];
1027         int i;
1028         
1029         fprintf (output, "MethodSpec (1..%d)\n", t->rows);
1030
1031         for (i = 1; i <= t->rows; i++) {
1032                 char *sig;
1033                 char *method;
1034                 guint32 token;
1035                 
1036                 mono_metadata_decode_row (t, i - 1, cols, MONO_METHODSPEC_SIZE);
1037
1038                 // build a methodspec token to get the method
1039                 token = MONO_TOKEN_METHOD_SPEC | i;
1040                 method = get_method (m, token);
1041                 
1042                 sig = get_method_type_param (m, cols [MONO_METHODSPEC_SIGNATURE]);
1043                 fprintf (output, "%d: %s, %s\n", i, method, sig);
1044                 g_free (sig);
1045                 g_free (method);
1046         }
1047 }
1048
1049 void
1050 dump_table_parconstraint (MonoImage *m)
1051 {
1052         MonoTableInfo *t = &m->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
1053         guint32 cols [MONO_GENPARCONSTRAINT_SIZE];
1054         int i;
1055         
1056         fprintf (output, "Generic Param Constraint (1..%d)\n", t->rows);
1057
1058         for (i = 1; i <= t->rows; i++) {
1059                 char *sig;
1060                 mono_metadata_decode_row (t, i - 1, cols, MONO_GENPARCONSTRAINT_SIZE);
1061
1062                 sig = get_typedef_or_ref (m, cols [MONO_GENPARCONSTRAINT_CONSTRAINT]);
1063                 fprintf (output, "%d: gen-par=%d, Constraint=%s\n", i,
1064                          cols [MONO_GENPARCONSTRAINT_GENERICPAR], sig);
1065                 g_free (sig);
1066         }
1067 }
1068