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