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