Ooops, fix my last commit.
[mono.git] / mono / dis / get.c
1 /*
2  * get.c: Functions to get stringified values from the metadata tables.
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 <stdlib.h>
12 #include <string.h>
13 #include <ctype.h>
14 #include <glib.h>
15 #include "meta.h"
16 #include "util.h"
17 #include "get.h"
18 #include <mono/metadata/class.h>
19 #include <mono/metadata/marshal.h>
20
21 extern gboolean substitute_with_mscorlib_p;
22
23 static MonoGenericContext *
24 get_memberref_context (MonoImage *m, guint32 mrp_token, MonoGenericContext *context);
25
26 static char *
27 get_memberref_parent (MonoImage *m, guint32 mrp_token, MonoGenericContext *context);
28
29 GHashTable *key_table = NULL;
30 gboolean show_method_tokens = FALSE;
31 gboolean show_tokens = FALSE;
32
33 char *
34 get_typedef (MonoImage *m, int idx)
35 {
36         guint32 cols [MONO_TYPEDEF_SIZE];
37         const char *ns;
38         char *tstring, *result;
39         guint32 token;
40         
41         mono_metadata_decode_row (&m->tables [MONO_TABLE_TYPEDEF], idx - 1, cols, MONO_TYPEDEF_SIZE);
42
43         ns = mono_metadata_string_heap (m, cols [MONO_TYPEDEF_NAMESPACE]);
44
45         /* Check if this is a nested type */
46         token = MONO_TOKEN_TYPE_DEF | (idx);
47         token = mono_metadata_nested_in_typedef (m, token);
48         tstring = show_tokens ? g_strdup_printf ("/*%08x*/", token) : NULL;
49         if (token) {
50                 char *outer;
51                 
52                 outer = get_typedef (m, mono_metadata_token_index (token));
53                 result = g_strdup_printf (
54                         "%s%s%s/%s%s", ns, *ns?".":"", outer,
55                         mono_metadata_string_heap (m, cols [MONO_TYPEDEF_NAME]),
56                         tstring ? tstring : "");
57                 g_free (outer);
58                 g_free (tstring);
59                 return result;
60         }
61         
62         
63         result = g_strdup_printf (
64                 "%s%s%s%s", ns, *ns?".":"",
65                 mono_metadata_string_heap (m, cols [MONO_TYPEDEF_NAME]),
66                 tstring ? tstring : "");
67         g_free (tstring);
68
69         return result;
70 }
71
72 char *
73 get_module (MonoImage *m, int idx)
74 {
75         guint32 cols [MONO_MODULE_SIZE];
76         
77         /*
78          * There MUST BE only one module in the Module table
79          */
80         g_assert (idx == 1);
81             
82         mono_metadata_decode_row (&m->tables [MONO_TABLE_MODULE], idx - 1, cols, MONO_MODULE_SIZE);
83
84         return g_strdup (mono_metadata_string_heap (m, cols [MONO_MODULE_NAME]));
85 }
86
87 char *
88 get_moduleref (MonoImage *m, int idx)
89 {
90         guint32 cols [MONO_MODULEREF_SIZE];
91         
92         mono_metadata_decode_row (&m->tables [MONO_TABLE_MODULEREF], idx - 1, cols, MONO_MODULEREF_SIZE);
93
94         return g_strdup (mono_metadata_string_heap (m, cols [MONO_MODULEREF_NAME]));
95 }
96
97 char *
98 get_assemblyref (MonoImage *m, int idx)
99 {
100         guint32 cols [MONO_ASSEMBLYREF_SIZE];
101         
102         mono_metadata_decode_row (&m->tables [MONO_TABLE_ASSEMBLYREF], idx - 1, cols, MONO_ASSEMBLYREF_SIZE);
103
104         return g_strdup (mono_metadata_string_heap (m, cols [MONO_ASSEMBLYREF_NAME]));
105 }
106
107 /*
108  *
109  * Returns a string representing the ArrayShape (22.2.16).
110  */
111 static const char *
112 get_array_shape (MonoImage *m, const char *ptr, char **result)
113 {
114         GString *res = g_string_new ("[");
115         guint32 rank, num_sizes, num_lo_bounds;
116         guint32 *sizes = NULL, *lo_bounds = NULL;
117         int i, r;
118         char buffer [80];
119         
120         rank = mono_metadata_decode_value (ptr, &ptr);
121         num_sizes = mono_metadata_decode_value (ptr, &ptr);
122
123         if (num_sizes > 0)
124                 sizes = g_new (guint32, num_sizes);
125         
126         for (i = 0; i < num_sizes; i++)
127                 sizes [i] = mono_metadata_decode_value (ptr, &ptr);
128
129         num_lo_bounds = mono_metadata_decode_value (ptr, &ptr);
130         if (num_lo_bounds > 0)
131                 lo_bounds = g_new (guint32, num_lo_bounds);
132         
133         for (i = 0; i < num_lo_bounds; i++)
134                 lo_bounds [i] = mono_metadata_decode_value (ptr, &ptr);
135
136         for (r = 0; r < rank; r++){
137                 if (r < num_sizes){
138                         if (r < num_lo_bounds){
139                                 sprintf (buffer, "%d..%d", lo_bounds [r], lo_bounds [r] + sizes [r] - 1);
140                         } else {
141                                 sprintf (buffer, "0..%d", sizes [r] - 1);
142                         }
143                 } else
144                         buffer [0] = 0;
145                 
146                 g_string_append (res, buffer);
147                 if ((r + 1) != rank)
148                         g_string_append (res, ", ");
149         }
150         g_string_append (res, "]");
151         
152         if (sizes)
153                 g_free (sizes);
154
155         if (lo_bounds)
156                 g_free (lo_bounds);
157
158         *result = res->str;
159         g_string_free (res, FALSE);
160
161         return ptr;
162 }
163
164 /**
165  * get_typespec:
166  * @m: metadata context
167  * @blob_idx: index into the blob heap
168  *
169  * Returns the stringified representation of a TypeSpec signature (22.2.17)
170  */
171 char *
172 get_typespec (MonoImage *m, guint32 idx, MonoGenericContext *context)
173 {
174         guint32 cols [MONO_TYPESPEC_SIZE];
175         const char *ptr;
176         char *s, *result;
177         GString *res = g_string_new ("");
178         int len;
179
180         MonoType *type;
181
182         type = mono_type_create_from_typespec_full (m, context, idx);
183
184         mono_metadata_decode_row (&m->tables [MONO_TABLE_TYPESPEC], idx-1, cols, MONO_TYPESPEC_SIZE);
185         ptr = mono_metadata_blob_heap (m, cols [MONO_TYPESPEC_SIGNATURE]);
186         len = mono_metadata_decode_value (ptr, &ptr);
187         
188         switch (*ptr++){
189         case MONO_TYPE_PTR:
190                 ptr = get_custom_mod (m, ptr, &s);
191                 if (s){
192                         g_string_append (res, s);
193                         g_string_append_c (res, ' ');
194                         g_free (s);
195                 }
196                 
197                 if (*ptr == MONO_TYPE_VOID)
198                         g_string_append (res, "void");
199                 else {
200                         ptr = get_type (m, ptr, &s, context);
201                         if (s)
202                                 g_string_append (res, s);
203                 }
204                 g_string_append (res, "*");
205                 break;
206                 
207         case MONO_TYPE_FNPTR:
208                 s = dis_stringify_function_ptr (m, type->data.method);
209                 g_string_append (res, "method ");
210                 g_string_append (res, s);
211                 g_free (s);
212                 break;
213                         
214         case MONO_TYPE_ARRAY:
215                 ptr = get_type (m, ptr, &s, context);
216                 g_string_append (res, s);
217                 g_free (s);
218                 g_string_append_c (res, ' ');
219                 ptr = get_array_shape (m, ptr, &s);
220                 g_string_append (res, s);
221                 g_free (s);
222                 break;
223                 
224         case MONO_TYPE_SZARRAY:
225                 ptr = get_custom_mod (m, ptr, &s);
226                 if (s){
227                         g_string_append (res, s);
228                         g_string_append_c (res, ' ');
229                         g_free (s);
230                 }
231                 ptr = get_type (m, ptr, &s, context);
232                 g_string_append (res, s);
233                 g_string_append (res, "[]");
234                 g_free (s);
235                 break;
236
237         case MONO_TYPE_VAR:
238         case MONO_TYPE_MVAR:
239                 ptr = get_type (m, ptr-1, &s, context);
240                 g_string_append (res, s);
241                 g_free (s);
242                 break;
243                 
244         default:
245                 s = dis_stringify_type (m, type, FALSE);
246                 g_string_append (res, s);
247                 g_free (s);
248                 break;
249         }
250
251         if (show_tokens) {
252                 int token = mono_metadata_make_token (MONO_TABLE_TYPESPEC, idx);
253                 result = g_strdup_printf ("%s/*%08x*/", res->str, token);
254         } else
255                 result = res->str;
256
257         g_string_free (res, FALSE);
258
259         return result;
260 }
261
262 char *
263 get_typeref (MonoImage *m, int idx)
264 {
265         guint32 cols [MONO_TYPEREF_SIZE];
266         const char *s, *t;
267         char *x, *ret;
268         guint32 rs_idx, table;
269         
270         mono_metadata_decode_row (&m->tables [MONO_TABLE_TYPEREF], idx - 1, cols, MONO_TYPEREF_SIZE);
271
272         t = mono_metadata_string_heap (m, cols [MONO_TYPEREF_NAME]);
273         s = mono_metadata_string_heap (m, cols [MONO_TYPEREF_NAMESPACE]);
274
275         rs_idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLTION_SCOPE_BITS;
276         table = cols [MONO_TYPEREF_SCOPE] & MONO_RESOLTION_SCOPE_MASK;
277         
278         switch (table){
279         case MONO_RESOLTION_SCOPE_MODULE: /* Module */
280                 x = get_module (m, rs_idx);
281                 ret = g_strdup_printf ("[%s] %s%s%s", x, s, *s?".":"", t);
282                 g_free (x);
283                 break;
284
285         case MONO_RESOLTION_SCOPE_MODULEREF: /* ModuleRef */
286                 x = get_moduleref (m, rs_idx);
287                 ret = g_strdup_printf ("[.module %s]%s%s%s", x, s, *s ? "." : "", t);
288                 break;
289                               
290         case MONO_RESOLTION_SCOPE_ASSEMBLYREF: /*
291                  * AssemblyRef (ECMA docs claim it is 3, but it looks to
292                  * me like it is 2 (tokens are prefixed with 0x23)
293                  */
294                 x = get_assemblyref (m, rs_idx);
295                 ret = g_strdup_printf ("[%s]%s%s%s", x, s, *s?".":"", t);
296                 g_free (x);
297                 break;
298                 
299         case MONO_RESOLTION_SCOPE_TYPEREF: /* TypeRef */
300                 x = get_typeref (m, rs_idx);
301                 ret =  g_strdup_printf ("%s/%s", x, t);
302                 g_free (x);
303                 break;
304                 
305         default:
306                 ret = g_strdup_printf ("Unknown table in TypeRef %d", table);
307         }
308
309         if (show_tokens) {
310                 int token = mono_metadata_make_token (MONO_TABLE_TYPEREF, idx);
311                 char *temp = g_strdup_printf ("%s/*%08x*/", ret, token);
312                 g_free (ret);
313                 ret = temp;
314         }
315
316         return ret;
317 }
318
319 /**
320  * get_typedef_or_ref:
321  * @m: metadata context
322  * @dor_token: def or ref encoded index
323  *
324  * Low two bits contain table to lookup from
325  * high bits contain the index into the def or ref table
326  *
327  * Returns: a stringified version of the MethodDef or MethodRef
328  * at (dor_token >> 2) 
329  */
330 char *
331 get_typedef_or_ref (MonoImage *m, guint32 dor_token, MonoGenericContext *context)
332 {
333         char *temp = NULL, *s = NULL;
334         int table, idx;
335
336         /*
337          * low 2 bits contain encoding
338          */
339         table = dor_token & MONO_TYPEDEFORREF_MASK;
340         idx = dor_token >> MONO_TYPEDEFORREF_BITS;
341         
342         switch (table){
343         case 0: /* TypeDef */
344                 temp = get_typedef (m, idx);
345                 s = g_strdup_printf ("%s", temp);
346                 break;
347                 
348         case 1: /* TypeRef */
349                 temp = get_typeref (m, idx);
350                 s = g_strdup_printf ("%s", temp);
351                 break;
352                 
353         case 2: /* TypeSpec */
354                 s = get_typespec (m, idx, context);
355                 break;
356
357         default:
358                 g_error ("Unhandled encoding for typedef-or-ref coded index 0x%08x", dor_token);
359
360         }
361         
362         if (temp)
363                 g_free (temp);
364
365         return s;
366 }
367
368 /**
369  * get_type_or_methdef
370  * @m: metadata context
371  * @dor_token: type or method def encoded index
372  *
373  * Low bit contains the table to lookup from
374  * high bits contain the index into the type def or method def table
375  *
376  * Returns: a stringified version of the TypeOrMethodDef token
377  */
378 char *
379 get_type_or_methdef (MonoImage *m, guint32 dor_token)
380 {
381         if (dor_token & MONO_TYPEORMETHOD_METHOD) /* MethodDef */
382                 return get_methoddef (m, dor_token >> MONO_TYPEORMETHOD_BITS);
383         else  /* TypeDef */
384                 return get_typedef (m, dor_token >> MONO_TYPEORMETHOD_BITS);
385 }
386
387 /** 
388  * get_encoded_typedef_or_ref:
389  * @m: metadata context 
390  * @ptr: location to decode from.
391  * @result: pointer to string where resulting decoded string is stored
392  *
393  * result will point to a g_malloc()ed string.
394  *
395  * Returns: the new ptr to continue decoding
396  */
397 const char *
398 get_encoded_typedef_or_ref (MonoImage *m, const char *ptr, char **result)
399 {
400         guint32 token;
401         
402         token = mono_metadata_decode_value (ptr, &ptr);
403
404         *result = get_typedef_or_ref (m, token, NULL);
405
406         return ptr;
407 }
408
409 /**
410  * get_custom_mod:
411  *
412  * Decodes a CustomMod (22.2.7)
413  *
414  * Returns: updated pointer location
415  */
416 const char *
417 get_custom_mod (MonoImage *m, const char *ptr, char **return_value)
418 {
419         char *s;
420         const char *reqd;
421         
422         *return_value = NULL;
423         while ((*ptr == MONO_TYPE_CMOD_OPT) ||
424                    (*ptr == MONO_TYPE_CMOD_REQD)) {
425                 reqd = (*ptr == MONO_TYPE_CMOD_REQD) ? "reqd" : "opt";
426                 ptr++;
427                 ptr = get_encoded_typedef_or_ref (m, ptr, &s);
428
429                 if (*return_value == NULL)
430                         *return_value = g_strconcat (reqd, " ", s, NULL);
431                 else
432                         *return_value = g_strconcat (*return_value, " ", reqd, " ", s, NULL);
433                 g_free (s);
434         }
435         return ptr;
436 }
437
438
439 static dis_map_t element_type_map [] = {
440         { MONO_TYPE_END        , "end" },
441         { MONO_TYPE_VOID       , "void" },
442         { MONO_TYPE_BOOLEAN    , "bool" },
443         { MONO_TYPE_CHAR       , "char" }, 
444         { MONO_TYPE_I1         , "int8" },
445         { MONO_TYPE_U1         , "unsigned int8" }, 
446         { MONO_TYPE_I2         , "int16" },
447         { MONO_TYPE_U2         , "unsigned int16" },
448         { MONO_TYPE_I4         , "int32" },
449         { MONO_TYPE_U4         , "unsigned int32" },
450         { MONO_TYPE_I8         , "int64" },
451         { MONO_TYPE_U8         , "unsigned int64" },
452         { MONO_TYPE_R4         , "float32" },
453         { MONO_TYPE_R8         , "float64" },
454         { MONO_TYPE_STRING     , "string" },
455         { MONO_TYPE_TYPEDBYREF , "TypedByRef" },
456         { MONO_TYPE_I          , "native int" },
457         { MONO_TYPE_U          , "native unsigned int" },
458         { MONO_TYPE_OBJECT     , "object" },
459         { 0, NULL }
460 };
461
462 static dis_map_t call_conv_type_map [] = {
463         { MONO_CALL_DEFAULT     , "default" },
464         { MONO_CALL_C           , "unmanaged cdecl" },
465         { MONO_CALL_STDCALL     , "unmanaged stdcall" },
466         { MONO_CALL_THISCALL    , "unmanaged thiscall" },
467         { MONO_CALL_FASTCALL    , "unmanaged fastcall" },
468         { MONO_CALL_VARARG      , "vararg" },
469         { 0, NULL }
470 };
471
472 char*
473 dis_stringify_token (MonoImage *m, guint32 token)
474 {
475         guint idx = token & 0xffffff;
476         switch (token >> 24) {
477         case MONO_TABLE_TYPEDEF: return get_typedef (m, idx);
478         case MONO_TABLE_TYPEREF: return get_typeref (m, idx);
479         case MONO_TABLE_TYPESPEC: return get_typespec (m, idx, NULL);
480         default:
481                  break;
482         }
483         return g_strdup_printf("0x%08x", token);
484 }
485
486 char*
487 dis_stringify_array (MonoImage *m, MonoArrayType *array, gboolean is_def)
488 {
489         char *type;
490         GString *s = g_string_new("");
491         int i;
492         
493         type = dis_stringify_type (m, &array->eklass->byval_arg, is_def);
494         g_string_append (s, type);
495         g_free (type);
496         g_string_append_c (s, '[');
497         for (i = 0; i < array->rank; ++i) {
498                 if (i)
499                         g_string_append_c (s, ',');
500                 if (i < array->numsizes) {
501                         if (i < array->numlobounds && array->lobounds[i] != 0)
502                                 g_string_sprintfa (s, "%d..%d", array->lobounds[i], array->sizes[i]);
503                         else
504                                 g_string_sprintfa (s, "%d", array->sizes[i]);
505                 }
506         }
507         g_string_append_c (s, ']');
508         type = s->str;
509         g_string_free (s, FALSE);
510         return type;
511 }
512
513 char*
514 dis_stringify_modifiers (MonoImage *m, int n, MonoCustomMod *mod)
515 {
516         GString *s = g_string_new("");
517         char *result;
518         int i;
519         for (i = 0; i < n; ++i) {
520                 char *tok = dis_stringify_token (m, mod[i].token);
521                 if (i > 0)
522                         g_string_sprintfa (s, " ");
523                 g_string_sprintfa (s, "%s (%s)", mod[i].required ? "modreq": "modopt", tok);
524                 g_free (tok);
525         }
526         g_string_append_c (s, ' ');
527         result = s->str;
528         g_string_free (s, FALSE);
529         return result;
530 }
531
532 char*
533 dis_stringify_param (MonoImage *m, MonoType *param) 
534 {
535         char *t;
536         char *result;
537         char *attribs;
538         const char *out = param->attrs & PARAM_ATTRIBUTE_OUT ? "[out]": "";
539         const char *opt = param->attrs & PARAM_ATTRIBUTE_OPTIONAL ? "[opt]": "";
540         attribs = g_strconcat(out, opt, NULL);
541         t = dis_stringify_type (m, param, TRUE);
542         result = g_strjoin(attribs[0] ? " ":"", attribs, t, NULL);
543         g_free (t);
544         g_free (attribs);
545         return result;
546 }
547
548 /**
549  * get_generic_param
550  * @m: metadata context 
551  * @table_type: The type of table we are getting generics for (0 for typedef, 1 for method)
552  * @row: The row in the table
553  *
554  * Returns: Allocated stringified generic parameters
555  */
556 char*
557 get_generic_param (MonoImage *m, MonoGenericContainer *container)
558 {
559         GString *result;
560         char *retval;
561         int i;
562
563         if (!container)
564                 return NULL;
565
566         result = g_string_new ("");
567
568         g_string_append_c (result, '<');
569         for (i = 0; i < container->type_argc; i++) {
570                 MonoGenericParam *param = &container->type_params [i];
571                 MonoClass **constr;
572                 int first = 1;
573                 guint16 flags;
574                 char *esname;
575
576                 if (i > 0)
577                         g_string_append (result, ",");
578
579                 flags = param->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
580                 if (flags == GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT)
581                         g_string_append (result, "class ");
582                 else if (flags == GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT)
583                         g_string_append (result, "valuetype ");
584                 else if (flags == GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT)
585                         g_string_append (result, ".ctor ");
586
587                 for (constr = param->constraints; constr && *constr; constr++) {
588                         char *sig;
589
590                         if (first) {
591                                 g_string_append_c (result, '(');
592                                 first = 0;
593                         } else
594                                 g_string_append (result, ", ");
595                         sig = dis_stringify_object_with_class (m, *constr, TRUE, TRUE);
596                         g_string_append (result, sig);
597                         g_free (sig);
598                 }
599
600                 if (!first)
601                         g_string_append (result, ") ");
602
603                 esname = get_escaped_name (param->name);
604                 g_string_append (result, esname);
605                 g_free (esname);
606         }
607
608         g_string_append_c (result, '>');
609
610         retval = result->str;
611         g_string_free (result, FALSE);
612         return retval;
613 }
614
615 char*
616 dis_stringify_method_signature (MonoImage *m, MonoMethodSignature *method, int methoddef_row,
617                                 MonoGenericContext *context, gboolean fully_qualified)
618 {
619         guint32 cols [MONO_METHOD_SIZE];
620         guint32 pcols [MONO_PARAM_SIZE];
621         guint32 param_index = 0;
622         const char *name = "";
623         int free_method = 0;
624         char *retval, *esname;
625         char *type = NULL;
626         char *gen_param = NULL;
627         GString *result = g_string_new ("");
628         MonoGenericContainer *container = NULL;
629         int i;
630         
631         g_assert (method || methoddef_row);
632
633         if (methoddef_row) {
634                 mono_metadata_decode_row (&m->tables [MONO_TABLE_METHOD], methoddef_row -1, cols, MONO_METHOD_SIZE);
635                 if (fully_qualified)
636                         type = get_typedef (m, mono_metadata_typedef_from_method (m, methoddef_row));
637                 name = mono_metadata_string_heap (m, cols [MONO_METHOD_NAME]);
638                 param_index = cols [MONO_METHOD_PARAMLIST];
639                 if (!method) {
640                         const char *sig = mono_metadata_blob_heap (m, cols [MONO_METHOD_SIGNATURE]);
641
642                         container = mono_metadata_load_generic_params (
643                                 m, MONO_TOKEN_METHOD_DEF | methoddef_row, context ? context->container : NULL);
644                         if (container)
645                                 context = (MonoGenericContext *) container;
646
647                         mono_metadata_decode_blob_size (sig, &sig);
648                         method = mono_metadata_parse_method_signature_full (m, context, methoddef_row, sig, &sig);
649                         free_method = 1;
650                 } else if (context)
651                         container = context->container;
652
653                 if (container && container->is_method)
654                         gen_param = get_generic_param (m, container);
655         }
656         
657         retval = dis_stringify_param (m, method->ret);
658         if (method->hasthis)
659                 g_string_append (result, "instance ");
660         g_string_append (result, map (method->call_convention, call_conv_type_map));
661         g_string_sprintfa (result, " %s ", retval);
662         if (type) {
663                 char *estype = get_escaped_name (type);
664                 g_string_sprintfa (result, "%s::", estype);
665                 g_free (estype);
666         }
667         esname = get_escaped_name (name);
668         g_string_append (result, esname);
669         g_free (esname);
670         if (gen_param) {
671                 g_string_append (result, gen_param);
672                 g_free (gen_param);
673         }
674         g_string_append (result, " (");
675         g_free (retval);
676         for (i = 0; i < method->param_count; ++i) {
677                 if (param_index && param_index <= m->tables [MONO_TABLE_PARAM].rows) {
678                         mono_metadata_decode_row (&m->tables [MONO_TABLE_PARAM], param_index - 1, pcols, MONO_PARAM_SIZE);
679                         name = mono_metadata_string_heap (m, pcols [MONO_PARAM_NAME]);
680                         method->params [i]->attrs = pcols [MONO_PARAM_FLAGS];
681                         param_index++;
682                 } else {
683                         name = "";
684                 }
685                 if (i)
686                         g_string_append (result, ", ");
687                 retval = dis_stringify_param (m, method->params [i]);
688                 esname = get_escaped_name (name);
689                 g_string_append_printf (result, "%s %s", retval, esname);
690                 g_free (retval);
691                 g_free (esname);
692         }
693         g_string_append (result, ") ");
694
695         if (show_method_tokens && methoddef_row)
696                 g_string_append_printf (result, " /* 0x%X */ ",
697                                 (methoddef_row >> MONO_TYPEORMETHOD_BITS) | MONO_TOKEN_METHOD_DEF);
698
699         if (free_method)
700                 mono_metadata_free_method_signature (method);
701         retval = result->str;
702         g_string_free (result, FALSE);
703
704         return retval;
705 }
706
707 char*
708 dis_stringify_function_ptr (MonoImage *m, MonoMethodSignature *method)
709 {
710         char *retval;
711         GString *result = g_string_new ("");
712         int i;
713         
714         g_assert (method);
715
716         g_string_append (result, map (method->call_convention, call_conv_type_map));
717
718         retval = dis_stringify_param (m, method->ret);
719         g_string_sprintfa (result, " %s ", retval);
720         g_free (retval);
721
722         g_string_append (result, " *(");
723         for (i = 0; i < method->param_count; ++i) {
724                 if (i)
725                         g_string_append (result, ", ");
726                 retval = dis_stringify_param (m, method->params [i]);
727                 g_string_append (result, retval);
728                 g_free (retval);
729         }
730         g_string_append (result, ") ");
731
732         retval = result->str;
733         g_string_free (result, FALSE);
734
735         return retval;
736 }
737
738 static char *
739 get_escaped_class_name (MonoClass *c)
740 {
741         char *result, *esname;
742
743         esname = get_escaped_name (c->name);
744
745         if (c->nested_in){
746                 char *part_a = get_escaped_class_name (c->nested_in);
747
748                 result = g_strdup_printf ("%s/%s", part_a, esname);
749                 g_free (part_a);
750         } else if (*c->name_space)
751                 result = g_strdup_printf ("%s.%s", c->name_space, esname);
752         else
753                 result = g_strdup (esname);
754
755         g_free (esname);
756         return result;
757 }
758
759 char *
760 dis_stringify_object_with_class (MonoImage *m, MonoClass *c, gboolean prefix, gboolean is_def)
761 {
762         /* FIXME: handle MONO_TYPE_OBJECT ... */
763         const char *otype = c->byval_arg.type == MONO_TYPE_VALUETYPE ? "valuetype " : "class " ;
764         char *assemblyref = NULL, *result, *esname, *generic = NULL;
765         
766         if (m != c->image) {
767                 if (c->image->assembly_name) {
768                         /* we cheat */
769                         if (substitute_with_mscorlib_p && !strcmp ("corlib", c->image->assembly_name))
770                                 assemblyref = g_strdup_printf ("[%s]", "mscorlib");
771                         else {
772                                 char *esc = get_escaped_name (c->image->assembly->aname.name);
773                                 
774                                 assemblyref = g_strdup_printf ("[%s]", esc);
775                                 g_free (esc);
776                         }
777                 } else {
778                         assemblyref = g_strdup_printf ("[.module %s]", c->image->module_name);
779                 }
780         }
781
782         esname = get_escaped_class_name (c);
783
784         if (c->generic_class) {
785                 MonoGenericClass *gclass = c->generic_class;
786                 GString *str = g_string_new ("");
787                 int i;
788
789                 for (i = 0; i < gclass->inst->type_argc; i++){
790                         char *t = dis_stringify_type (m, gclass->inst->type_argv [i], is_def);
791
792                         g_string_append (str, t);
793                         if (i+1 != gclass->inst->type_argc)
794                                 g_string_append (str, ", ");
795                         g_free (t);
796                 }
797                 generic = g_strdup_printf ("<%s>", str->str);
798                 g_string_free (str, TRUE);
799         }
800
801
802         result = g_strdup_printf ("%s%s%s%s", prefix ? otype : "", assemblyref?assemblyref:"",
803                                   esname, generic?generic:"");
804         
805         g_free (generic);
806         g_free (assemblyref);
807         g_free (esname);
808         
809         return result;
810 }
811
812 static char *
813 dis_stringify_object (MonoImage *m, MonoType *type, gboolean is_def)
814 {
815         MonoClass *c = mono_class_from_mono_type (type);
816         return dis_stringify_object_with_class (m, c, TRUE, is_def);
817 }
818
819 char*
820 dis_stringify_type (MonoImage *m, MonoType *type, gboolean is_def)
821 {
822         const char *pinned = "", *byref = "";
823         char *bare = NULL, *mods = NULL;
824         char *result;
825
826         if (type->num_mods)
827                 mods = dis_stringify_modifiers (m, type->num_mods, type->modifiers);
828
829         switch (type->type){
830         case MONO_TYPE_BOOLEAN:
831         case MONO_TYPE_CHAR:
832         case MONO_TYPE_I1:
833         case MONO_TYPE_U1:
834         case MONO_TYPE_I2:
835         case MONO_TYPE_U2:
836         case MONO_TYPE_I4:
837         case MONO_TYPE_U4:
838         case MONO_TYPE_I8:
839         case MONO_TYPE_U8:
840         case MONO_TYPE_R4:
841         case MONO_TYPE_R8:
842         case MONO_TYPE_I:
843         case MONO_TYPE_U:
844         case MONO_TYPE_STRING:
845         case MONO_TYPE_OBJECT:
846         case MONO_TYPE_TYPEDBYREF:
847                 bare = g_strdup (map (type->type, element_type_map));
848                 break;
849                 
850         case MONO_TYPE_VALUETYPE:
851         case MONO_TYPE_CLASS:
852                 bare = dis_stringify_object (m, type, is_def);
853                 break;
854         case MONO_TYPE_FNPTR: {
855                 char *child_type;
856                 child_type = dis_stringify_function_ptr (m, type->data.method);
857                 bare = g_strdup_printf ("method %s", child_type);
858                 g_free (child_type);
859                 break;
860         }
861         case MONO_TYPE_PTR: {
862                 char *child_type;
863                 child_type = dis_stringify_type (m, type->data.type, is_def);
864                 
865                 bare = g_strdup_printf ("%s*", child_type);
866                 g_free (child_type);
867                 break;
868         }
869         case MONO_TYPE_SZARRAY: {
870                 char *child_type;
871                 child_type = dis_stringify_type (m, &type->data.klass->byval_arg, is_def);
872                 
873                 bare = g_strdup_printf ("%s[]", child_type);
874                 g_free (child_type);
875                 break;
876         }
877         case MONO_TYPE_ARRAY:
878                 bare = dis_stringify_array (m, type->data.array, is_def);
879                 break;
880         case MONO_TYPE_VOID:
881                 bare = g_strdup ("void");
882                 break;
883         case MONO_TYPE_MVAR:
884                 if (is_def) {
885                         g_assert (type->data.generic_param->name);
886                         bare = g_strdup_printf ("!!%s", type->data.generic_param->name);
887                 } else
888                         bare = g_strdup_printf ("!!%d", type->data.generic_param->num);
889                 break;
890         case MONO_TYPE_VAR:
891                 if (is_def) {
892                         g_assert (type->data.generic_param->name);
893                         bare = g_strdup_printf ("!%s", type->data.generic_param->name);
894                 } else
895                         bare = g_strdup_printf ("!%d", type->data.generic_param->num);
896                 break;
897         case MONO_TYPE_GENERICINST: {
898                 GString *str = g_string_new ("");
899                 int i;
900                 char *generic_type = dis_stringify_type (m, type->data.generic_class->generic_type, is_def);
901
902                 for (i = 0; i < type->data.generic_class->inst->type_argc; i++){
903                         char *t = dis_stringify_type (m, type->data.generic_class->inst->type_argv [i], is_def);
904
905                         g_string_append (str, t);
906                         if (i+1 != type->data.generic_class->inst->type_argc)
907                                 g_string_append (str, ", ");
908                         g_free (t);
909                 }
910                 bare = g_strdup_printf ("%s<%s>", generic_type, str->str);
911                 g_string_free (str, TRUE);
912                 break;
913         }
914                 
915         default:
916                 g_error ("Do not know how to stringify type 0x%x", type->type);
917         }
918         
919         if (type->pinned)
920                 pinned = " pinned";
921
922         if (type->byref)
923                 byref = "&";
924                 
925         result = g_strconcat (mods ? mods : "", bare, byref, pinned, NULL);
926
927         g_free (bare);
928
929         return result;
930 }
931
932 /**
933  * get_type:
934  * @m: metadata context 
935  * @ptr: location to decode from.
936  * @result: pointer to string where resulting decoded string is stored
937  *
938  * This routine returs in @result the stringified type pointed by @ptr.
939  * (22.2.12)
940  *
941  * Returns: the new ptr to continue decoding
942  */
943 const char *
944 get_type (MonoImage *m, const char *ptr, char **result, MonoGenericContext *context)
945 {
946         const char *start = ptr;
947         guint32 type;
948         MonoType *t;
949
950         if (*ptr == MONO_TYPE_BYREF)
951                 ++ptr;
952
953         type = mono_metadata_decode_value (ptr, &ptr);
954
955         switch (type){
956         case MONO_TYPE_VALUETYPE:
957         case MONO_TYPE_CLASS: {
958                 guint32 token = mono_metadata_parse_typedef_or_ref (m, ptr, &ptr);
959                 MonoClass *klass = mono_class_get (m, token);
960                 char *temp = dis_stringify_object_with_class (m, klass, TRUE, FALSE);
961
962                 if (show_tokens) {
963                         *result = g_strdup_printf ("%s/*%08x*/", temp, token);
964                         g_free (temp);
965                 } else
966                         *result = temp;
967                 break;
968         }
969
970         case MONO_TYPE_GENERICINST: {
971                 GString *str = g_string_new ("");
972                 int count, i;
973                 char *temp;
974
975                 ptr = get_type (m, ptr, &temp, context);
976                 g_string_append (str, temp);
977                 g_free (temp);
978
979                 count = mono_metadata_decode_value (ptr, &ptr);
980                 g_string_append (str, "<");
981
982                 for (i = 0; i < count; i++) {
983                         if (i)
984                                 g_string_append (str, ",");
985                         ptr = get_type (m, ptr, &temp, context);
986                         g_string_append (str, temp);
987                 }
988
989                 g_string_append (str, ">");
990                 *result = str->str;
991                 g_string_free (str, FALSE);
992                 break;
993         }
994
995         default:
996                 t = mono_metadata_parse_type_full (m, context, MONO_PARSE_TYPE, 0, start, &ptr);
997                 *result = dis_stringify_type (m, t, FALSE);
998                 mono_metadata_free_type (t);
999                 break;
1000         }
1001
1002         return ptr;
1003 }
1004
1005 /**
1006  * 
1007  * Returns a stringified representation of a FieldSig (22.2.4)
1008  */
1009 char *
1010 get_field_signature (MonoImage *m, guint32 blob_signature, MonoGenericContext *context)
1011 {
1012         char *allocated_modifier_string, *allocated_type_string;
1013         const char *ptr = mono_metadata_blob_heap (m, blob_signature);
1014         const char *base;
1015         char *res;
1016         int len;
1017         
1018         len = mono_metadata_decode_value (ptr, &ptr);
1019         base = ptr;
1020         /* FIELD is 0x06 */
1021         g_assert (*ptr == 0x06);
1022 /*      hex_dump (ptr, 0, len); */
1023         ptr++; len--;
1024         
1025         ptr = get_custom_mod (m, ptr, &allocated_modifier_string);
1026         ptr = get_type (m, ptr, &allocated_type_string, context);
1027
1028         res = g_strdup_printf (
1029                 "%s %s",
1030                 allocated_modifier_string ? allocated_modifier_string : "",
1031                 allocated_type_string);
1032         
1033         if (allocated_modifier_string)
1034                 g_free (allocated_modifier_string);
1035         if (allocated_type_string)
1036                 g_free (allocated_type_string);
1037         
1038         return res;
1039 }
1040
1041 MonoTypeEnum
1042 get_field_literal_type (MonoImage *m, guint32 blob_signature)
1043 {
1044         const char *ptr = mono_metadata_blob_heap (m, blob_signature);
1045         int len;
1046         char *allocated_modifier_string;
1047         
1048         len = mono_metadata_decode_value (ptr, &ptr);
1049
1050         /* FIELD is 0x06 */
1051         g_assert (*ptr == 0x06);
1052         ptr++; len--;
1053         
1054         ptr = get_custom_mod (m, ptr, &allocated_modifier_string);
1055         if (allocated_modifier_string)
1056                 g_free (allocated_modifier_string);
1057
1058         return (MonoTypeEnum) *ptr;
1059         
1060 }
1061
1062 /**
1063  * decode_literal:
1064  * @m: metadata context
1065  * @token: token to decode
1066  *
1067  * decodes the literal indexed by @token.
1068  */
1069 char *
1070 decode_literal (MonoImage *m, guint32 token)
1071 {
1072         return g_strdup ("LITERAL_VALUE");
1073 }
1074
1075 /**
1076  * get_ret_type:
1077  * @m: metadata context 
1078  * @ptr: location to decode from.
1079  * @result: pointer to string where resulting decoded string is stored
1080  *
1081  * This routine returns in @result the stringified RetType (22.2.11)
1082  *
1083  * Returns: the new ptr to continue decoding.
1084  */
1085 const char *
1086 get_ret_type (MonoImage *m, const char *ptr, char **ret_type, MonoGenericContext *context)
1087 {
1088         GString *str = g_string_new ("");
1089         char *mod = NULL;
1090         char *allocated_type_string;
1091         
1092         ptr = get_custom_mod (m, ptr, &mod);
1093         if (mod){
1094                 g_string_append (str, mod);
1095                 g_string_append_c (str, ' ');
1096                 g_free (mod);
1097         }
1098
1099         if (*ptr == MONO_TYPE_TYPEDBYREF){
1100                 g_string_append (str, "typedbyref");
1101                 ptr++;
1102         } else if (*ptr == MONO_TYPE_VOID){
1103                  g_string_append (str, "void");
1104                  ptr++;
1105         } else {
1106                 if (*ptr == MONO_TYPE_BYREF){
1107                         g_string_append (str, "[out] ");
1108                         ptr++;
1109                 }
1110
1111                 ptr = get_type (m, ptr, &allocated_type_string, context);
1112                 g_string_append (str, allocated_type_string);
1113                 g_free (allocated_type_string);
1114         }
1115
1116         *ret_type = str->str;
1117         g_string_free (str, FALSE);
1118
1119         return ptr;
1120 }
1121
1122 /**
1123  * get_param:
1124  * @m: metadata context 
1125  * @ptr: location to decode from.
1126  * @result: pointer to string where resulting decoded string is stored
1127  *
1128  * This routine returns in @result the stringified Param (22.2.10)
1129  *
1130  * Returns: the new ptr to continue decoding.
1131  */
1132 const char *
1133 get_param (MonoImage *m, const char *ptr, char **retval, MonoGenericContext *context)
1134 {
1135         GString *str = g_string_new ("");
1136         char *allocated_mod_string, *allocated_type_string;
1137         
1138         ptr = get_custom_mod (m, ptr, &allocated_mod_string);
1139         if (allocated_mod_string){
1140                 g_string_append (str, allocated_mod_string);
1141                 g_string_append_c (str, ' ');
1142                 g_free (allocated_mod_string);
1143         }
1144         
1145         if (*ptr == MONO_TYPE_TYPEDBYREF){
1146                 g_string_append (str, " typedbyref ");
1147                 ptr++;
1148         } else {
1149                 gboolean by_ref = 0;
1150                 if (*ptr == MONO_TYPE_BYREF){
1151                         g_string_append (str, "[out] ");
1152                         ptr++;
1153                         by_ref = 1;
1154                 }
1155                 ptr = get_type (m, ptr, &allocated_type_string, context);
1156                 g_string_append (str, allocated_type_string);
1157                 if (by_ref)
1158                         g_string_append_c (str, '&');
1159                 g_free (allocated_type_string);
1160         }
1161
1162         *retval = str->str;
1163         g_string_free (str, FALSE);
1164         return ptr;
1165 }
1166
1167 /**
1168  * get_escaped_name
1169  *
1170  * Returns: An allocated escaped name. A name needs to be escaped
1171  * because it might be an ilasm keyword.
1172  */
1173 char*
1174 get_escaped_name (const char *name)
1175 {
1176         const char *s;
1177
1178         g_assert (key_table);
1179
1180         if (strlen (name) == 0)
1181                 return g_strdup (name);
1182
1183         for (s = name; *s; s++) {
1184                 if (isalnum (*s) || *s == '_' || *s == '$' || *s == '@' || *s == '?' || *s == '.' || *s == 0)
1185                         continue;
1186
1187                 return g_strdup_printf ("'%s'", name);
1188         }
1189         
1190         if (g_hash_table_lookup (key_table, name))
1191                 return g_strdup_printf ("'%s'", name);
1192                         
1193         return g_strdup (name);
1194 }
1195
1196 static dis_map_t param_map [] = {
1197         { PARAM_ATTRIBUTE_IN,                "[in] " },
1198         { PARAM_ATTRIBUTE_OUT,               "[out] " },
1199         { PARAM_ATTRIBUTE_OPTIONAL,          "optional " },
1200         { PARAM_ATTRIBUTE_HAS_DEFAULT,       "hasdefault " },
1201         { PARAM_ATTRIBUTE_HAS_FIELD_MARSHAL, "fieldmarshal " },
1202         { 0, NULL }
1203 };
1204
1205 char *
1206 param_flags (guint32 f)
1207 {
1208         return g_strdup (flags (f, param_map));
1209 }
1210
1211 static dis_map_t field_access_map [] = {
1212         { FIELD_ATTRIBUTE_COMPILER_CONTROLLED, "privatescope " },
1213         { FIELD_ATTRIBUTE_PRIVATE,             "private " },
1214         { FIELD_ATTRIBUTE_FAM_AND_ASSEM,       "famandassem " },
1215         { FIELD_ATTRIBUTE_ASSEMBLY,            "assembly " },
1216         { FIELD_ATTRIBUTE_FAMILY,              "family " },
1217         { FIELD_ATTRIBUTE_FAM_OR_ASSEM,        "famorassem " },
1218         { FIELD_ATTRIBUTE_PUBLIC,              "public " },
1219         { 0, NULL }
1220 };
1221
1222 static dis_map_t field_flags_map [] = {
1223         { FIELD_ATTRIBUTE_STATIC,              "static " },
1224         { FIELD_ATTRIBUTE_INIT_ONLY,           "initonly " },
1225         { FIELD_ATTRIBUTE_LITERAL,             "literal " },
1226         { FIELD_ATTRIBUTE_NOT_SERIALIZED,      "notserialized " },
1227         { FIELD_ATTRIBUTE_SPECIAL_NAME,        "specialname " },
1228         { FIELD_ATTRIBUTE_PINVOKE_IMPL,        "FIXME:pinvokeimpl " },
1229         { FIELD_ATTRIBUTE_RT_SPECIAL_NAME,        "rtspecialname " },
1230         { FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL,        "hasfieldmarshal " },
1231         { 0, NULL }
1232 };
1233
1234 /**
1235  * field_flags:
1236  *
1237  * Returns a stringified version of a Field's flags
1238  */
1239 char *
1240 field_flags (guint32 f)
1241 {
1242         char buffer [1024];
1243         int access = f & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK;
1244         
1245         buffer [0] = 0;
1246
1247         strcat (buffer, map (access, field_access_map));
1248         strcat (buffer, flags (f, field_flags_map));
1249         return g_strdup (buffer);
1250 }
1251
1252 /**
1253  * Returns a stringifed representation of a MethodRefSig (22.2.2)
1254  */
1255 char *
1256 get_methodref_signature (MonoImage *m, guint32 blob_signature, const char *fancy_name,
1257                          MonoGenericContext *context)
1258 {
1259         GString *res = g_string_new ("");
1260         const char *ptr = mono_metadata_blob_heap (m, blob_signature);
1261         char *allocated_ret_type, *s;
1262         const char *cconv_str;
1263         gboolean seen_vararg = 0;
1264         int param_count, signature_len;
1265         int i, gen_count = 0;
1266         int cconv;
1267
1268         signature_len = mono_metadata_decode_value (ptr, &ptr);
1269
1270         if (*ptr & 0x20){
1271                 if (*ptr & 0x40)
1272                         g_string_append (res, "explicit-this ");
1273                 else
1274                         g_string_append (res, "instance "); /* has-this */
1275         }
1276
1277         if (*ptr & 0x10)
1278                 gen_count = 1;
1279         cconv = *ptr & 0x0f;
1280         cconv_str = map (cconv, call_conv_type_map);
1281         if (strcmp (cconv_str, "default") != 0) {
1282                 g_string_append (res, cconv_str);
1283                 g_string_append (res, " ");
1284         }
1285
1286         ptr++;
1287         if (gen_count)
1288                 gen_count = mono_metadata_decode_value (ptr, &ptr);
1289         param_count = mono_metadata_decode_value (ptr, &ptr);
1290         if (cconv != 0xa) {
1291                 ptr = get_ret_type (m, ptr, &allocated_ret_type, context);
1292                 g_string_append (res, allocated_ret_type);
1293                 g_free (allocated_ret_type);
1294         }
1295
1296         if (fancy_name){
1297                 g_string_append_c (res, ' ');
1298                 g_string_append (res, fancy_name);
1299         }
1300         
1301         g_string_append (res, "(");
1302
1303         /*
1304          * param_count describes parameters *before* and *after*
1305          * the vararg sentinel
1306          */
1307         for (i = 0; i < param_count; i++){
1308                 char *param = NULL;
1309                 
1310                 /*
1311                  * If ptr is a SENTINEL
1312                  */
1313                 if (*ptr == 0x41){
1314                         if (!seen_vararg){
1315                                 g_string_append (res, "..., ");
1316                                 seen_vararg = 1;
1317                         }
1318
1319                         ptr++;
1320                 }
1321
1322                 ptr = get_param (m, ptr, &param, context);
1323                 g_string_append (res, param);
1324                 if (i+1 != param_count)
1325                         g_string_append (res, ", ");
1326                 g_free (param);
1327         }
1328         g_string_append (res, ")");
1329         
1330         /*
1331          * cleanup and return
1332          */
1333         s = res->str;
1334         g_string_free (res, FALSE);
1335         return s;
1336 }
1337
1338 /**
1339  * Returns a stringifed representation of a field ref
1340  */
1341 char *
1342 get_fieldref_signature (MonoImage *m, int idx, MonoGenericContext *context)
1343 {
1344         guint32 cols [MONO_MEMBERREF_SIZE];
1345         MonoGenericContext *new_context;
1346         char *type, *esname;
1347         char *sig;
1348         char *full_sig;
1349
1350         mono_metadata_decode_row (&m->tables [MONO_TABLE_MEMBERREF],
1351                                   idx - 1, cols, MONO_MEMBERREF_SIZE);
1352
1353         new_context = get_memberref_context (m, cols [MONO_MEMBERREF_CLASS], context);
1354         sig = get_field_signature (m, cols [MONO_MEMBERREF_SIGNATURE], new_context);
1355
1356         type = get_memberref_parent (m, cols [MONO_MEMBERREF_CLASS], context);
1357         esname = get_escaped_name (mono_metadata_string_heap (m, cols [MONO_MEMBERREF_NAME]));
1358
1359         full_sig = g_strdup_printf ("%s %s::%s", sig, type, esname);
1360         g_free (sig);
1361         g_free (type);
1362         g_free (esname);
1363         
1364         return full_sig;
1365 }
1366
1367 /**
1368  * get_field:
1369  * @m: metadata context
1370  * @token: a FIELD_DEF token
1371  *
1372  * This routine has to locate the TypeDef that "owns" this Field.
1373  * Since there is no backpointer in the Field table, we have to scan
1374  * the TypeDef table and locate the actual "owner" of the field
1375  */
1376 char *
1377 get_field (MonoImage *m, guint32 token, MonoGenericContext *context)
1378 {
1379         int idx = mono_metadata_token_index (token);
1380         guint32 cols [MONO_FIELD_SIZE];
1381         char *sig, *res, *type, *estype, *esname;
1382         guint32 type_idx;
1383
1384         /*
1385          * We can get here also with a MenberRef token (for a field
1386          * defined in another module/assembly, just like in get_method ()
1387          */
1388         if (mono_metadata_token_code (token) == MONO_TOKEN_MEMBER_REF) {
1389                 return get_fieldref_signature (m, idx, context);
1390         }
1391         g_assert (mono_metadata_token_code (token) == MONO_TOKEN_FIELD_DEF);
1392
1393         mono_metadata_decode_row (&m->tables [MONO_TABLE_FIELD], idx - 1, cols, MONO_FIELD_SIZE);
1394         sig = get_field_signature (m, cols [MONO_FIELD_SIGNATURE], context);
1395
1396         /*
1397          * To locate the actual "container" for this field, we have to scan
1398          * the TypeDef table.  LAME!
1399          */
1400         type_idx = mono_metadata_typedef_from_field (m, idx);
1401
1402         type = get_typedef (m, type_idx);
1403         estype = get_escaped_name (type);
1404         esname = get_escaped_name (mono_metadata_string_heap (m, cols [MONO_FIELD_NAME]));
1405         res = g_strdup_printf ("%s %s::%s",
1406                         sig, estype, esname);
1407
1408         g_free (type);
1409         g_free (sig);
1410         g_free (estype);
1411         g_free (esname);
1412
1413         return res;
1414 }
1415
1416 static MonoGenericContext *
1417 get_memberref_context (MonoImage *m, guint32 mrp_token, MonoGenericContext *context)
1418 {
1419         MonoClass *klass;
1420
1421         /*
1422          * mrp_index is a MemberRefParent coded index
1423          */
1424         guint32 table = mrp_token & 7;
1425         guint32 idx = mrp_token >> 3;
1426
1427         switch (table){
1428         case 0: /* TypeDef */
1429                 return (MonoGenericContext *) mono_metadata_load_generic_params (
1430                         m, MONO_TOKEN_TYPE_DEF | idx, NULL);
1431                 
1432         case 1: /* TypeRef */
1433                 return NULL;
1434                 
1435         case 4: /* TypeSpec */
1436                 klass = mono_class_get_full (m, MONO_TOKEN_TYPE_SPEC | idx, context);
1437                 g_assert (klass);
1438                 return klass->generic_class ? klass->generic_class->context : NULL;
1439         }
1440         g_assert_not_reached ();
1441         return NULL;
1442 }
1443
1444 static char *
1445 get_memberref_parent (MonoImage *m, guint32 mrp_token, MonoGenericContext *context)
1446 {
1447         /*
1448          * mrp_index is a MemberRefParent coded index
1449          */
1450         guint32 table = mrp_token & 7;
1451         guint32 idx = mrp_token >> 3;
1452
1453         switch (table){
1454         case 0: /* TypeDef */
1455                 return get_typedef (m, idx);
1456                 
1457         case 1: /* TypeRef */
1458                 return get_typeref (m, idx);
1459                 
1460         case 2: /* ModuleRef */
1461                 return g_strdup_printf ("TODO:MemberRefParent-ModuleRef");
1462                 
1463         case 3: /* MethodDef */
1464                 return g_strdup ("TODO:MethodDef");
1465                 
1466         case 4: /* TypeSpec */
1467                 return get_typespec (m, idx, context);
1468         }
1469         g_assert_not_reached ();
1470         return NULL;
1471 }
1472
1473 /**
1474  * get_method:
1475  * @m: metadata context
1476  * @token: a METHOD_DEF or MEMBER_REF token
1477  *
1478  * This routine has to locate the TypeDef that "owns" this Field.
1479  * Since there is no backpointer in the Field table, we have to scan
1480  * the TypeDef table and locate the actual "owner" of the field
1481  */
1482 char *
1483 get_method_core (MonoImage *m, guint32 token, gboolean fullsig, MonoGenericContext *context)
1484 {
1485         int idx = mono_metadata_token_index (token);
1486         guint32 member_cols [MONO_MEMBERREF_SIZE], method_cols [MONO_METHOD_SIZE];
1487         char *sig = NULL, *esname;
1488         char *name;
1489
1490         MonoMethod *mh;
1491
1492         mh = mono_get_method_full (m, token, NULL, context);
1493         if (mh) {
1494                 if (mh->signature->is_inflated)
1495                         context = ((MonoMethodInflated *) mh)->context;
1496                 esname = get_escaped_name (mh->name);
1497                 sig = dis_stringify_object_with_class (m, mh->klass, TRUE, TRUE);
1498                 if (show_tokens)
1499                         name = g_strdup_printf ("%s/*%08x*/::%s", sig, token, esname);
1500                 else
1501                         name = g_strdup_printf ("%s::%s", sig, esname);
1502                 g_free (sig);
1503                 g_free (esname);
1504         } else
1505                 name = NULL;
1506
1507         switch (mono_metadata_token_code (token)){
1508         case MONO_TOKEN_METHOD_DEF:
1509                 mono_metadata_decode_row (&m->tables [MONO_TABLE_METHOD], 
1510                                           idx - 1, method_cols, MONO_METHOD_SIZE);
1511
1512                 sig = get_methodref_signature (m, method_cols [MONO_METHOD_SIGNATURE], name, context);
1513                 break;
1514                 
1515         case MONO_TOKEN_MEMBER_REF: {
1516                 mono_metadata_decode_row (&m->tables [MONO_TABLE_MEMBERREF],
1517                                           idx - 1, member_cols, MONO_MEMBERREF_SIZE);
1518                 if (!name)
1519                         name = g_strdup_printf ("%s::%s",
1520                                                 get_memberref_parent (m, member_cols [MONO_MEMBERREF_CLASS], context),
1521                                                 mono_metadata_string_heap (m, member_cols [MONO_MEMBERREF_NAME]));
1522                 sig = get_methodref_signature (
1523                         m, member_cols [MONO_MEMBERREF_SIGNATURE], name, context);
1524                 break;
1525         }
1526         case MONO_TOKEN_METHOD_SPEC: {
1527                 mono_metadata_decode_row (&m->tables [MONO_TABLE_METHODSPEC],
1528                                 idx - 1, member_cols, MONO_METHODSPEC_SIZE);
1529                 token = member_cols [MONO_METHODSPEC_METHOD];
1530                 sig = get_methodspec (m, idx, token, name, context);
1531                 break;
1532         }
1533
1534         default:
1535                 g_assert_not_reached ();
1536         }
1537
1538         if (fullsig)
1539                 g_free (name);
1540         else {
1541                 g_free (sig);
1542                 return name;
1543         }
1544         
1545         if (show_tokens) {
1546                 char *retval = g_strdup_printf ("%s /* %08x */", sig, token);
1547                 g_free (sig);
1548                 return retval;
1549         } else
1550                 return sig;
1551 }
1552
1553 char *
1554 get_method (MonoImage *m, guint32 token, MonoGenericContext *context)
1555 {
1556         return get_method_core (m, token, TRUE, context);
1557 }
1558
1559 /**
1560  * get_methoddef
1561  * @m: metadata context
1562  * @idx: index into the method table
1563  *
1564  * Returns: A stringified version of the method signature.
1565  */
1566 char *
1567 get_methoddef (MonoImage *m, guint32 idx)
1568 {
1569         guint32 cols [MONO_METHOD_SIZE];
1570         char *sig;
1571         const char *name;
1572
1573         MonoMethod *mh;
1574
1575         mh = mono_get_method (m, MONO_TOKEN_METHOD_DEF | idx, NULL);
1576         if (mh) {
1577                 sig = dis_stringify_object_with_class (m, mh->klass, TRUE, FALSE);
1578                 name = g_strdup_printf ("%s::%s", sig, mh->name);
1579                 g_free (sig);
1580         } else
1581                 name = NULL;
1582         mono_metadata_decode_row (&m->tables [MONO_TABLE_METHOD], 
1583                         idx - 1, cols, MONO_METHOD_SIZE);
1584         sig = get_methodref_signature (m, cols [MONO_METHOD_SIGNATURE], name, NULL);
1585         
1586         return sig;
1587 }
1588
1589 char *
1590 get_method_type_param (MonoImage *m, guint32 blob_signature, MonoGenericContext *context)
1591 {
1592         GString *res = g_string_new ("");
1593         const char *ptr = mono_metadata_blob_heap (m, blob_signature);
1594         int param_count;
1595         int i = 0;
1596         char *s;
1597         
1598         mono_metadata_decode_value (ptr, &ptr);
1599         ptr++;
1600         param_count = mono_metadata_decode_value (ptr, &ptr);
1601         
1602         g_string_append_c (res, '<');
1603         
1604         for (i = 0; i < param_count; i++){
1605                 char *param = NULL;
1606
1607                 ptr = get_param (m, ptr, &param, context);
1608                 g_string_append (res, param);
1609                 if (i+1 != param_count)
1610                         g_string_append (res, ", ");
1611                 g_free (param);
1612         }
1613         g_string_append_c (res, '>');
1614         
1615         s = res->str;
1616         g_string_free (res, FALSE);
1617         return s;
1618 }
1619
1620 /**
1621  * get_methodspec
1622  *
1623  * Returns: An allocated stringified version of the methodspec signature.
1624  */
1625
1626 char *
1627 get_methodspec (MonoImage *m, int idx, guint32 token, const char *fancy_name, MonoGenericContext *context)
1628 {
1629         GString *res = g_string_new ("");
1630         guint32 member_cols [MONO_MEMBERREF_SIZE], method_cols [MONO_METHOD_SIZE];
1631         char *s, *type_param;
1632         const char *ptr;
1633         guint32 sig = 0;
1634         int param_count, cconv, i, gen_count = 0;
1635
1636         switch (token & MONO_METHODDEFORREF_MASK) {
1637         case MONO_METHODDEFORREF_METHODDEF:
1638                 mono_metadata_decode_row (&m->tables [MONO_TABLE_METHOD], 
1639                                           (token >> MONO_METHODDEFORREF_BITS) - 1,
1640                                           method_cols, MONO_METHOD_SIZE);
1641                 sig = method_cols [MONO_METHOD_SIGNATURE];
1642                 break;
1643         case MONO_METHODDEFORREF_METHODREF:
1644                 mono_metadata_decode_row (&m->tables [MONO_TABLE_MEMBERREF], 
1645                                           (token >> MONO_METHODDEFORREF_BITS) - 1,
1646                                           member_cols, MONO_MEMBERREF_SIZE);
1647                 sig = member_cols [MONO_MEMBERREF_SIGNATURE];
1648                 break;
1649         default:
1650                 g_assert_not_reached ();
1651         }
1652
1653         ptr = mono_metadata_blob_heap (m, sig);
1654         mono_metadata_decode_value (ptr, &ptr);
1655
1656         if (*ptr & 0x20){
1657                 if (*ptr & 0x40)
1658                         g_string_append (res, "explicit-this ");
1659                 else
1660                         g_string_append (res, "instance "); /* has-this */
1661         }
1662
1663         if (*ptr & 0x10)
1664                 gen_count = 1;
1665         cconv = *ptr & 0x0f;
1666         ptr++;
1667         if (gen_count)
1668                 gen_count = mono_metadata_decode_value (ptr, &ptr);
1669         param_count = mono_metadata_decode_value (ptr, &ptr);
1670         if (cconv != 0xa) {
1671                 char *allocated_ret_type;
1672                 ptr = get_ret_type (m, ptr, &allocated_ret_type, context);
1673                 g_string_append (res, allocated_ret_type);
1674                 g_free (allocated_ret_type);
1675         }
1676
1677         if (fancy_name){
1678                 g_string_append_c (res, ' ');
1679                 g_string_append (res, fancy_name);
1680         }
1681
1682         mono_metadata_decode_row (&m->tables [MONO_TABLE_METHODSPEC],
1683                         idx - 1, member_cols, MONO_METHODSPEC_SIZE);
1684         token = member_cols [MONO_METHODSPEC_SIGNATURE];
1685         type_param = get_method_type_param (m, token, context);
1686         g_string_append (res, type_param);
1687         g_string_append (res, " (");
1688
1689         /*
1690          * methodspecs can not be varargs so we don't need to worry about that here
1691          */
1692          
1693         for (i = 0; i < param_count; i++){
1694                 char *param = NULL;
1695                 
1696                 ptr = get_param (m, ptr, &param, context);
1697                 g_string_append (res, param);
1698                 if (i+1 != param_count)
1699                         g_string_append (res, ", ");
1700                 g_free (param);
1701         }
1702         g_string_append (res, ")");
1703         
1704         /*
1705          * cleanup and return
1706          */
1707         s = res->str;
1708         g_string_free (res, FALSE);
1709         return s;
1710 }
1711
1712
1713 /**
1714  * get_constant:
1715  * @m: metadata context
1716  * @blob_index: index into the blob where the constant is stored
1717  *
1718  * Returns: An allocated value representing a stringified version of the
1719  * constant.
1720  */
1721 char *
1722 get_constant (MonoImage *m, MonoTypeEnum t, guint32 blob_index)
1723 {
1724         const unsigned char *ptr = mono_metadata_blob_heap (m, blob_index);
1725         int len;
1726         
1727         len = mono_metadata_decode_value (ptr, (const char**)&ptr);
1728         
1729         switch (t){
1730         case MONO_TYPE_BOOLEAN:
1731                 return g_strdup_printf ("%s", *ptr ? "bool(true)" : "bool(false)");
1732                 
1733         case MONO_TYPE_CHAR:
1734                 return g_strdup_printf ("char(0x%04x)", read16(ptr)); 
1735                 
1736         case MONO_TYPE_U1:
1737         case MONO_TYPE_I1:
1738                 return g_strdup_printf ("int8(0x%02x)", (int) (*ptr));
1739                 break;
1740                 
1741         case MONO_TYPE_U2:
1742         case MONO_TYPE_I2:
1743                 return g_strdup_printf ("int16(0x%08x)", (int) read16 (ptr));
1744                 
1745         case MONO_TYPE_U4:
1746         case MONO_TYPE_I4:
1747                 return g_strdup_printf ("int32(%d)", read32 (ptr));
1748                 
1749         case MONO_TYPE_I8: {
1750                 guint32 low, high;
1751                 low = read32 (ptr);
1752                 high = read32 (ptr + 4);
1753                 return g_strdup_printf ("int64(0x%08x%08x)", high, low);
1754         }
1755         case MONO_TYPE_U8: {
1756                 guint32 low, high;
1757                 low = read32 (ptr);
1758                 high = read32 (ptr + 4);
1759                 return g_strdup_printf ("0x%08x%08x", high, low);
1760         }
1761         case MONO_TYPE_R4: {
1762                 float r;
1763                 readr4 (ptr, &r);
1764                 return g_strdup_printf ("float32(%g)", (double) r);
1765         }
1766         case MONO_TYPE_R8: {
1767                 double r;
1768                 readr8 (ptr, &r);
1769                 return g_strdup_printf ("float64(%g)", r);
1770         }
1771         case MONO_TYPE_STRING: {
1772                 gchar *str;
1773                 int i, j, tspaces = (len%16);
1774                 GString *res = g_string_new ("bytearray (\n\t");
1775
1776                 for(i = 1; i <= len; ++i) {
1777                         g_string_append_printf(res, "%02x ", ptr[i-1]);
1778
1779                         if(i%16 == 0) {
1780                                 if(i == len)
1781                                         g_string_append(res, ")// ");
1782                                 else
1783                                         g_string_append(res, " // ");
1784
1785                                 for(j = i-16; j < i; ++j) 
1786                                         g_string_append_printf(res, "%c", isprint(ptr[j]) ? ptr[j] : '.');
1787                                 g_string_append(res, "\n\t");
1788                         }
1789                 }
1790
1791                 if(tspaces) {
1792                         g_string_append(res, ")  ");
1793                         for(i = tspaces+1; i < 16; ++i)
1794                                 g_string_append_printf(res, "   ");
1795
1796                         g_string_append(res, " // ");
1797                         for(i = len-tspaces; i < len; ++i)
1798                                 g_string_append_printf(res, "%c", isprint(ptr[i]) ? ptr[i] : '.');
1799                         g_string_append(res, "\n\t");
1800                 } 
1801
1802                 str = res->str;
1803                 g_string_free(res, FALSE);
1804                 return str;
1805         }
1806                 
1807         case MONO_TYPE_CLASS:
1808                 return g_strdup ("nullref");
1809                 
1810         default:
1811                 g_error ("Unknown MONO_TYPE (%d) on constant at Blob index (0x%08x)\n",
1812                          (int) *ptr, blob_index);
1813                 return g_strdup_printf ("Unknown");
1814         }
1815
1816 }
1817
1818 /**
1819  * get_token:
1820  * @m: metadata context
1821  * @token: token that we want to decode.
1822  *
1823  * Returns: An allocated value representing a stringified version of the
1824  * constant.
1825  */
1826 char *
1827 get_token (MonoImage *m, guint32 token, MonoGenericContext *context)
1828 {
1829         char *temp, *result;
1830         guint32 idx = mono_metadata_token_index (token);
1831
1832         switch (mono_metadata_token_code (token)){
1833         case MONO_TOKEN_FIELD_DEF:
1834                 temp = get_field (m, token, context);
1835                 result = g_strdup_printf ("field %s", temp);
1836                 g_free (temp);
1837                 return result;
1838         case MONO_TOKEN_TYPE_DEF:
1839                 return get_typedef (m, idx);
1840         case MONO_TOKEN_TYPE_REF:
1841                 return get_typeref (m, idx);
1842         case MONO_TOKEN_TYPE_SPEC:
1843                 return get_typespec (m, idx, context);
1844         case MONO_TOKEN_MEMBER_REF: {
1845                 guint32 cols [MONO_MEMBERREF_SIZE];
1846                 const char *sig;
1847                 mono_metadata_decode_row (&m->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
1848                 sig = mono_metadata_blob_heap (m, cols [MONO_MEMBERREF_SIGNATURE]);
1849                 mono_metadata_decode_blob_size (sig, &sig);
1850                 if (*sig == 0x6) { /* it's a field */
1851                         temp = get_field (m, token, context);
1852                         result = g_strdup_printf ("field %s", temp);
1853                         g_free (temp);
1854                         return result;
1855                 }
1856                 else {
1857                         g_error ("Do not know how to decode tokens of type 0x%08x", token);
1858                 }
1859                 break;
1860         }
1861         default:                
1862                 g_error ("Do not know how to decode tokens of type 0x%08x", token);
1863         }
1864
1865         g_assert_not_reached ();
1866         return g_strdup ("ERROR");
1867 }
1868
1869 /**
1870  * get_token_type:
1871  * @m: metadata context
1872  * @token: the token can belong to any of the following tables:
1873  * MONO_TOKEN_TYPE_REF, MONO_TOKEN_TYPE_DEF, MONO_TOKEN_TYPE_SPEC
1874  *
1875  * Returns: a stringified version of the MethodDef or MethodRef or TypeSpecn
1876  * at (token & 0xffffff) 
1877  */
1878 char *
1879 get_token_type (MonoImage *m, guint32 token, MonoGenericContext *context)
1880 {
1881         char *temp = NULL, *s = NULL;
1882         int idx;
1883
1884         idx = mono_metadata_token_index (token);
1885         
1886         switch (mono_metadata_token_code (token)){
1887         case MONO_TOKEN_TYPE_DEF:
1888                 temp = get_typedef (m, idx);
1889                 s = g_strdup_printf ("%s", temp);
1890                 break;
1891                 
1892         case MONO_TOKEN_TYPE_REF: 
1893                 temp = get_typeref (m, idx);
1894                 s = g_strdup_printf ("%s", temp);
1895                 break;
1896                 
1897         case MONO_TOKEN_TYPE_SPEC:
1898                 s = get_typespec (m, idx, context);
1899                 break;
1900
1901         default:
1902                 g_error ("Unhandled encoding for token 0x%08x", token);
1903
1904         }
1905         
1906         if (temp)
1907                 g_free (temp);
1908
1909         return s;
1910 }
1911
1912 char *
1913 get_guid (MonoImage *m, guint32 guid_index)
1914 {
1915         const unsigned char *guid;
1916         char *result;
1917
1918         guid = mono_metadata_guid_heap (m, guid_index);
1919
1920         result = g_strdup_printf ("{%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X}", 
1921                         guid [3], guid [2], guid [1], guid [0], guid [5], guid [4], guid [7], guid [6],
1922                         guid [8], guid [9], guid [10], guid [11], guid [12], guid [13], guid [14], guid [15]);
1923         return result;
1924 }
1925
1926 GList *
1927 dis_get_custom_attrs (MonoImage *m, guint32 token)
1928 {
1929         GList *list = NULL;
1930         guint32 idx, i, len, mtoken;
1931         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
1932         MonoTableInfo *ca;
1933         char *method;
1934         GString *attr;
1935         const char *val;
1936
1937         idx = mono_metadata_token_index (token);
1938         idx <<= MONO_CUSTOM_ATTR_BITS;
1939         
1940         switch (mono_metadata_token_table (token)) {
1941         case MONO_TABLE_TYPEDEF:
1942                 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
1943                 break;
1944         case MONO_TABLE_ASSEMBLY:
1945                 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
1946                 break;
1947         case MONO_TABLE_MODULE:
1948                 idx |= MONO_CUSTOM_ATTR_MODULE;
1949                 break;
1950         case MONO_TABLE_PROPERTY:
1951                 idx |= MONO_CUSTOM_ATTR_PROPERTY;
1952                 break;
1953         case MONO_TABLE_EVENT:
1954                 idx |= MONO_CUSTOM_ATTR_EVENT;
1955                 break;
1956         case MONO_TABLE_FIELD:
1957                 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
1958                 break;
1959         case MONO_TABLE_METHOD:
1960                 idx |= MONO_CUSTOM_ATTR_METHODDEF;
1961                 break;
1962         case MONO_TABLE_PARAM:
1963                 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
1964                 break;
1965         default:
1966                 g_print ("Missing custom attr get support for token 0x%08x\n", token);
1967                 return NULL;
1968         }
1969
1970         ca = &m->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1971         /* the table is not sorted */
1972         for (i = 0; i < ca->rows; ++i) {
1973                 char *dump;
1974                 mono_metadata_decode_row (ca, i, cols, MONO_CUSTOM_ATTR_SIZE);
1975                 if (cols [MONO_CUSTOM_ATTR_PARENT] != idx)
1976                         continue;
1977                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
1978                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
1979                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
1980                         mtoken |= MONO_TOKEN_METHOD_DEF;
1981                         break;
1982                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
1983                         mtoken |= MONO_TOKEN_MEMBER_REF;
1984                         break;
1985                 default:
1986                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
1987                         break;
1988                 }
1989                 method = get_method (m, mtoken, NULL);
1990                 val = mono_metadata_blob_heap (m, cols [MONO_CUSTOM_ATTR_VALUE]);
1991                 len = mono_metadata_decode_value (val, &val);
1992                 attr = g_string_new (".custom ");
1993                 dump = data_dump (val, len, "\t\t");
1994                 g_string_sprintfa (attr, "%s = %s", method, dump);
1995                 g_free (dump);
1996                 list = g_list_append (list, attr->str);
1997                 g_string_free (attr, FALSE);
1998                 g_free (method);
1999         }
2000         return list;
2001 }
2002
2003 char*
2004 get_marshal_info (MonoImage *m, const char *blob) {
2005         int len, size = 0;
2006
2007         len = mono_metadata_decode_blob_size (blob, &blob);
2008
2009         switch (*blob) {
2010         case MONO_NATIVE_BOOLEAN:
2011                 return g_strdup ("bool");
2012         case MONO_NATIVE_I1:
2013                 return g_strdup ("int8");
2014         case MONO_NATIVE_U1:
2015                 return g_strdup ("unsigned int8");
2016         case MONO_NATIVE_I2:
2017                 return g_strdup ("int16");
2018         case MONO_NATIVE_U2:
2019                 return g_strdup ("unsigned int16");
2020         case MONO_NATIVE_I4:
2021                 return g_strdup ("int32");
2022         case MONO_NATIVE_U4:
2023                 return g_strdup ("unsigned int32");
2024         case MONO_NATIVE_I8:
2025                 return g_strdup ("int64");
2026         case MONO_NATIVE_U8:
2027                 return g_strdup ("unsigned int64");
2028         case MONO_NATIVE_R4:
2029                 return g_strdup ("float32");
2030         case MONO_NATIVE_R8:
2031                 return g_strdup ("float64");
2032         case MONO_NATIVE_CURRENCY:
2033                 return g_strdup ("currency");
2034         case MONO_NATIVE_BSTR:
2035                 return g_strdup ("bstr");
2036         case MONO_NATIVE_LPSTR:
2037                 return g_strdup ("lpstr");
2038         case MONO_NATIVE_LPWSTR:
2039                 return g_strdup ("lpwstr");
2040         case MONO_NATIVE_LPTSTR:
2041                 return g_strdup ("lptstr");
2042         case MONO_NATIVE_BYVALTSTR:
2043                 size = mono_metadata_decode_value (blob + 1, &blob);
2044                 return g_strdup_printf ("fixed sysstring [%d]", size);
2045         case MONO_NATIVE_IUNKNOWN:
2046                 return g_strdup ("iunknown");
2047         case MONO_NATIVE_IDISPATCH:
2048                 return g_strdup ("idispatch");
2049         case MONO_NATIVE_STRUCT:
2050                 return g_strdup ("struct");
2051         case MONO_NATIVE_INTERFACE:
2052                 return g_strdup ("interface");
2053         case MONO_NATIVE_SAFEARRAY:
2054                 return g_strdup ("safearray");
2055         case MONO_NATIVE_BYVALARRAY:
2056                 size = mono_metadata_decode_value (blob + 1, &blob);
2057                 return g_strdup_printf ("fixed array [%d]", size);
2058         case MONO_NATIVE_INT:
2059                 return g_strdup ("int");
2060         case MONO_NATIVE_UINT:
2061                 return g_strdup ("unsigned int");
2062         case MONO_NATIVE_VBBYREFSTR:
2063                 return g_strdup ("vbbyrefstr");
2064         case MONO_NATIVE_ANSIBSTR:
2065                 return g_strdup ("ansi bstr");
2066         case MONO_NATIVE_TBSTR:
2067                 return g_strdup ("tbstr");
2068         case MONO_NATIVE_VARIANTBOOL:
2069                 return g_strdup ("variant bool");
2070         case MONO_NATIVE_FUNC:
2071                 return g_strdup ("method");
2072         case MONO_NATIVE_ASANY:
2073                 return g_strdup ("as any");
2074         case MONO_NATIVE_LPARRAY:
2075                 return g_strdup ("[]");
2076         case MONO_NATIVE_LPSTRUCT:
2077                 return g_strdup ("lpstruct");
2078         case MONO_NATIVE_CUSTOM:
2079                 return g_strdup ("custom");
2080         case MONO_NATIVE_ERROR:
2081                 return g_strdup ("error");
2082         default:
2083                 return g_strdup ("unknown");
2084         }
2085 }
2086
2087 void
2088 init_key_table (void)
2089 {
2090         key_table = g_hash_table_new (g_str_hash, g_str_equal);
2091
2092         g_hash_table_insert (key_table, (char *) "9", GINT_TO_POINTER (TRUE));
2093         g_hash_table_insert (key_table, (char *) "abstract", GINT_TO_POINTER (TRUE));
2094         g_hash_table_insert (key_table, (char *) "add", GINT_TO_POINTER (TRUE));
2095         g_hash_table_insert (key_table, (char *) "add.ovf", GINT_TO_POINTER (TRUE));
2096         g_hash_table_insert (key_table, (char *) "add.ovf.un", GINT_TO_POINTER (TRUE));
2097         g_hash_table_insert (key_table, (char *) "algorithm", GINT_TO_POINTER (TRUE));
2098         g_hash_table_insert (key_table, (char *) "alignment", GINT_TO_POINTER (TRUE));
2099         g_hash_table_insert (key_table, (char *) "and", GINT_TO_POINTER (TRUE));
2100         g_hash_table_insert (key_table, (char *) "ansi", GINT_TO_POINTER (TRUE));
2101         g_hash_table_insert (key_table, (char *) "any", GINT_TO_POINTER (TRUE));
2102         g_hash_table_insert (key_table, (char *) "arglist", GINT_TO_POINTER (TRUE));
2103         g_hash_table_insert (key_table, (char *) "array", GINT_TO_POINTER (TRUE));
2104         g_hash_table_insert (key_table, (char *) "as", GINT_TO_POINTER (TRUE));
2105         g_hash_table_insert (key_table, (char *) "assembly", GINT_TO_POINTER (TRUE));
2106         g_hash_table_insert (key_table, (char *) "assert", GINT_TO_POINTER (TRUE));
2107         g_hash_table_insert (key_table, (char *) "at", GINT_TO_POINTER (TRUE));
2108         g_hash_table_insert (key_table, (char *) "autochar", GINT_TO_POINTER (TRUE));
2109         g_hash_table_insert (key_table, (char *) "auto", GINT_TO_POINTER (TRUE));
2110         g_hash_table_insert (key_table, (char *) "beforefieldinit", GINT_TO_POINTER (TRUE));
2111         g_hash_table_insert (key_table, (char *) "beq", GINT_TO_POINTER (TRUE));
2112         g_hash_table_insert (key_table, (char *) "beq.s", GINT_TO_POINTER (TRUE));
2113         g_hash_table_insert (key_table, (char *) "bge", GINT_TO_POINTER (TRUE));
2114         g_hash_table_insert (key_table, (char *) "bge.s", GINT_TO_POINTER (TRUE));
2115         g_hash_table_insert (key_table, (char *) "bge.un", GINT_TO_POINTER (TRUE));
2116         g_hash_table_insert (key_table, (char *) "bge.un.s", GINT_TO_POINTER (TRUE));
2117         g_hash_table_insert (key_table, (char *) "bgt", GINT_TO_POINTER (TRUE));
2118         g_hash_table_insert (key_table, (char *) "bgt.s", GINT_TO_POINTER (TRUE));
2119         g_hash_table_insert (key_table, (char *) "bgt.un", GINT_TO_POINTER (TRUE));
2120         g_hash_table_insert (key_table, (char *) "bgt.un.s", GINT_TO_POINTER (TRUE));
2121         g_hash_table_insert (key_table, (char *) "ble", GINT_TO_POINTER (TRUE));
2122         g_hash_table_insert (key_table, (char *) "ble.s", GINT_TO_POINTER (TRUE));
2123         g_hash_table_insert (key_table, (char *) "ble.un", GINT_TO_POINTER (TRUE));
2124         g_hash_table_insert (key_table, (char *) "ble.un.s", GINT_TO_POINTER (TRUE));
2125         g_hash_table_insert (key_table, (char *) "blob", GINT_TO_POINTER (TRUE));
2126         g_hash_table_insert (key_table, (char *) "blob_object", GINT_TO_POINTER (TRUE));
2127         g_hash_table_insert (key_table, (char *) "blt", GINT_TO_POINTER (TRUE));
2128         g_hash_table_insert (key_table, (char *) "blt.s", GINT_TO_POINTER (TRUE));
2129         g_hash_table_insert (key_table, (char *) "blt.un", GINT_TO_POINTER (TRUE));
2130         g_hash_table_insert (key_table, (char *) "blt.un.s", GINT_TO_POINTER (TRUE));
2131         g_hash_table_insert (key_table, (char *) "bne.un", GINT_TO_POINTER (TRUE));
2132         g_hash_table_insert (key_table, (char *) "bne.un.s", GINT_TO_POINTER (TRUE));
2133         g_hash_table_insert (key_table, (char *) "bool", GINT_TO_POINTER (TRUE));
2134         g_hash_table_insert (key_table, (char *) "box", GINT_TO_POINTER (TRUE));
2135         g_hash_table_insert (key_table, (char *) "break", GINT_TO_POINTER (TRUE));
2136         g_hash_table_insert (key_table, (char *) "brfalse", GINT_TO_POINTER (TRUE));
2137         g_hash_table_insert (key_table, (char *) "brfalse.s", GINT_TO_POINTER (TRUE));
2138         g_hash_table_insert (key_table, (char *) "br", GINT_TO_POINTER (TRUE));
2139         g_hash_table_insert (key_table, (char *) "brinst", GINT_TO_POINTER (TRUE));
2140         g_hash_table_insert (key_table, (char *) "brinst.s", GINT_TO_POINTER (TRUE));
2141         g_hash_table_insert (key_table, (char *) "brnull", GINT_TO_POINTER (TRUE));
2142         g_hash_table_insert (key_table, (char *) "brnull.s", GINT_TO_POINTER (TRUE));
2143         g_hash_table_insert (key_table, (char *) "br.s", GINT_TO_POINTER (TRUE));
2144         g_hash_table_insert (key_table, (char *) "brtrue", GINT_TO_POINTER (TRUE));
2145         g_hash_table_insert (key_table, (char *) "brtrue.s", GINT_TO_POINTER (TRUE));
2146         g_hash_table_insert (key_table, (char *) "brzero", GINT_TO_POINTER (TRUE));
2147         g_hash_table_insert (key_table, (char *) "brzero.s", GINT_TO_POINTER (TRUE));
2148         g_hash_table_insert (key_table, (char *) "bstr", GINT_TO_POINTER (TRUE));
2149         g_hash_table_insert (key_table, (char *) "bytearray", GINT_TO_POINTER (TRUE));
2150         g_hash_table_insert (key_table, (char *) "byvalstr", GINT_TO_POINTER (TRUE));
2151         g_hash_table_insert (key_table, (char *) "call", GINT_TO_POINTER (TRUE));
2152         g_hash_table_insert (key_table, (char *) "calli", GINT_TO_POINTER (TRUE));
2153         g_hash_table_insert (key_table, (char *) "callmostderived", GINT_TO_POINTER (TRUE));
2154         g_hash_table_insert (key_table, (char *) "callvirt", GINT_TO_POINTER (TRUE));
2155         g_hash_table_insert (key_table, (char *) "carray", GINT_TO_POINTER (TRUE));
2156         g_hash_table_insert (key_table, (char *) "castclass", GINT_TO_POINTER (TRUE));
2157         g_hash_table_insert (key_table, (char *) "catch", GINT_TO_POINTER (TRUE));
2158         g_hash_table_insert (key_table, (char *) "cdecl", GINT_TO_POINTER (TRUE));
2159         g_hash_table_insert (key_table, (char *) "ceq", GINT_TO_POINTER (TRUE));
2160         g_hash_table_insert (key_table, (char *) "cf", GINT_TO_POINTER (TRUE));
2161         g_hash_table_insert (key_table, (char *) "cgt", GINT_TO_POINTER (TRUE));
2162         g_hash_table_insert (key_table, (char *) "cgt.un", GINT_TO_POINTER (TRUE));
2163         g_hash_table_insert (key_table, (char *) "char", GINT_TO_POINTER (TRUE));
2164         g_hash_table_insert (key_table, (char *) "cil", GINT_TO_POINTER (TRUE));
2165         g_hash_table_insert (key_table, (char *) "ckfinite", GINT_TO_POINTER (TRUE));
2166         g_hash_table_insert (key_table, (char *) "class", GINT_TO_POINTER (TRUE));
2167         g_hash_table_insert (key_table, (char *) "clsid", GINT_TO_POINTER (TRUE));
2168         g_hash_table_insert (key_table, (char *) "clt", GINT_TO_POINTER (TRUE));
2169         g_hash_table_insert (key_table, (char *) "clt.un", GINT_TO_POINTER (TRUE));
2170         g_hash_table_insert (key_table, (char *) "Compilercontrolled", GINT_TO_POINTER (TRUE));
2171         g_hash_table_insert (key_table, (char *) "const", GINT_TO_POINTER (TRUE));
2172         g_hash_table_insert (key_table, (char *) "conv.i1", GINT_TO_POINTER (TRUE));
2173         g_hash_table_insert (key_table, (char *) "conv.i2", GINT_TO_POINTER (TRUE));
2174         g_hash_table_insert (key_table, (char *) "conv.i4", GINT_TO_POINTER (TRUE));
2175         g_hash_table_insert (key_table, (char *) "conv.i8", GINT_TO_POINTER (TRUE));
2176         g_hash_table_insert (key_table, (char *) "conv.i", GINT_TO_POINTER (TRUE));
2177         g_hash_table_insert (key_table, (char *) "conv.ovf.i1", GINT_TO_POINTER (TRUE));
2178         g_hash_table_insert (key_table, (char *) "conv.ovf.i1.un", GINT_TO_POINTER (TRUE));
2179         g_hash_table_insert (key_table, (char *) "conv.ovf.i2", GINT_TO_POINTER (TRUE));
2180         g_hash_table_insert (key_table, (char *) "conv.ovf.i2.un", GINT_TO_POINTER (TRUE));
2181         g_hash_table_insert (key_table, (char *) "conv.ovf.i4", GINT_TO_POINTER (TRUE));
2182         g_hash_table_insert (key_table, (char *) "conv.ovf.i4.un", GINT_TO_POINTER (TRUE));
2183         g_hash_table_insert (key_table, (char *) "conv.ovf.i8", GINT_TO_POINTER (TRUE));
2184         g_hash_table_insert (key_table, (char *) "conv.ovf.i8.un", GINT_TO_POINTER (TRUE));
2185         g_hash_table_insert (key_table, (char *) "conv.ovf.i", GINT_TO_POINTER (TRUE));
2186         g_hash_table_insert (key_table, (char *) "conv.ovf.i.un", GINT_TO_POINTER (TRUE));
2187         g_hash_table_insert (key_table, (char *) "conv.ovf.u1", GINT_TO_POINTER (TRUE));
2188         g_hash_table_insert (key_table, (char *) "conv.ovf.u1.un", GINT_TO_POINTER (TRUE));
2189         g_hash_table_insert (key_table, (char *) "conv.ovf.u2", GINT_TO_POINTER (TRUE));
2190         g_hash_table_insert (key_table, (char *) "conv.ovf.u2.un", GINT_TO_POINTER (TRUE));
2191         g_hash_table_insert (key_table, (char *) "conv.ovf.u4", GINT_TO_POINTER (TRUE));
2192         g_hash_table_insert (key_table, (char *) "conv.ovf.u4.un", GINT_TO_POINTER (TRUE));
2193         g_hash_table_insert (key_table, (char *) "conv.ovf.u8", GINT_TO_POINTER (TRUE));
2194         g_hash_table_insert (key_table, (char *) "conv.ovf.u8.un", GINT_TO_POINTER (TRUE));
2195         g_hash_table_insert (key_table, (char *) "conv.ovf.u", GINT_TO_POINTER (TRUE));
2196         g_hash_table_insert (key_table, (char *) "conv.ovf.u.un", GINT_TO_POINTER (TRUE));
2197         g_hash_table_insert (key_table, (char *) "conv.r4", GINT_TO_POINTER (TRUE));
2198         g_hash_table_insert (key_table, (char *) "conv.r8", GINT_TO_POINTER (TRUE));
2199         g_hash_table_insert (key_table, (char *) "conv.r.un", GINT_TO_POINTER (TRUE));
2200         g_hash_table_insert (key_table, (char *) "conv.u1", GINT_TO_POINTER (TRUE));
2201         g_hash_table_insert (key_table, (char *) "conv.u2", GINT_TO_POINTER (TRUE));
2202         g_hash_table_insert (key_table, (char *) "conv.u4", GINT_TO_POINTER (TRUE));
2203         g_hash_table_insert (key_table, (char *) "conv.u8", GINT_TO_POINTER (TRUE));
2204         g_hash_table_insert (key_table, (char *) "conv.u", GINT_TO_POINTER (TRUE));
2205         g_hash_table_insert (key_table, (char *) "cpblk", GINT_TO_POINTER (TRUE));
2206         g_hash_table_insert (key_table, (char *) "cpobj", GINT_TO_POINTER (TRUE));
2207         g_hash_table_insert (key_table, (char *) "currency", GINT_TO_POINTER (TRUE));
2208         g_hash_table_insert (key_table, (char *) "custom", GINT_TO_POINTER (TRUE));
2209         g_hash_table_insert (key_table, (char *) "date", GINT_TO_POINTER (TRUE));
2210         g_hash_table_insert (key_table, (char *) "decimal", GINT_TO_POINTER (TRUE));
2211         g_hash_table_insert (key_table, (char *) "default", GINT_TO_POINTER (TRUE));
2212         g_hash_table_insert (key_table, (char *) "demand", GINT_TO_POINTER (TRUE));
2213         g_hash_table_insert (key_table, (char *) "deny", GINT_TO_POINTER (TRUE));
2214         g_hash_table_insert (key_table, (char *) "div", GINT_TO_POINTER (TRUE));
2215         g_hash_table_insert (key_table, (char *) "div.un", GINT_TO_POINTER (TRUE));
2216         g_hash_table_insert (key_table, (char *) "dup", GINT_TO_POINTER (TRUE));
2217         g_hash_table_insert (key_table, (char *) "endfault", GINT_TO_POINTER (TRUE));
2218         g_hash_table_insert (key_table, (char *) "endfilter", GINT_TO_POINTER (TRUE));
2219         g_hash_table_insert (key_table, (char *) "endfinally", GINT_TO_POINTER (TRUE));
2220         g_hash_table_insert (key_table, (char *) "endmac", GINT_TO_POINTER (TRUE));
2221         g_hash_table_insert (key_table, (char *) "enum", GINT_TO_POINTER (TRUE));
2222         g_hash_table_insert (key_table, (char *) "error", GINT_TO_POINTER (TRUE));
2223         g_hash_table_insert (key_table, (char *) "explicit", GINT_TO_POINTER (TRUE));
2224         g_hash_table_insert (key_table, (char *) "extends", GINT_TO_POINTER (TRUE));
2225         g_hash_table_insert (key_table, (char *) "extern", GINT_TO_POINTER (TRUE));
2226         g_hash_table_insert (key_table, (char *) "false", GINT_TO_POINTER (TRUE));
2227         g_hash_table_insert (key_table, (char *) "famandassem", GINT_TO_POINTER (TRUE));
2228         g_hash_table_insert (key_table, (char *) "family", GINT_TO_POINTER (TRUE));
2229         g_hash_table_insert (key_table, (char *) "famorassem", GINT_TO_POINTER (TRUE));
2230         g_hash_table_insert (key_table, (char *) "fastcall", GINT_TO_POINTER (TRUE));
2231         g_hash_table_insert (key_table, (char *) "fault", GINT_TO_POINTER (TRUE));
2232         g_hash_table_insert (key_table, (char *) "field", GINT_TO_POINTER (TRUE));
2233         g_hash_table_insert (key_table, (char *) "filetime", GINT_TO_POINTER (TRUE));
2234         g_hash_table_insert (key_table, (char *) "filter", GINT_TO_POINTER (TRUE));
2235         g_hash_table_insert (key_table, (char *) "final", GINT_TO_POINTER (TRUE));
2236         g_hash_table_insert (key_table, (char *) "finally", GINT_TO_POINTER (TRUE));
2237         g_hash_table_insert (key_table, (char *) "fixed", GINT_TO_POINTER (TRUE));
2238         g_hash_table_insert (key_table, (char *) "float32", GINT_TO_POINTER (TRUE));
2239         g_hash_table_insert (key_table, (char *) "float64", GINT_TO_POINTER (TRUE));
2240         g_hash_table_insert (key_table, (char *) "float", GINT_TO_POINTER (TRUE));
2241         g_hash_table_insert (key_table, (char *) "forwardref", GINT_TO_POINTER (TRUE));
2242         g_hash_table_insert (key_table, (char *) "fromunmanaged", GINT_TO_POINTER (TRUE));
2243         g_hash_table_insert (key_table, (char *) "handler", GINT_TO_POINTER (TRUE));
2244         g_hash_table_insert (key_table, (char *) "hidebysig", GINT_TO_POINTER (TRUE));
2245         g_hash_table_insert (key_table, (char *) "hresult", GINT_TO_POINTER (TRUE));
2246         g_hash_table_insert (key_table, (char *) "idispatch", GINT_TO_POINTER (TRUE));
2247         g_hash_table_insert (key_table, (char *) "il", GINT_TO_POINTER (TRUE));
2248         g_hash_table_insert (key_table, (char *) "illegal", GINT_TO_POINTER (TRUE));
2249         g_hash_table_insert (key_table, (char *) "implements", GINT_TO_POINTER (TRUE));
2250         g_hash_table_insert (key_table, (char *) "implicitcom", GINT_TO_POINTER (TRUE));
2251         g_hash_table_insert (key_table, (char *) "implicitres", GINT_TO_POINTER (TRUE));
2252         g_hash_table_insert (key_table, (char *) "import", GINT_TO_POINTER (TRUE));
2253         g_hash_table_insert (key_table, (char *) "in", GINT_TO_POINTER (TRUE));
2254         g_hash_table_insert (key_table, (char *) "inheritcheck", GINT_TO_POINTER (TRUE));
2255         g_hash_table_insert (key_table, (char *) "initblk", GINT_TO_POINTER (TRUE));
2256         g_hash_table_insert (key_table, (char *) "init", GINT_TO_POINTER (TRUE));
2257         g_hash_table_insert (key_table, (char *) "initobj", GINT_TO_POINTER (TRUE));
2258         g_hash_table_insert (key_table, (char *) "initonly", GINT_TO_POINTER (TRUE));
2259         g_hash_table_insert (key_table, (char *) "instance", GINT_TO_POINTER (TRUE));
2260         g_hash_table_insert (key_table, (char *) "int16", GINT_TO_POINTER (TRUE));
2261         g_hash_table_insert (key_table, (char *) "int32", GINT_TO_POINTER (TRUE));
2262         g_hash_table_insert (key_table, (char *) "int64", GINT_TO_POINTER (TRUE));
2263         g_hash_table_insert (key_table, (char *) "int8", GINT_TO_POINTER (TRUE));
2264         g_hash_table_insert (key_table, (char *) "interface", GINT_TO_POINTER (TRUE));
2265         g_hash_table_insert (key_table, (char *) "internalcall", GINT_TO_POINTER (TRUE));
2266         g_hash_table_insert (key_table, (char *) "int", GINT_TO_POINTER (TRUE));
2267         g_hash_table_insert (key_table, (char *) "isinst", GINT_TO_POINTER (TRUE));
2268         g_hash_table_insert (key_table, (char *) "iunknown", GINT_TO_POINTER (TRUE));
2269         g_hash_table_insert (key_table, (char *) "jmp", GINT_TO_POINTER (TRUE));
2270         g_hash_table_insert (key_table, (char *) "lasterr", GINT_TO_POINTER (TRUE));
2271         g_hash_table_insert (key_table, (char *) "lcid", GINT_TO_POINTER (TRUE));
2272         g_hash_table_insert (key_table, (char *) "ldarg.0", GINT_TO_POINTER (TRUE));
2273         g_hash_table_insert (key_table, (char *) "ldarg.1", GINT_TO_POINTER (TRUE));
2274         g_hash_table_insert (key_table, (char *) "ldarg.2", GINT_TO_POINTER (TRUE));
2275         g_hash_table_insert (key_table, (char *) "ldarg.3", GINT_TO_POINTER (TRUE));
2276         g_hash_table_insert (key_table, (char *) "ldarga", GINT_TO_POINTER (TRUE));
2277         g_hash_table_insert (key_table, (char *) "ldarga.s", GINT_TO_POINTER (TRUE));
2278         g_hash_table_insert (key_table, (char *) "ldarg", GINT_TO_POINTER (TRUE));
2279         g_hash_table_insert (key_table, (char *) "ldarg.s", GINT_TO_POINTER (TRUE));
2280         g_hash_table_insert (key_table, (char *) "ldc.i4.0", GINT_TO_POINTER (TRUE));
2281         g_hash_table_insert (key_table, (char *) "ldc.i4.1", GINT_TO_POINTER (TRUE));
2282         g_hash_table_insert (key_table, (char *) "ldc.i4.2", GINT_TO_POINTER (TRUE));
2283         g_hash_table_insert (key_table, (char *) "ldc.i4.3", GINT_TO_POINTER (TRUE));
2284         g_hash_table_insert (key_table, (char *) "ldc.i4.4", GINT_TO_POINTER (TRUE));
2285         g_hash_table_insert (key_table, (char *) "ldc.i4.5", GINT_TO_POINTER (TRUE));
2286         g_hash_table_insert (key_table, (char *) "ldc.i4.6", GINT_TO_POINTER (TRUE));
2287         g_hash_table_insert (key_table, (char *) "ldc.i4.7", GINT_TO_POINTER (TRUE));
2288         g_hash_table_insert (key_table, (char *) "ldc.i4.8", GINT_TO_POINTER (TRUE));
2289         g_hash_table_insert (key_table, (char *) "ldc.i4", GINT_TO_POINTER (TRUE));
2290         g_hash_table_insert (key_table, (char *) "ldc.i4.m1", GINT_TO_POINTER (TRUE));
2291         g_hash_table_insert (key_table, (char *) "ldc.i4.M1", GINT_TO_POINTER (TRUE));
2292         g_hash_table_insert (key_table, (char *) "ldc.i4.s", GINT_TO_POINTER (TRUE));
2293         g_hash_table_insert (key_table, (char *) "ldc.i8", GINT_TO_POINTER (TRUE));
2294         g_hash_table_insert (key_table, (char *) "ldc.r4", GINT_TO_POINTER (TRUE));
2295         g_hash_table_insert (key_table, (char *) "ldc.r8", GINT_TO_POINTER (TRUE));
2296         g_hash_table_insert (key_table, (char *) "ldelema", GINT_TO_POINTER (TRUE));
2297         g_hash_table_insert (key_table, (char *) "ldelem.i1", GINT_TO_POINTER (TRUE));
2298         g_hash_table_insert (key_table, (char *) "ldelem.i2", GINT_TO_POINTER (TRUE));
2299         g_hash_table_insert (key_table, (char *) "ldelem.i4", GINT_TO_POINTER (TRUE));
2300         g_hash_table_insert (key_table, (char *) "ldelem.i8", GINT_TO_POINTER (TRUE));
2301         g_hash_table_insert (key_table, (char *) "ldelem.i", GINT_TO_POINTER (TRUE));
2302         g_hash_table_insert (key_table, (char *) "ldelem.r4", GINT_TO_POINTER (TRUE));
2303         g_hash_table_insert (key_table, (char *) "ldelem.r8", GINT_TO_POINTER (TRUE));
2304         g_hash_table_insert (key_table, (char *) "ldelem.ref", GINT_TO_POINTER (TRUE));
2305         g_hash_table_insert (key_table, (char *) "ldelem.u1", GINT_TO_POINTER (TRUE));
2306         g_hash_table_insert (key_table, (char *) "ldelem.u2", GINT_TO_POINTER (TRUE));
2307         g_hash_table_insert (key_table, (char *) "ldelem.u4", GINT_TO_POINTER (TRUE));
2308         g_hash_table_insert (key_table, (char *) "ldelem.u8", GINT_TO_POINTER (TRUE));
2309         g_hash_table_insert (key_table, (char *) "ldflda", GINT_TO_POINTER (TRUE));
2310         g_hash_table_insert (key_table, (char *) "ldfld", GINT_TO_POINTER (TRUE));
2311         g_hash_table_insert (key_table, (char *) "ldftn", GINT_TO_POINTER (TRUE));
2312         g_hash_table_insert (key_table, (char *) "ldind.i1", GINT_TO_POINTER (TRUE));
2313         g_hash_table_insert (key_table, (char *) "ldind.i2", GINT_TO_POINTER (TRUE));
2314         g_hash_table_insert (key_table, (char *) "ldind.i4", GINT_TO_POINTER (TRUE));
2315         g_hash_table_insert (key_table, (char *) "ldind.i8", GINT_TO_POINTER (TRUE));
2316         g_hash_table_insert (key_table, (char *) "ldind.i", GINT_TO_POINTER (TRUE));
2317         g_hash_table_insert (key_table, (char *) "ldind.r4", GINT_TO_POINTER (TRUE));
2318         g_hash_table_insert (key_table, (char *) "ldind.r8", GINT_TO_POINTER (TRUE));
2319         g_hash_table_insert (key_table, (char *) "ldind.ref", GINT_TO_POINTER (TRUE));
2320         g_hash_table_insert (key_table, (char *) "ldind.u1", GINT_TO_POINTER (TRUE));
2321         g_hash_table_insert (key_table, (char *) "ldind.u2", GINT_TO_POINTER (TRUE));
2322         g_hash_table_insert (key_table, (char *) "ldind.u4", GINT_TO_POINTER (TRUE));
2323         g_hash_table_insert (key_table, (char *) "ldind.u8", GINT_TO_POINTER (TRUE));
2324         g_hash_table_insert (key_table, (char *) "ldlen", GINT_TO_POINTER (TRUE));
2325         g_hash_table_insert (key_table, (char *) "ldloc.0", GINT_TO_POINTER (TRUE));
2326         g_hash_table_insert (key_table, (char *) "ldloc.1", GINT_TO_POINTER (TRUE));
2327         g_hash_table_insert (key_table, (char *) "ldloc.2", GINT_TO_POINTER (TRUE));
2328         g_hash_table_insert (key_table, (char *) "ldloc.3", GINT_TO_POINTER (TRUE));
2329         g_hash_table_insert (key_table, (char *) "ldloca", GINT_TO_POINTER (TRUE));
2330         g_hash_table_insert (key_table, (char *) "ldloca.s", GINT_TO_POINTER (TRUE));
2331         g_hash_table_insert (key_table, (char *) "ldloc", GINT_TO_POINTER (TRUE));
2332         g_hash_table_insert (key_table, (char *) "ldloc.s", GINT_TO_POINTER (TRUE));
2333         g_hash_table_insert (key_table, (char *) "ldnull", GINT_TO_POINTER (TRUE));
2334         g_hash_table_insert (key_table, (char *) "ldobj", GINT_TO_POINTER (TRUE));
2335         g_hash_table_insert (key_table, (char *) "ldsflda", GINT_TO_POINTER (TRUE));
2336         g_hash_table_insert (key_table, (char *) "ldsfld", GINT_TO_POINTER (TRUE));
2337         g_hash_table_insert (key_table, (char *) "ldstr", GINT_TO_POINTER (TRUE));
2338         g_hash_table_insert (key_table, (char *) "ldtoken", GINT_TO_POINTER (TRUE));
2339         g_hash_table_insert (key_table, (char *) "ldvirtftn", GINT_TO_POINTER (TRUE));
2340         g_hash_table_insert (key_table, (char *) "leave", GINT_TO_POINTER (TRUE));
2341         g_hash_table_insert (key_table, (char *) "leave.s", GINT_TO_POINTER (TRUE));
2342         g_hash_table_insert (key_table, (char *) "linkcheck", GINT_TO_POINTER (TRUE));
2343         g_hash_table_insert (key_table, (char *) "literal", GINT_TO_POINTER (TRUE));
2344         g_hash_table_insert (key_table, (char *) "localloc", GINT_TO_POINTER (TRUE));
2345         g_hash_table_insert (key_table, (char *) "lpstr", GINT_TO_POINTER (TRUE));
2346         g_hash_table_insert (key_table, (char *) "lpstruct", GINT_TO_POINTER (TRUE));
2347         g_hash_table_insert (key_table, (char *) "lptstr", GINT_TO_POINTER (TRUE));
2348         g_hash_table_insert (key_table, (char *) "lpvoid", GINT_TO_POINTER (TRUE));
2349         g_hash_table_insert (key_table, (char *) "lpwstr", GINT_TO_POINTER (TRUE));
2350         g_hash_table_insert (key_table, (char *) "managed", GINT_TO_POINTER (TRUE));
2351         g_hash_table_insert (key_table, (char *) "marshal", GINT_TO_POINTER (TRUE));
2352         g_hash_table_insert (key_table, (char *) "method", GINT_TO_POINTER (TRUE));
2353         g_hash_table_insert (key_table, (char *) "mkrefany", GINT_TO_POINTER (TRUE));
2354         g_hash_table_insert (key_table, (char *) "modopt", GINT_TO_POINTER (TRUE));
2355         g_hash_table_insert (key_table, (char *) "modreq", GINT_TO_POINTER (TRUE));
2356         g_hash_table_insert (key_table, (char *) "mul", GINT_TO_POINTER (TRUE));
2357         g_hash_table_insert (key_table, (char *) "mul.ovf", GINT_TO_POINTER (TRUE));
2358         g_hash_table_insert (key_table, (char *) "mul.ovf.un", GINT_TO_POINTER (TRUE));
2359         g_hash_table_insert (key_table, (char *) "native", GINT_TO_POINTER (TRUE));
2360         g_hash_table_insert (key_table, (char *) "neg", GINT_TO_POINTER (TRUE));
2361         g_hash_table_insert (key_table, (char *) "nested", GINT_TO_POINTER (TRUE));
2362         g_hash_table_insert (key_table, (char *) "newarr", GINT_TO_POINTER (TRUE));
2363         g_hash_table_insert (key_table, (char *) "newobj", GINT_TO_POINTER (TRUE));
2364         g_hash_table_insert (key_table, (char *) "newslot", GINT_TO_POINTER (TRUE));
2365         g_hash_table_insert (key_table, (char *) "noappdomain", GINT_TO_POINTER (TRUE));
2366         g_hash_table_insert (key_table, (char *) "noinlining", GINT_TO_POINTER (TRUE));
2367         g_hash_table_insert (key_table, (char *) "nomachine", GINT_TO_POINTER (TRUE));
2368         g_hash_table_insert (key_table, (char *) "nomangle", GINT_TO_POINTER (TRUE));
2369         g_hash_table_insert (key_table, (char *) "nometadata", GINT_TO_POINTER (TRUE));
2370         g_hash_table_insert (key_table, (char *) "noncasdemand", GINT_TO_POINTER (TRUE));
2371         g_hash_table_insert (key_table, (char *) "noncasinheritance", GINT_TO_POINTER (TRUE));
2372         g_hash_table_insert (key_table, (char *) "noncaslinkdemand", GINT_TO_POINTER (TRUE));
2373         g_hash_table_insert (key_table, (char *) "nop", GINT_TO_POINTER (TRUE));
2374         g_hash_table_insert (key_table, (char *) "noprocess", GINT_TO_POINTER (TRUE));
2375         g_hash_table_insert (key_table, (char *) "not", GINT_TO_POINTER (TRUE));
2376         g_hash_table_insert (key_table, (char *) "not_in_gc_heap", GINT_TO_POINTER (TRUE));
2377         g_hash_table_insert (key_table, (char *) "notremotable", GINT_TO_POINTER (TRUE));
2378         g_hash_table_insert (key_table, (char *) "notserialized", GINT_TO_POINTER (TRUE));
2379         g_hash_table_insert (key_table, (char *) "null", GINT_TO_POINTER (TRUE));
2380         g_hash_table_insert (key_table, (char *) "nullref", GINT_TO_POINTER (TRUE));
2381         g_hash_table_insert (key_table, (char *) "object", GINT_TO_POINTER (TRUE));
2382         g_hash_table_insert (key_table, (char *) "objectref", GINT_TO_POINTER (TRUE));
2383         g_hash_table_insert (key_table, (char *) "opt", GINT_TO_POINTER (TRUE));
2384         g_hash_table_insert (key_table, (char *) "optil", GINT_TO_POINTER (TRUE));
2385         g_hash_table_insert (key_table, (char *) "or", GINT_TO_POINTER (TRUE));
2386         g_hash_table_insert (key_table, (char *) "out", GINT_TO_POINTER (TRUE));
2387         g_hash_table_insert (key_table, (char *) "permitonly", GINT_TO_POINTER (TRUE));
2388         g_hash_table_insert (key_table, (char *) "pinned", GINT_TO_POINTER (TRUE));
2389         g_hash_table_insert (key_table, (char *) "pinvokeimpl", GINT_TO_POINTER (TRUE));
2390         g_hash_table_insert (key_table, (char *) "pop", GINT_TO_POINTER (TRUE));
2391         g_hash_table_insert (key_table, (char *) "prefix1", GINT_TO_POINTER (TRUE));
2392         g_hash_table_insert (key_table, (char *) "prefix2", GINT_TO_POINTER (TRUE));
2393         g_hash_table_insert (key_table, (char *) "prefix3", GINT_TO_POINTER (TRUE));
2394         g_hash_table_insert (key_table, (char *) "prefix4", GINT_TO_POINTER (TRUE));
2395         g_hash_table_insert (key_table, (char *) "prefix5", GINT_TO_POINTER (TRUE));
2396         g_hash_table_insert (key_table, (char *) "prefix6", GINT_TO_POINTER (TRUE));
2397         g_hash_table_insert (key_table, (char *) "prefix7", GINT_TO_POINTER (TRUE));
2398         g_hash_table_insert (key_table, (char *) "prefixref", GINT_TO_POINTER (TRUE));
2399         g_hash_table_insert (key_table, (char *) "prejitdeny", GINT_TO_POINTER (TRUE));
2400         g_hash_table_insert (key_table, (char *) "prejitgrant", GINT_TO_POINTER (TRUE));
2401         g_hash_table_insert (key_table, (char *) "preservesig", GINT_TO_POINTER (TRUE));
2402         g_hash_table_insert (key_table, (char *) "private", GINT_TO_POINTER (TRUE));
2403         g_hash_table_insert (key_table, (char *) "privatescope", GINT_TO_POINTER (TRUE));
2404         g_hash_table_insert (key_table, (char *) "protected", GINT_TO_POINTER (TRUE));
2405         g_hash_table_insert (key_table, (char *) "public", GINT_TO_POINTER (TRUE));
2406         g_hash_table_insert (key_table, (char *) "readonly", GINT_TO_POINTER (TRUE));
2407         g_hash_table_insert (key_table, (char *) "record", GINT_TO_POINTER (TRUE));
2408         g_hash_table_insert (key_table, (char *) "refany", GINT_TO_POINTER (TRUE));
2409         g_hash_table_insert (key_table, (char *) "refanytype", GINT_TO_POINTER (TRUE));
2410         g_hash_table_insert (key_table, (char *) "refanyval", GINT_TO_POINTER (TRUE));
2411         g_hash_table_insert (key_table, (char *) "rem", GINT_TO_POINTER (TRUE));
2412         g_hash_table_insert (key_table, (char *) "rem.un", GINT_TO_POINTER (TRUE));
2413         g_hash_table_insert (key_table, (char *) "reqmin", GINT_TO_POINTER (TRUE));
2414         g_hash_table_insert (key_table, (char *) "reqopt", GINT_TO_POINTER (TRUE));
2415         g_hash_table_insert (key_table, (char *) "reqrefuse", GINT_TO_POINTER (TRUE));
2416         g_hash_table_insert (key_table, (char *) "reqsecobj", GINT_TO_POINTER (TRUE));
2417         g_hash_table_insert (key_table, (char *) "request", GINT_TO_POINTER (TRUE));
2418         g_hash_table_insert (key_table, (char *) "ret", GINT_TO_POINTER (TRUE));
2419         g_hash_table_insert (key_table, (char *) "rethrow", GINT_TO_POINTER (TRUE));
2420         g_hash_table_insert (key_table, (char *) "retval", GINT_TO_POINTER (TRUE));
2421         g_hash_table_insert (key_table, (char *) "rtspecialname", GINT_TO_POINTER (TRUE));
2422         g_hash_table_insert (key_table, (char *) "runtime", GINT_TO_POINTER (TRUE));
2423         g_hash_table_insert (key_table, (char *) "safearray", GINT_TO_POINTER (TRUE));
2424         g_hash_table_insert (key_table, (char *) "sealed", GINT_TO_POINTER (TRUE));
2425         g_hash_table_insert (key_table, (char *) "sequential", GINT_TO_POINTER (TRUE));
2426         g_hash_table_insert (key_table, (char *) "serializable", GINT_TO_POINTER (TRUE));
2427         g_hash_table_insert (key_table, (char *) "shl", GINT_TO_POINTER (TRUE));
2428         g_hash_table_insert (key_table, (char *) "shr", GINT_TO_POINTER (TRUE));
2429         g_hash_table_insert (key_table, (char *) "shr.un", GINT_TO_POINTER (TRUE));
2430         g_hash_table_insert (key_table, (char *) "sizeof", GINT_TO_POINTER (TRUE));
2431         g_hash_table_insert (key_table, (char *) "special", GINT_TO_POINTER (TRUE));
2432         g_hash_table_insert (key_table, (char *) "specialname", GINT_TO_POINTER (TRUE));
2433         g_hash_table_insert (key_table, (char *) "starg", GINT_TO_POINTER (TRUE));
2434         g_hash_table_insert (key_table, (char *) "starg.s", GINT_TO_POINTER (TRUE));
2435         g_hash_table_insert (key_table, (char *) "static", GINT_TO_POINTER (TRUE));
2436         g_hash_table_insert (key_table, (char *) "stdcall", GINT_TO_POINTER (TRUE));
2437         g_hash_table_insert (key_table, (char *) "stelem.i1", GINT_TO_POINTER (TRUE));
2438         g_hash_table_insert (key_table, (char *) "stelem.i2", GINT_TO_POINTER (TRUE));
2439         g_hash_table_insert (key_table, (char *) "stelem.i4", GINT_TO_POINTER (TRUE));
2440         g_hash_table_insert (key_table, (char *) "stelem.i8", GINT_TO_POINTER (TRUE));
2441         g_hash_table_insert (key_table, (char *) "stelem.i", GINT_TO_POINTER (TRUE));
2442         g_hash_table_insert (key_table, (char *) "stelem.r4", GINT_TO_POINTER (TRUE));
2443         g_hash_table_insert (key_table, (char *) "stelem.r8", GINT_TO_POINTER (TRUE));
2444         g_hash_table_insert (key_table, (char *) "stelem.ref", GINT_TO_POINTER (TRUE));
2445         g_hash_table_insert (key_table, (char *) "stfld", GINT_TO_POINTER (TRUE));
2446         g_hash_table_insert (key_table, (char *) "stind.i1", GINT_TO_POINTER (TRUE));
2447         g_hash_table_insert (key_table, (char *) "stind.i2", GINT_TO_POINTER (TRUE));
2448         g_hash_table_insert (key_table, (char *) "stind.i4", GINT_TO_POINTER (TRUE));
2449         g_hash_table_insert (key_table, (char *) "stind.i8", GINT_TO_POINTER (TRUE));
2450         g_hash_table_insert (key_table, (char *) "stind.i", GINT_TO_POINTER (TRUE));
2451         g_hash_table_insert (key_table, (char *) "stind.r4", GINT_TO_POINTER (TRUE));
2452         g_hash_table_insert (key_table, (char *) "stind.r8", GINT_TO_POINTER (TRUE));
2453         g_hash_table_insert (key_table, (char *) "storage", GINT_TO_POINTER (TRUE));
2454         g_hash_table_insert (key_table, (char *) "stored_object", GINT_TO_POINTER (TRUE));
2455         g_hash_table_insert (key_table, (char *) "streamed_object", GINT_TO_POINTER (TRUE));
2456         g_hash_table_insert (key_table, (char *) "stream", GINT_TO_POINTER (TRUE));
2457         g_hash_table_insert (key_table, (char *) "string", GINT_TO_POINTER (TRUE));
2458         g_hash_table_insert (key_table, (char *) "struct", GINT_TO_POINTER (TRUE));
2459         g_hash_table_insert (key_table, (char *) "synchronized", GINT_TO_POINTER (TRUE));
2460         g_hash_table_insert (key_table, (char *) "syschar", GINT_TO_POINTER (TRUE));
2461         g_hash_table_insert (key_table, (char *) "sysstring", GINT_TO_POINTER (TRUE));
2462         g_hash_table_insert (key_table, (char *) "tbstr", GINT_TO_POINTER (TRUE));
2463         g_hash_table_insert (key_table, (char *) "thiscall", GINT_TO_POINTER (TRUE));
2464         g_hash_table_insert (key_table, (char *) "tls", GINT_TO_POINTER (TRUE));
2465         g_hash_table_insert (key_table, (char *) "to", GINT_TO_POINTER (TRUE));
2466         g_hash_table_insert (key_table, (char *) "true", GINT_TO_POINTER (TRUE));
2467         g_hash_table_insert (key_table, (char *) "type", GINT_TO_POINTER (TRUE));
2468         g_hash_table_insert (key_table, (char *) "typedref", GINT_TO_POINTER (TRUE));
2469         g_hash_table_insert (key_table, (char *) "unicode", GINT_TO_POINTER (TRUE));
2470         g_hash_table_insert (key_table, (char *) "unmanagedexp", GINT_TO_POINTER (TRUE));
2471         g_hash_table_insert (key_table, (char *) "unmanaged", GINT_TO_POINTER (TRUE));
2472         g_hash_table_insert (key_table, (char *) "unsigned", GINT_TO_POINTER (TRUE));
2473         g_hash_table_insert (key_table, (char *) "userdefined", GINT_TO_POINTER (TRUE));
2474         g_hash_table_insert (key_table, (char *) "value", GINT_TO_POINTER (TRUE));
2475         g_hash_table_insert (key_table, (char *) "valuetype", GINT_TO_POINTER (TRUE));
2476         g_hash_table_insert (key_table, (char *) "vararg", GINT_TO_POINTER (TRUE));
2477         g_hash_table_insert (key_table, (char *) "variant", GINT_TO_POINTER (TRUE));
2478         g_hash_table_insert (key_table, (char *) "vector", GINT_TO_POINTER (TRUE));
2479         g_hash_table_insert (key_table, (char *) "virtual", GINT_TO_POINTER (TRUE));
2480         g_hash_table_insert (key_table, (char *) "void", GINT_TO_POINTER (TRUE));
2481         g_hash_table_insert (key_table, (char *) "wchar", GINT_TO_POINTER (TRUE));
2482         g_hash_table_insert (key_table, (char *) "winapi", GINT_TO_POINTER (TRUE));
2483         g_hash_table_insert (key_table, (char *) "with", GINT_TO_POINTER (TRUE));
2484 }
2485
2486 guint32
2487 method_dor_to_token (guint32 idx) {
2488         switch (idx & MONO_METHODDEFORREF_MASK) {
2489         case MONO_METHODDEFORREF_METHODDEF:
2490                 return MONO_TOKEN_METHOD_DEF | (idx >> MONO_METHODDEFORREF_BITS);
2491         case MONO_METHODDEFORREF_METHODREF:
2492                 return MONO_TOKEN_MEMBER_REF | (idx >> MONO_METHODDEFORREF_BITS);
2493         }
2494         return -1;
2495 }
2496
2497 char *
2498 get_method_override (MonoImage *m, guint32 token, MonoGenericContext *context)
2499 {
2500         MonoTableInfo *t = &m->tables [MONO_TABLE_METHODIMPL];
2501         int i;
2502
2503         for (i = 1; i <= t->rows; i++){
2504                 guint32 cols [MONO_METHODIMPL_SIZE];
2505                 guint32 decl, impl;
2506
2507                 mono_metadata_decode_row (t, i - 1, cols, MONO_METHODIMPL_SIZE);
2508
2509                 impl = method_dor_to_token (cols [MONO_METHODIMPL_BODY]);
2510                 decl = method_dor_to_token (cols [MONO_METHODIMPL_DECLARATION]);
2511
2512                 if (token == impl)
2513                         return get_method_core (m, decl, FALSE, context);
2514         }
2515
2516         return NULL;
2517 }