* get.c/get.h add method to get a methoddef from an index, simplify
[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 char *
24 get_memberref_parent (MonoImage *m, guint32 mrp_token);
25
26 char *
27 get_typedef (MonoImage *m, int idx)
28 {
29         guint32 cols [MONO_TYPEDEF_SIZE];
30         const char *ns;
31
32         mono_metadata_decode_row (&m->tables [MONO_TABLE_TYPEDEF], idx - 1, cols, MONO_TYPEDEF_SIZE);
33
34         ns = mono_metadata_string_heap (m, cols [MONO_TYPEDEF_NAMESPACE]);
35         return g_strdup_printf (
36                 "%s%s%s", ns, *ns?".":"",
37                 mono_metadata_string_heap (m, cols [MONO_TYPEDEF_NAME]));
38 }
39
40 char *
41 get_module (MonoImage *m, int idx)
42 {
43         guint32 cols [MONO_MODULE_SIZE];
44         
45         /*
46          * There MUST BE only one module in the Module table
47          */
48         g_assert (idx == 1);
49             
50         mono_metadata_decode_row (&m->tables [MONO_TABLE_MODULE], idx - 1, cols, MONO_MODULE_SIZE);
51
52         return g_strdup (mono_metadata_string_heap (m, cols [MONO_MODULE_NAME]));
53 }
54
55 char *
56 get_assemblyref (MonoImage *m, int idx)
57 {
58         guint32 cols [MONO_ASSEMBLYREF_SIZE];
59         
60         mono_metadata_decode_row (&m->tables [MONO_TABLE_ASSEMBLYREF], idx - 1, cols, MONO_ASSEMBLYREF_SIZE);
61
62         return g_strdup (mono_metadata_string_heap (m, cols [MONO_ASSEMBLYREF_NAME]));
63 }
64
65 /*
66  *
67  * Returns a string representing the ArrayShape (22.2.16).
68  */
69 static const char *
70 get_array_shape (MonoImage *m, const char *ptr, char **result)
71 {
72         GString *res = g_string_new ("[");
73         guint32 rank, num_sizes, num_lo_bounds;
74         guint32 *sizes = NULL, *lo_bounds = NULL;
75         int i, r;
76         char buffer [80];
77         
78         rank = mono_metadata_decode_value (ptr, &ptr);
79         num_sizes = mono_metadata_decode_value (ptr, &ptr);
80
81         if (num_sizes > 0)
82                 sizes = g_new (guint32, num_sizes);
83         
84         for (i = 0; i < num_sizes; i++)
85                 sizes [i] = mono_metadata_decode_value (ptr, &ptr);
86
87         num_lo_bounds = mono_metadata_decode_value (ptr, &ptr);
88         if (num_lo_bounds > 0)
89                 lo_bounds = g_new (guint32, num_lo_bounds);
90         
91         for (i = 0; i < num_lo_bounds; i++)
92                 lo_bounds [i] = mono_metadata_decode_value (ptr, &ptr);
93
94         for (r = 0; r < rank; r++){
95                 if (r < num_sizes){
96                         if (r < num_lo_bounds){
97                                 sprintf (buffer, "%d..%d", lo_bounds [r], lo_bounds [r] + sizes [r] - 1);
98                         } else {
99                                 sprintf (buffer, "0..%d", sizes [r] - 1);
100                         }
101                 } else
102                         buffer [0] = 0;
103                 
104                 g_string_append (res, buffer);
105                 if ((r + 1) != rank)
106                         g_string_append (res, ", ");
107         }
108         g_string_append (res, "]");
109         
110         if (sizes)
111                 g_free (sizes);
112
113         if (lo_bounds)
114                 g_free (lo_bounds);
115
116         *result = res->str;
117         g_string_free (res, FALSE);
118
119         return ptr;
120 }
121
122 /**
123  * get_typespec:
124  * @m: metadata context
125  * @blob_idx: index into the blob heap
126  *
127  * Returns the stringified representation of a TypeSpec signature (22.2.17)
128  */
129 char *
130 get_typespec (MonoImage *m, guint32 idx)
131 {
132         guint32 cols [MONO_TYPESPEC_SIZE];
133         const char *ptr;
134         char *s, *result;
135         GString *res = g_string_new ("");
136         int len;
137
138         mono_metadata_decode_row (&m->tables [MONO_TABLE_TYPESPEC], idx-1, cols, MONO_TYPESPEC_SIZE);
139         ptr = mono_metadata_blob_heap (m, cols [MONO_TYPESPEC_SIGNATURE]);
140         len = mono_metadata_decode_value (ptr, &ptr);
141         
142         switch (*ptr++){
143         case MONO_TYPE_PTR:
144                 ptr = get_custom_mod (m, ptr, &s);
145                 if (s){
146                         g_string_append (res, s);
147                         g_string_append_c (res, ' ');
148                         g_free (s);
149                 }
150                 
151                 if (*ptr == MONO_TYPE_VOID)
152                         g_string_append (res, "void");
153                 else {
154                         ptr = get_type (m, ptr, &s);
155                         if (s)
156                                 g_string_append (res, s);
157                 }
158                 break;
159                 
160         case MONO_TYPE_FNPTR:
161                 g_string_append (res, "FNPTR ");
162                 /*
163                  * we assume MethodRefSig, as we do not know
164                  * whether it is a MethodDefSig or a MethodRefSig.
165                  */
166                 printf ("\n FNPTR:\n");
167                 
168                 hex_dump (ptr, 0, 40);
169                 break;
170                         
171         case MONO_TYPE_ARRAY:
172                 ptr = get_type (m, ptr, &s);
173                 g_string_append (res, s);
174                 g_free (s);
175                 g_string_append_c (res, ' ');
176                 ptr = get_array_shape (m, ptr, &s);
177                 g_string_append (res, s);
178                 g_free (s);
179                 break;
180                 
181         case MONO_TYPE_SZARRAY:
182                 ptr = get_custom_mod (m, ptr, &s);
183                 if (s){
184                         g_string_append (res, s);
185                         g_string_append_c (res, ' ');
186                         g_free (s);
187                 }
188                 ptr = get_type (m, ptr, &s);
189                 g_string_append (res, s);
190                 g_string_append (res, "[]");
191                 g_free (s);
192         }
193
194         result = res->str;
195         g_string_free (res, FALSE);
196
197         return result;
198 }
199
200 char *
201 get_typeref (MonoImage *m, int idx)
202 {
203         guint32 cols [MONO_TYPEREF_SIZE];
204         const char *s, *t;
205         char *x, *ret;
206         guint32 rs_idx, table;
207         
208         mono_metadata_decode_row (&m->tables [MONO_TABLE_TYPEREF], idx - 1, cols, MONO_TYPEREF_SIZE);
209
210         t = mono_metadata_string_heap (m, cols [MONO_TYPEREF_NAME]);
211         s = mono_metadata_string_heap (m, cols [MONO_TYPEREF_NAMESPACE]);
212
213         rs_idx = cols [MONO_TYPEREF_SCOPE] >> RESOLTION_SCOPE_BITS;
214         table = cols [MONO_TYPEREF_SCOPE] & RESOLTION_SCOPE_MASK;
215         
216         switch (table){
217         case RESOLTION_SCOPE_MODULE: /* Module */
218                 x = get_module (m, rs_idx);
219                 ret = g_strdup_printf ("[%s] %s%s%s", x, s, *s?".":"", t);
220                 g_free (x);
221                 break;
222
223         case RESOLTION_SCOPE_MODULEREF: /* ModuleRef */
224                 ret = g_strdup_printf ("TODO:TypeRef-ModuleRef (%s.%s)", s, t);
225                 break;
226                               
227         case RESOLTION_SCOPE_ASSEMBLYREF: /*
228                  * AssemblyRef (ECMA docs claim it is 3, but it looks to
229                  * me like it is 2 (tokens are prefixed with 0x23)
230                  */
231                 x = get_assemblyref (m, rs_idx);
232                 ret = g_strdup_printf ("[%s]%s%s%s", x, s, *s?".":"", t);
233                 g_free (x);
234                 break;
235                 
236         case RESOLTION_SCOPE_TYPEREF: /* TypeRef */
237                 x = get_typeref (m, rs_idx);
238                 ret =  g_strdup_printf ("%s/%s", x, t);
239                 g_free (x);
240                 break;
241                 
242         default:
243                 ret = g_strdup_printf ("Unknown table in TypeRef %d", table);
244         }
245
246         return ret;
247 }
248
249 /**
250  * get_typedef_or_ref:
251  * @m: metadata context
252  * @dor_token: def or ref encoded index
253  *
254  * Low two bits contain table to lookup from
255  * high bits contain the index into the def or ref table
256  *
257  * Returns: a stringified version of the MethodDef or MethodRef
258  * at (dor_token >> 2) 
259  */
260 char *
261 get_typedef_or_ref (MonoImage *m, guint32 dor_token)
262 {
263         char *temp = NULL, *s;
264         int table, idx;
265
266         /*
267          * low 2 bits contain encoding
268          */
269         table = dor_token & 0x03;
270         idx = dor_token >> 2;
271         
272         switch (table){
273         case 0: /* TypeDef */
274                 temp = get_typedef (m, idx);
275                 s = g_strdup_printf ("%s", temp);
276                 break;
277                 
278         case 1: /* TypeRef */
279                 temp = get_typeref (m, idx);
280                 s = g_strdup_printf ("%s", temp);
281                 break;
282                 
283         case 2: /* TypeSpec */
284                 s = get_typespec (m, idx);
285                 break;
286
287         default:
288                 g_error ("Unhandled encoding for typedef-or-ref coded index 0x%08x", dor_token);
289
290         }
291         
292         if (temp)
293                 g_free (temp);
294
295         return s;
296 }
297
298 /**
299  * get_type_or_methdef
300  * @m: metadata context
301  * @dor_token: type or method def encoded index
302  *
303  * Low bit contains the table to lookup from
304  * high bits contain the index into the type def or method def table
305  *
306  * Returns: a stringified version of the TypeOrMethodDef token
307  */
308 char *
309 get_type_or_methdef (MonoImage *m, guint32 dor_token)
310 {
311         if (dor_token & 0x01) /* MethodDef */
312                 return get_methoddef (m, dor_token >> 1);
313         else  /* TypeDef */
314                 return get_typedef (m, dor_token >> 1);
315 }
316
317 /** 
318  * get_encoded_typedef_or_ref:
319  * @m: metadata context 
320  * @ptr: location to decode from.
321  * @result: pointer to string where resulting decoded string is stored
322  *
323  * result will point to a g_malloc()ed string.
324  *
325  * Returns: the new ptr to continue decoding
326  */
327 const char *
328 get_encoded_typedef_or_ref (MonoImage *m, const char *ptr, char **result)
329 {
330         guint32 token;
331         
332         token = mono_metadata_decode_value (ptr, &ptr);
333
334         *result = get_typedef_or_ref (m, token);
335
336         return ptr;
337 }
338
339 /**
340  * get_custom_mod:
341  *
342  * Decodes a CustomMod (22.2.7)
343  *
344  * Returns: updated pointer location
345  */
346 const char *
347 get_custom_mod (MonoImage *m, const char *ptr, char **return_value)
348 {
349         char *s;
350         const char *reqd;
351         
352         *return_value = NULL;
353         while ((*ptr == MONO_TYPE_CMOD_OPT) ||
354                    (*ptr == MONO_TYPE_CMOD_REQD)) {
355                 reqd = (*ptr == MONO_TYPE_CMOD_REQD) ? "reqd" : "opt";
356                 ptr++;
357                 ptr = get_encoded_typedef_or_ref (m, ptr, &s);
358
359                 if (*return_value == NULL)
360                         *return_value = g_strconcat (reqd, " ", s, NULL);
361                 else
362                         *return_value = g_strconcat (*return_value, " ", reqd, " ", s, NULL);
363                 g_free (s);
364         }
365         return ptr;
366 }
367
368
369 static map_t element_type_map [] = {
370         { MONO_TYPE_END        , "end" },
371         { MONO_TYPE_VOID       , "void" },
372         { MONO_TYPE_BOOLEAN    , "bool" },
373         { MONO_TYPE_CHAR       , "char" }, 
374         { MONO_TYPE_I1         , "int8" },
375         { MONO_TYPE_U1         , "unsigned int8" }, 
376         { MONO_TYPE_I2         , "int16" },
377         { MONO_TYPE_U2         , "unsigned int16" },
378         { MONO_TYPE_I4         , "int32" },
379         { MONO_TYPE_U4         , "unsigned int32" },
380         { MONO_TYPE_I8         , "int64" },
381         { MONO_TYPE_U8         , "unsigned int64" },
382         { MONO_TYPE_R4         , "float32" },
383         { MONO_TYPE_R8         , "float64" },
384         { MONO_TYPE_STRING     , "string" },
385         { MONO_TYPE_TYPEDBYREF , "TypedByRef" },
386         { MONO_TYPE_I          , "native int" },
387         { MONO_TYPE_U          , "native unsigned int" },
388         { MONO_TYPE_OBJECT     , "object" },
389         { 0, NULL }
390 };
391
392 static map_t call_conv_type_map [] = {
393         { MONO_CALL_DEFAULT     , "default" },
394         { MONO_CALL_C           , "c" },
395         { MONO_CALL_STDCALL     , "stdcall" },
396         { MONO_CALL_THISCALL    , "thiscall" },
397         { MONO_CALL_FASTCALL    , "fastcall" },
398         { MONO_CALL_VARARG      , "vararg" },
399         { 0, NULL }
400 };
401
402 char*
403 dis_stringify_token (MonoImage *m, guint32 token)
404 {
405         guint idx = token & 0xffffff;
406         switch (token >> 24) {
407         case MONO_TABLE_TYPEDEF: return get_typedef (m, idx);
408         case MONO_TABLE_TYPEREF: return get_typeref (m, idx);
409         case MONO_TABLE_TYPESPEC: return get_typespec (m, idx);
410         default:
411                  break;
412         }
413         return g_strdup_printf("0x%08x", token);
414 }
415
416 char*
417 dis_stringify_array (MonoImage *m, MonoArrayType *array) 
418 {
419         char *type;
420         GString *s = g_string_new("");
421         int i;
422         
423         type = dis_stringify_type (m, &array->eklass->byval_arg);
424         g_string_append (s, type);
425         g_free (type);
426         g_string_append_c (s, '[');
427         for (i = 0; i < array->rank; ++i) {
428                 if (i)
429                         g_string_append_c (s, ',');
430                 if (i < array->numsizes) {
431                         if (i < array->numlobounds && array->lobounds[i] != 0)
432                                 g_string_sprintfa (s, "%d..%d", array->lobounds[i], array->sizes[i]);
433                         else
434                                 g_string_sprintfa (s, "%d", array->sizes[i]);
435                 }
436         }
437         g_string_append_c (s, ']');
438         type = s->str;
439         g_string_free (s, FALSE);
440         return type;
441 }
442
443 char*
444 dis_stringify_modifiers (MonoImage *m, int n, MonoCustomMod *mod)
445 {
446         GString *s = g_string_new("");
447         char *result;
448         int i;
449         for (i = 0; i < n; ++i) {
450                 char *tok = dis_stringify_token (m, mod[i].token);
451                 if (i > 0)
452                         g_string_sprintfa (s, " ");
453                 g_string_sprintfa (s, "%s (%s)", mod[i].required ? "modopt": "modreq", tok);
454                 g_free (tok);
455         }
456         g_string_append_c (s, ' ');
457         result = s->str;
458         g_string_free (s, FALSE);
459         return result;
460 }
461
462 char*
463 dis_stringify_param (MonoImage *m, MonoType *param) 
464 {
465         char *t;
466         char *result;
467         const char *out = param->attrs & 2 ? "[out] ": "";
468         t = dis_stringify_type (m, param);
469         result = g_strconcat (out, t, NULL);
470         g_free (t);
471         return result;
472 }
473
474 char*
475 dis_stringify_method_signature (MonoImage *m, MonoMethodSignature *method, int methoddef_row, gboolean fully_qualified)
476 {
477         guint32 cols [MONO_METHOD_SIZE];
478         guint32 pcols [MONO_PARAM_SIZE];
479         guint32 param_index = 0;
480         const char *name = "";
481         int free_method = 0;
482         char *retval;
483         char *type = NULL;
484         GString *result = g_string_new ("");
485         int i;
486
487         g_assert (method || methoddef_row);
488
489         if (methoddef_row) {
490                 mono_metadata_decode_row (&m->tables [MONO_TABLE_METHOD], methoddef_row -1, cols, MONO_METHOD_SIZE);
491                 if (fully_qualified)
492                         type = get_typedef (m, mono_metadata_typedef_from_method (m, methoddef_row));
493                 name = mono_metadata_string_heap (m, cols [MONO_METHOD_NAME]);
494                 param_index = cols [MONO_METHOD_PARAMLIST];
495                 if (!method) {
496                         const char *sig = mono_metadata_blob_heap (m, cols [MONO_METHOD_SIGNATURE]);
497                         mono_metadata_decode_blob_size (sig, &sig);
498                         method = mono_metadata_parse_method_signature (m, methoddef_row, sig, &sig);
499                         free_method = 1;
500                 }
501         }
502         
503         retval = dis_stringify_param (m, method->ret);
504         if (method->hasthis)
505                 g_string_append (result, "instance ");
506         g_string_append (result, map (method->call_convention, call_conv_type_map));
507         g_string_sprintfa (result, " %s ", retval);
508         if (type)
509                 g_string_sprintfa (result, "%s::", type);
510         g_string_sprintfa (result, "%s(", name);
511         g_free (retval);
512         for (i = 0; i < method->param_count; ++i) {
513                 if (param_index && param_index <= m->tables [MONO_TABLE_PARAM].rows) {
514                         mono_metadata_decode_row (&m->tables [MONO_TABLE_PARAM], param_index - 1, pcols, MONO_PARAM_SIZE);
515                         name = mono_metadata_string_heap (m, pcols [MONO_PARAM_NAME]);
516                         method->params [i]->attrs = pcols [MONO_PARAM_FLAGS];
517                         param_index++;
518                 } else {
519                         name = "";
520                 }
521                 if (i)
522                         g_string_append (result, ", ");
523                 retval = dis_stringify_param (m, method->params [i]);
524                 g_string_sprintfa (result, "%s '%s'", retval, name);
525                 g_free (retval);
526         }
527         g_string_append (result, ") ");
528
529         if (free_method)
530                 mono_metadata_free_method_signature (method);
531         retval = result->str;
532         g_string_free (result, FALSE);
533
534         return retval;
535 }
536
537 static char *
538 dis_stringify_object_with_class (MonoImage *m, MonoClass *c)
539 {
540         /* FIXME: handle MONO_TYPE_OBJECT ... */
541         const char *otype = c->byval_arg.type == MONO_TYPE_CLASS? "class" : "valuetype";
542         char *assemblyref = NULL, *result;
543         if (m != c->image) {
544                 if (c->image->assembly_name) {
545                         /* we cheat */
546                         if (substitute_with_mscorlib_p && !strcmp ("corlib", c->image->assembly_name))
547                                 assemblyref = g_strdup_printf ("[%s]", "mscorlib");
548                         else
549                                 assemblyref = g_strdup_printf ("[%s]", c->image->assembly->aname.name);
550                 } else {
551                         assemblyref = g_strdup_printf ("[.module %s]", c->image->module_name);
552                 }
553         }
554         result = g_strdup_printf ("%s %s%s%s%s", otype, assemblyref?assemblyref:"", c->name_space, 
555                                 *c->name_space?".":"", c->name);
556         g_free (assemblyref);
557         return result;
558 }
559
560 static char *
561 dis_stringify_object (MonoImage *m, MonoType *type)
562 {
563         MonoClass *c = mono_class_from_mono_type (type);
564         return dis_stringify_object_with_class (m, c);
565 }
566
567 char*
568 dis_stringify_type (MonoImage *m, MonoType *type)
569 {
570         const char *pinned = "", *byref = "";
571         char *bare = NULL, *mods = NULL;
572         char *result;
573
574         if (type->num_mods)
575                 mods = dis_stringify_modifiers (m, type->num_mods, type->modifiers);
576
577         switch (type->type){
578         case MONO_TYPE_BOOLEAN:
579         case MONO_TYPE_CHAR:
580         case MONO_TYPE_I1:
581         case MONO_TYPE_U1:
582         case MONO_TYPE_I2:
583         case MONO_TYPE_U2:
584         case MONO_TYPE_I4:
585         case MONO_TYPE_U4:
586         case MONO_TYPE_I8:
587         case MONO_TYPE_U8:
588         case MONO_TYPE_R4:
589         case MONO_TYPE_R8:
590         case MONO_TYPE_I:
591         case MONO_TYPE_U:
592         case MONO_TYPE_STRING:
593         case MONO_TYPE_OBJECT:
594         case MONO_TYPE_TYPEDBYREF:
595                 bare = g_strdup (map (type->type, element_type_map));
596                 break;
597                 
598         case MONO_TYPE_VALUETYPE:
599         case MONO_TYPE_CLASS:
600                 bare = dis_stringify_object (m, type);
601                 break;
602                 
603         case MONO_TYPE_FNPTR:
604                 bare = dis_stringify_method_signature (m, type->data.method, 0, FALSE);
605                 break;
606         case MONO_TYPE_PTR: {
607                 char *child_type;
608                 child_type = dis_stringify_type (m, type->data.type);
609                 
610                 bare = g_strdup_printf ("%s*", child_type);
611                 g_free (child_type);
612                 break;
613         }
614         case MONO_TYPE_SZARRAY: {
615                 char *child_type;
616                 child_type = dis_stringify_type (m, &type->data.klass->byval_arg);
617                 
618                 bare = g_strdup_printf ("%s[]", child_type);
619                 g_free (child_type);
620                 break;
621         }
622         case MONO_TYPE_ARRAY:
623                 bare = dis_stringify_array (m, type->data.array);
624                 break;
625         case MONO_TYPE_VOID:
626                 bare = g_strdup ("void");
627                 break;
628         case MONO_TYPE_MVAR:
629                 bare = g_strdup_printf ("!!%d", type->data.generic_param->num);
630                 break;
631         case MONO_TYPE_VAR:
632                 bare = g_strdup_printf ("!%d", type->data.generic_param->num);
633                 break;
634         case MONO_TYPE_GENERICINST: {
635                 GString *str = g_string_new ("");
636                 int i;
637                 char *generic_type = dis_stringify_type (m, type->data.generic_inst->generic_type);
638
639                 for (i = 0; i < type->data.generic_inst->type_argc; i++){
640                         char *t = dis_stringify_type (m, type->data.generic_inst->type_argv [i]);
641
642                         g_string_append (str, t);
643                         if (i+1 != type->data.generic_inst->type_argc)
644                                 g_string_append (str, ", ");
645                         g_free (t);
646                 }
647                 bare = g_strdup_printf ("%s<%s>", generic_type, str->str);
648                 g_string_free (str, TRUE);
649                 break;
650         }
651                 
652         default:
653                 g_error ("Do not know how to stringify type 0x%x", type->type);
654         }
655         
656         if (type->pinned)
657                 pinned = " pinned";
658
659         if (type->byref)
660                 byref = "&";
661                 
662         result = g_strconcat (mods ? mods : "", bare, byref, pinned, NULL);
663
664         g_free (bare);
665
666         return result;
667 }
668
669 /**
670  * get_type:
671  * @m: metadata context 
672  * @ptr: location to decode from.
673  * @result: pointer to string where resulting decoded string is stored
674  *
675  * This routine returs in @result the stringified type pointed by @ptr.
676  * (22.2.12)
677  *
678  * Returns: the new ptr to continue decoding
679  */
680 const char *
681 get_type (MonoImage *m, const char *ptr, char **result)
682 {
683         MonoType *type = mono_metadata_parse_type (m, MONO_PARSE_TYPE, 0, ptr, &ptr);
684         *result = dis_stringify_type (m, type);
685         mono_metadata_free_type (type);
686         return ptr;
687 }
688
689 /**
690  * 
691  * Returns a stringified representation of a FieldSig (22.2.4)
692  */
693 char *
694 get_field_signature (MonoImage *m, guint32 blob_signature)
695 {
696         char *allocated_modifier_string, *allocated_type_string;
697         const char *ptr = mono_metadata_blob_heap (m, blob_signature);
698         const char *base;
699         char *res;
700         int len;
701         
702         len = mono_metadata_decode_value (ptr, &ptr);
703         base = ptr;
704         /* FIELD is 0x06 */
705         g_assert (*ptr == 0x06);
706 /*      hex_dump (ptr, 0, len); */
707         ptr++; len--;
708         
709         ptr = get_custom_mod (m, ptr, &allocated_modifier_string);
710         ptr = get_type (m, ptr, &allocated_type_string);
711
712         res = g_strdup_printf (
713                 "%s %s",
714                 allocated_modifier_string ? allocated_modifier_string : "",
715                 allocated_type_string);
716         
717         if (allocated_modifier_string)
718                 g_free (allocated_modifier_string);
719         if (allocated_type_string)
720                 g_free (allocated_type_string);
721         
722         return res;
723 }
724
725 MonoTypeEnum
726 get_field_literal_type (MonoImage *m, guint32 blob_signature)
727 {
728         const char *ptr = mono_metadata_blob_heap (m, blob_signature);
729         int len;
730         char *allocated_modifier_string;
731         
732         len = mono_metadata_decode_value (ptr, &ptr);
733
734         /* FIELD is 0x06 */
735         g_assert (*ptr == 0x06);
736         ptr++; len--;
737         
738         ptr = get_custom_mod (m, ptr, &allocated_modifier_string);
739         if (allocated_modifier_string)
740                 g_free (allocated_modifier_string);
741
742         return (MonoTypeEnum) *ptr;
743         
744 }
745
746 /**
747  * decode_literal:
748  * @m: metadata context
749  * @token: token to decode
750  *
751  * decodes the literal indexed by @token.
752  */
753 char *
754 decode_literal (MonoImage *m, guint32 token)
755 {
756         return g_strdup ("LITERAL_VALUE");
757 }
758
759 /**
760  * get_ret_type:
761  * @m: metadata context 
762  * @ptr: location to decode from.
763  * @result: pointer to string where resulting decoded string is stored
764  *
765  * This routine returns in @result the stringified RetType (22.2.11)
766  *
767  * Returns: the new ptr to continue decoding.
768  */
769 const char *
770 get_ret_type (MonoImage *m, const char *ptr, char **ret_type)
771 {
772         GString *str = g_string_new ("");
773         char *mod = NULL;
774         char *allocated_type_string;
775         
776         ptr = get_custom_mod (m, ptr, &mod);
777         if (mod){
778                 g_string_append (str, mod);
779                 g_string_append_c (str, ' ');
780                 g_free (mod);
781         }
782
783         if (*ptr == MONO_TYPE_TYPEDBYREF){
784                 /* TODO: what does `typedbyref' mean? */
785                 g_string_append (str, "/* FIXME: What does this mean? */ typedbyref ");
786                 ptr++;
787         } else if (*ptr == MONO_TYPE_VOID){
788                  g_string_append (str, "void");
789                  ptr++;
790         } else {
791                 if (*ptr == MONO_TYPE_BYREF){
792                         g_string_append (str, "[out] ");
793                         ptr++;
794                 }
795
796                 ptr = get_type (m, ptr, &allocated_type_string);
797                 g_string_append (str, allocated_type_string);
798                 g_free (allocated_type_string);
799         }
800
801         *ret_type = str->str;
802         g_string_free (str, FALSE);
803
804         return ptr;
805 }
806
807 /**
808  * get_param:
809  * @m: metadata context 
810  * @ptr: location to decode from.
811  * @result: pointer to string where resulting decoded string is stored
812  *
813  * This routine returns in @result the stringified Param (22.2.10)
814  *
815  * Returns: the new ptr to continue decoding.
816  */
817 const char *
818 get_param (MonoImage *m, const char *ptr, char **retval)
819 {
820         GString *str = g_string_new ("");
821         char *allocated_mod_string, *allocated_type_string;
822         
823         ptr = get_custom_mod (m, ptr, &allocated_mod_string);
824         if (allocated_mod_string){
825                 g_string_append (str, allocated_mod_string);
826                 g_string_append_c (str, ' ');
827                 g_free (allocated_mod_string);
828         }
829         
830         if (*ptr == MONO_TYPE_TYPEDBYREF){
831                 g_string_append (str, " typedbyref ");
832                 ptr++;
833         } else {
834                  if (*ptr == MONO_TYPE_BYREF){
835                         g_string_append (str, "[out] ");
836                         ptr++;
837                 }
838                 ptr = get_type (m, ptr, &allocated_type_string);
839                 g_string_append (str, allocated_type_string);
840                 g_free (allocated_type_string);
841         }
842
843         *retval = str->str;
844         g_string_free (str, FALSE);
845         return ptr;
846 }
847
848 static map_t param_map [] = {
849         { PARAM_ATTRIBUTE_IN,                "[in] " },
850         { PARAM_ATTRIBUTE_OUT,               "[out] " },
851         { PARAM_ATTRIBUTE_OPTIONAL,          "optional " },
852         { PARAM_ATTRIBUTE_HAS_DEFAULT,       "hasdefault " },
853         { PARAM_ATTRIBUTE_HAS_FIELD_MARSHAL, "fieldmarshal " },
854         { 0, NULL }
855 };
856
857 char *
858 param_flags (guint32 f)
859 {
860         return g_strdup (flags (f, param_map));
861 }
862
863 static map_t field_access_map [] = {
864         { FIELD_ATTRIBUTE_COMPILER_CONTROLLED, "compilercontrolled " },
865         { FIELD_ATTRIBUTE_PRIVATE,             "private " },
866         { FIELD_ATTRIBUTE_FAM_AND_ASSEM,       "famandassem " },
867         { FIELD_ATTRIBUTE_ASSEMBLY,            "assembly " },
868         { FIELD_ATTRIBUTE_FAMILY,              "family " },
869         { FIELD_ATTRIBUTE_FAM_OR_ASSEM,        "famorassem " },
870         { FIELD_ATTRIBUTE_PUBLIC,              "public " },
871         { 0, NULL }
872 };
873
874 static map_t field_flags_map [] = {
875         { FIELD_ATTRIBUTE_STATIC,              "static " },
876         { FIELD_ATTRIBUTE_INIT_ONLY,           "initonly " },
877         { FIELD_ATTRIBUTE_LITERAL,             "literal " },
878         { FIELD_ATTRIBUTE_NOT_SERIALIZED,      "notserialized " },
879         { FIELD_ATTRIBUTE_SPECIAL_NAME,        "specialname " },
880         { FIELD_ATTRIBUTE_PINVOKE_IMPL,        "FIXME:pinvokeimpl " },
881         { FIELD_ATTRIBUTE_RT_SPECIAL_NAME,        "rtspecialname " },
882         { FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL,        "hasfieldmarshal " },
883         { FIELD_ATTRIBUTE_HAS_DEFAULT,        "hasdefault " },
884         { FIELD_ATTRIBUTE_HAS_FIELD_RVA,        "hasfieldrva " },
885         { 0, NULL }
886 };
887
888 /**
889  * field_flags:
890  *
891  * Returns a stringified version of a Field's flags
892  */
893 char *
894 field_flags (guint32 f)
895 {
896         char buffer [1024];
897         int access = f & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK;
898         
899         buffer [0] = 0;
900
901         strcat (buffer, map (access, field_access_map));
902         strcat (buffer, flags (f, field_flags_map));
903         return g_strdup (buffer);
904 }
905
906 /**
907  * Returns a stringifed representation of a MethodRefSig (22.2.2)
908  */
909 char *
910 get_methodref_signature (MonoImage *m, guint32 blob_signature, const char *fancy_name)
911 {
912         GString *res = g_string_new ("");
913         const char *ptr = mono_metadata_blob_heap (m, blob_signature);
914         char *allocated_ret_type, *s;
915         gboolean seen_vararg = 0;
916         int param_count, signature_len;
917         int i, gen_count = 0;
918         int cconv;
919         
920         signature_len = mono_metadata_decode_value (ptr, &ptr);
921
922         if (*ptr & 0x20){
923                 if (*ptr & 0x40)
924                         g_string_append (res, "explicit-this ");
925                 else
926                         g_string_append (res, "instance "); /* has-this */
927         }
928
929         if (*ptr & 0x05)
930                 seen_vararg = 1;
931         if (*ptr & 0x10)
932                 gen_count = 1;
933         cconv = *ptr & 0x0f;
934         ptr++;
935         if (gen_count)
936                 gen_count = mono_metadata_decode_value (ptr, &ptr);
937         param_count = mono_metadata_decode_value (ptr, &ptr);
938         if (cconv != 0xa) {
939                 ptr = get_ret_type (m, ptr, &allocated_ret_type);
940                 g_string_append (res, allocated_ret_type);
941                 g_free (allocated_ret_type);
942         }
943
944         if (fancy_name){
945                 g_string_append_c (res, ' ');
946                 g_string_append (res, fancy_name);
947         }
948         
949         g_string_append (res, "(");
950         
951         /*
952          * param_count describes parameters *before* and *after*
953          * the vararg sentinel
954          */
955         for (i = 0; i < param_count; i++){
956                 char *param = NULL;
957                 
958                 /*
959                  * If ptr is a SENTINEL
960                  */
961                 if (*ptr == 0x41){
962                         g_string_append (res, " varargs ");
963                         continue;
964                 }
965
966                 ptr = get_param (m, ptr, &param);
967                 g_string_append (res, param);
968                 if (i+1 != param_count)
969                         g_string_append (res, ", ");
970                 g_free (param);
971         }
972         g_string_append (res, ")");
973         
974         /*
975          * cleanup and return
976          */
977         s = res->str;
978         g_string_free (res, FALSE);
979         return s;
980 }
981
982 /**
983  * Returns a stringifed representation of a field ref
984  */
985 char *
986 get_fieldref_signature (MonoImage *m, int idx)
987 {
988         guint32 cols [MONO_MEMBERREF_SIZE];
989         char *sig;
990         char *full_sig;
991
992         mono_metadata_decode_row (&m->tables [MONO_TABLE_MEMBERREF],
993                         idx - 1, cols, MONO_MEMBERREF_SIZE);
994
995         sig = get_field_signature (m, cols [MONO_FIELD_SIGNATURE]);
996         full_sig = g_strdup_printf ("%s %s::%s", sig,
997                         get_memberref_parent (m, cols [MONO_MEMBERREF_CLASS]),
998                         mono_metadata_string_heap (m, cols [MONO_MEMBERREF_NAME]));
999         g_free (sig);
1000         
1001         return full_sig;
1002 }
1003
1004 /**
1005  * get_field:
1006  * @m: metadata context
1007  * @token: a FIELD_DEF token
1008  *
1009  * This routine has to locate the TypeDef that "owns" this Field.
1010  * Since there is no backpointer in the Field table, we have to scan
1011  * the TypeDef table and locate the actual "owner" of the field
1012  */
1013 char *
1014 get_field (MonoImage *m, guint32 token)
1015 {
1016         int idx = mono_metadata_token_index (token);
1017         guint32 cols [MONO_FIELD_SIZE];
1018         char *sig, *res, *type;
1019         guint32 type_idx;
1020
1021         /*
1022          * We can get here also with a MenberRef token (for a field
1023          * defined in another module/assembly, just like in get_method ()
1024          */
1025         if (mono_metadata_token_code (token) == MONO_TOKEN_MEMBER_REF) {
1026                 return get_fieldref_signature (m, idx);
1027         }
1028         g_assert (mono_metadata_token_code (token) == MONO_TOKEN_FIELD_DEF);
1029
1030         mono_metadata_decode_row (&m->tables [MONO_TABLE_FIELD], idx - 1, cols, MONO_FIELD_SIZE);
1031         sig = get_field_signature (m, cols [MONO_FIELD_SIGNATURE]);
1032
1033         /*
1034          * To locate the actual "container" for this field, we have to scan
1035          * the TypeDef table.  LAME!
1036          */
1037         type_idx = mono_metadata_typedef_from_field (m, idx);
1038
1039         type = get_typedef (m, type_idx);
1040         res = g_strdup_printf ("%s %s::%s",
1041                                sig, type,
1042                                mono_metadata_string_heap (m, cols [MONO_FIELD_NAME]));
1043         g_free (type);
1044         g_free (sig);
1045
1046         return res;
1047 }
1048
1049 static char *
1050 get_memberref_parent (MonoImage *m, guint32 mrp_token)
1051 {
1052         /*
1053          * mrp_index is a MemberRefParent coded index
1054          */
1055         guint32 table = mrp_token & 7;
1056         guint32 idx = mrp_token >> 3;
1057
1058         switch (table){
1059         case 0: /* TypeDef */
1060                 return get_typedef (m, idx);
1061                 
1062         case 1: /* TypeRef */
1063                 return get_typeref (m, idx);
1064                 
1065         case 2: /* ModuleRef */
1066                 return g_strdup_printf ("TODO:MemberRefParent-ModuleRef");
1067                 
1068         case 3: /* MethodDef */
1069                 return g_strdup ("TODO:MethodDef");
1070                 
1071         case 4: /* TypeSpec */
1072                 return get_typespec (m, idx);
1073         }
1074         g_assert_not_reached ();
1075         return NULL;
1076 }
1077
1078 /**
1079  * get_method:
1080  * @m: metadata context
1081  * @token: a METHOD_DEF or MEMBER_REF token
1082  *
1083  * This routine has to locate the TypeDef that "owns" this Field.
1084  * Since there is no backpointer in the Field table, we have to scan
1085  * the TypeDef table and locate the actual "owner" of the field
1086  */
1087 char *
1088 get_method (MonoImage *m, guint32 token)
1089 {
1090         int idx = mono_metadata_token_index (token);
1091         guint32 member_cols [MONO_MEMBERREF_SIZE], method_cols [MONO_METHOD_SIZE];
1092         char *sig;
1093         const char *name;
1094
1095         MonoMethod *mh;
1096
1097         mh = mono_get_method (m, token, NULL);
1098         if (mh) {
1099                 sig = dis_stringify_object_with_class (m, mh->klass);
1100                 name = g_strdup_printf ("%s::%s", sig, mh->name);
1101                 g_free (sig);
1102         } else
1103                 name = NULL;
1104
1105         switch (mono_metadata_token_code (token)){
1106         case MONO_TOKEN_METHOD_DEF:
1107                 mono_metadata_decode_row (&m->tables [MONO_TABLE_METHOD], 
1108                                           idx - 1, method_cols, MONO_METHOD_SIZE);
1109
1110                 sig = get_methodref_signature (m, method_cols [MONO_METHOD_SIGNATURE], name);
1111                 return sig;
1112                 
1113         case MONO_TOKEN_MEMBER_REF: {
1114                 mono_metadata_decode_row (&m->tables [MONO_TABLE_MEMBERREF],
1115                                           idx - 1, member_cols, MONO_MEMBERREF_SIZE);
1116                 if (!name)
1117                         name = g_strdup_printf ("%s::%s",
1118                                         get_memberref_parent (m, member_cols [MONO_MEMBERREF_CLASS]),
1119                                         mono_metadata_string_heap (m, member_cols [MONO_MEMBERREF_NAME]));
1120                 sig = get_methodref_signature (
1121                         m, member_cols [MONO_MEMBERREF_SIGNATURE], name);
1122                 return sig;
1123         }
1124         case MONO_TOKEN_METHOD_SPEC: {
1125                 mono_metadata_decode_row (&m->tables [MONO_TABLE_METHODSPEC], idx - 1, member_cols, MONO_METHODSPEC_SIZE);
1126                 token = member_cols [MONO_METHODSPEC_METHOD];
1127                 if ((token & METHODDEFORREF_MASK) == METHODDEFORREF_METHODDEF)
1128                         token = MONO_TOKEN_METHOD_DEF | (token >> METHODDEFORREF_BITS);
1129                 else
1130                         token = MONO_TOKEN_MEMBER_REF | (token >> METHODDEFORREF_BITS);
1131                 return get_method (m, token);
1132
1133         }
1134
1135         default:
1136                 g_assert_not_reached ();
1137         }
1138         g_assert_not_reached ();
1139         return NULL;
1140 }
1141
1142 /**
1143  * get_methoddef
1144  * @m: metadata context
1145  * @idx: index into the method table
1146  *
1147  * Returns: A stringified version of the method signature.
1148  */
1149 char *
1150 get_methoddef (MonoImage *m, guint32 idx)
1151 {
1152         guint32 cols [MONO_METHOD_SIZE];
1153         char *sig;
1154         const char *name;
1155
1156         MonoMethod *mh;
1157
1158         mh = mono_get_method (m, MONO_TOKEN_METHOD_DEF | idx, NULL);
1159         if (mh) {
1160                 sig = dis_stringify_object_with_class (m, mh->klass);
1161                 name = g_strdup_printf ("%s::%s", sig, mh->name);
1162                 g_free (sig);
1163         } else
1164                 name = NULL;
1165         mono_metadata_decode_row (&m->tables [MONO_TABLE_METHOD], 
1166                         idx - 1, cols, MONO_METHOD_SIZE);
1167         sig = get_methodref_signature (m, cols [MONO_METHOD_SIGNATURE], name);
1168         
1169         return sig;
1170 }
1171
1172 /**
1173  * get_constant:
1174  * @m: metadata context
1175  * @blob_index: index into the blob where the constant is stored
1176  *
1177  * Returns: An allocated value representing a stringified version of the
1178  * constant.
1179  */
1180 char *
1181 get_constant (MonoImage *m, MonoTypeEnum t, guint32 blob_index)
1182 {
1183         const char *ptr = mono_metadata_blob_heap (m, blob_index);
1184         int len;
1185         
1186         len = mono_metadata_decode_value (ptr, &ptr);
1187         
1188         switch (t){
1189         case MONO_TYPE_BOOLEAN:
1190                 return g_strdup_printf ("%s", *ptr ? "true" : "false");
1191                 
1192         case MONO_TYPE_CHAR:
1193                 return g_strdup_printf ("%c", *ptr); /* FIXME: unicode char */
1194                 
1195         case MONO_TYPE_U1:
1196         case MONO_TYPE_I1:
1197                 return g_strdup_printf ("int8(0x%02x)", (int) (*ptr));
1198                 break;
1199                 
1200         case MONO_TYPE_U2:
1201         case MONO_TYPE_I2:
1202                 return g_strdup_printf ("int16(0x%08x)", (int) read16 (ptr));
1203                 
1204         case MONO_TYPE_U4:
1205         case MONO_TYPE_I4:
1206                 return g_strdup_printf ("int32(%d)", read32 (ptr));
1207                 
1208         case MONO_TYPE_I8: {
1209                 guint32 low, high;
1210                 low = read32 (ptr);
1211                 high = read32 (ptr + 4);
1212                 return g_strdup_printf ("0x%08x%08x", high, low);
1213         }
1214         case MONO_TYPE_U8: {
1215                 guint32 low, high;
1216                 low = read32 (ptr);
1217                 high = read32 (ptr + 4);
1218                 return g_strdup_printf ("0x%08x%08x", high, low);
1219         }
1220         case MONO_TYPE_R4: {
1221                 float r;
1222                 readr4 (ptr, &r);
1223                 return g_strdup_printf ("%g", (double) r);
1224         }
1225         case MONO_TYPE_R8: {
1226                 double r;
1227                 readr8 (ptr, &r);
1228                 return g_strdup_printf ("%g", r);
1229         }
1230         case MONO_TYPE_STRING: {
1231                 int i, j, e;
1232                 char *res;
1233                 e = len = 0;
1234                 for (i = 0; !ptr [i+1]; i += 2){
1235                         len++;
1236                         switch (ptr [i]) {
1237                         case '"':
1238                         case '\\':
1239                         case '\n': /* add more */
1240                                 e++;
1241                         }
1242                 }
1243                 res = g_malloc (len + e + 3);
1244                 j = 1;
1245                 res [0] = '"';
1246
1247                 for (i = 0; i < len; i += 2){
1248                         switch(ptr[i]) {
1249                         case '"': 
1250                                 res[j++] = '\\';
1251                                 res[j++] = '"';
1252                         case '\\': 
1253                                 res[j++] = '\\';
1254                                 res[j++] = '\\';
1255                         case '\n':
1256                                 res[j++] = '\\';
1257                                 res[j++] = 'n';
1258                                 break;
1259                         default:
1260                                 res[j++] = isprint (ptr [i]) ? ptr [i] : '.';
1261                                 break;
1262                         }
1263                 }
1264                 res[j++] = '"';
1265                 res[j] = 0;
1266                 return res;
1267         }
1268                 
1269         case MONO_TYPE_CLASS:
1270                 return g_strdup ("CLASS CONSTANT.  MUST BE ZERO");
1271                 
1272         default:
1273                 g_error ("Unknown MONO_TYPE (%d) on constant at Blob index (0x%08x)\n",
1274                          (int) *ptr, blob_index);
1275                 return g_strdup_printf ("Unknown");
1276         }
1277
1278 }
1279
1280 /**
1281  * get_token:
1282  * @m: metadata context
1283  * @token: token that we want to decode.
1284  *
1285  * Returns: An allocated value representing a stringified version of the
1286  * constant.
1287  */
1288 char *
1289 get_token (MonoImage *m, guint32 token)
1290 {
1291         guint32 idx = mono_metadata_token_index (token);
1292
1293         switch (mono_metadata_token_code (token)){
1294         case MONO_TOKEN_FIELD_DEF:
1295                 return (get_field (m, token));
1296         case MONO_TOKEN_TYPE_DEF:
1297                 return get_typedef (m, idx);
1298         case MONO_TOKEN_TYPE_REF:
1299                 return get_typeref (m, idx);
1300         case MONO_TOKEN_TYPE_SPEC:
1301                 return get_typespec (m, idx);
1302         default:                
1303                 g_error ("Do not know how to decode tokens of type 0x%08x", token);
1304         }
1305
1306         g_assert_not_reached ();
1307         return g_strdup ("ERROR");
1308 }
1309
1310 /**
1311  * get_token_type:
1312  * @m: metadata context
1313  * @token: the token can belong to any of the following tables:
1314  * MONO_TOKEN_TYPE_REF, MONO_TOKEN_TYPE_DEF, MONO_TOKEN_TYPE_SPEC
1315  *
1316  * Returns: a stringified version of the MethodDef or MethodRef or TypeSpecn
1317  * at (token & 0xffffff) 
1318  */
1319 char *
1320 get_token_type (MonoImage *m, guint32 token)
1321 {
1322         char *temp = NULL, *s;
1323         int idx;
1324
1325         idx = mono_metadata_token_index (token);
1326         
1327         switch (mono_metadata_token_code (token)){
1328         case MONO_TOKEN_TYPE_DEF:
1329                 temp = get_typedef (m, idx);
1330                 s = g_strdup_printf ("%s", temp);
1331                 break;
1332                 
1333         case MONO_TOKEN_TYPE_REF: 
1334                 temp = get_typeref (m, idx);
1335                 s = g_strdup_printf ("%s", temp);
1336                 break;
1337                 
1338         case MONO_TOKEN_TYPE_SPEC:
1339                 s = get_typespec (m, idx);
1340                 break;
1341
1342         default:
1343                 g_error ("Unhandled encoding for token 0x%08x", token);
1344
1345         }
1346         
1347         if (temp)
1348                 g_free (temp);
1349
1350         return s;
1351 }
1352
1353 char *
1354 get_guid (MonoImage *m, guint32 guid_index)
1355 {
1356         const unsigned char *guid;
1357         char *result;
1358
1359         guid = mono_metadata_guid_heap (m, guid_index);
1360
1361         result = g_strdup_printf ("{%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X}", 
1362                         guid [3], guid [2], guid [1], guid [0], guid [5], guid [4], guid [7], guid [6],
1363                         guid [8], guid [9], guid [10], guid [11], guid [12], guid [13], guid [14], guid [15]);
1364         return result;
1365 }
1366
1367 GList *
1368 dis_get_custom_attrs (MonoImage *m, guint32 token)
1369 {
1370         GList *list = NULL;
1371         guint32 idx, i, len, mtoken;
1372         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
1373         MonoTableInfo *ca;
1374         char *method;
1375         GString *attr;
1376         const char *val;
1377
1378         idx = mono_metadata_token_index (token);
1379         idx <<= CUSTOM_ATTR_BITS;
1380         
1381         switch (mono_metadata_token_table (token)) {
1382         case MONO_TABLE_TYPEDEF:
1383                 idx |= CUSTOM_ATTR_TYPEDEF;
1384                 break;
1385         case MONO_TABLE_ASSEMBLY:
1386                 idx |= CUSTOM_ATTR_ASSEMBLY;
1387                 break;
1388         case MONO_TABLE_PROPERTY:
1389                 idx |= CUSTOM_ATTR_PROPERTY;
1390                 break;
1391         case MONO_TABLE_EVENT:
1392                 idx |= CUSTOM_ATTR_EVENT;
1393                 break;
1394         case MONO_TABLE_FIELD:
1395                 idx |= CUSTOM_ATTR_FIELDDEF;
1396                 break;
1397         case MONO_TABLE_METHOD:
1398                 idx |= CUSTOM_ATTR_METHODDEF;
1399                 break;
1400         case MONO_TABLE_PARAM:
1401                 idx |= CUSTOM_ATTR_PARAMDEF;
1402                 break;
1403         default:
1404                 g_print ("Missing custom attr get support for token 0x%08x\n", token);
1405                 return NULL;
1406         }
1407
1408         ca = &m->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1409         /* the table is not sorted */
1410         for (i = 0; i < ca->rows; ++i) {
1411                 char *dump;
1412                 mono_metadata_decode_row (ca, i, cols, MONO_CUSTOM_ATTR_SIZE);
1413                 if (cols [MONO_CUSTOM_ATTR_PARENT] != idx)
1414                         continue;
1415                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> CUSTOM_ATTR_TYPE_BITS;
1416                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & CUSTOM_ATTR_TYPE_MASK) {
1417                 case CUSTOM_ATTR_TYPE_METHODDEF:
1418                         mtoken |= MONO_TOKEN_METHOD_DEF;
1419                         break;
1420                 case CUSTOM_ATTR_TYPE_MEMBERREF:
1421                         mtoken |= MONO_TOKEN_MEMBER_REF;
1422                         break;
1423                 default:
1424                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
1425                         break;
1426                 }
1427                 method = get_method (m, mtoken);
1428                 val = mono_metadata_blob_heap (m, cols [MONO_CUSTOM_ATTR_VALUE]);
1429                 len = mono_metadata_decode_value (val, &val);
1430                 attr = g_string_new (".custom ");
1431                 dump = data_dump (val, len, "\t\t");
1432                 g_string_sprintfa (attr, "%s = %s", method, dump);
1433                 g_free (dump);
1434                 list = g_list_append (list, attr->str);
1435                 g_string_free (attr, FALSE);
1436                 g_free (method);
1437         }
1438         return list;
1439 }
1440
1441 char*
1442 get_marshal_info (MonoImage *m, const char *blob) {
1443         int len, size = 0;
1444
1445         len = mono_metadata_decode_blob_size (blob, &blob);
1446
1447         switch (*blob) {
1448         case MONO_NATIVE_BOOLEAN:
1449                 return g_strdup ("bool");
1450         case MONO_NATIVE_I1:
1451                 return g_strdup ("int8");
1452         case MONO_NATIVE_U1:
1453                 return g_strdup ("unsigned int8");
1454         case MONO_NATIVE_I2:
1455                 return g_strdup ("int16");
1456         case MONO_NATIVE_U2:
1457                 return g_strdup ("unsigned int16");
1458         case MONO_NATIVE_I4:
1459                 return g_strdup ("int32");
1460         case MONO_NATIVE_U4:
1461                 return g_strdup ("unsigned int32");
1462         case MONO_NATIVE_I8:
1463                 return g_strdup ("int64");
1464         case MONO_NATIVE_U8:
1465                 return g_strdup ("unsigned int64");
1466         case MONO_NATIVE_R4:
1467                 return g_strdup ("float32");
1468         case MONO_NATIVE_R8:
1469                 return g_strdup ("float64");
1470         case MONO_NATIVE_CURRENCY:
1471                 return g_strdup ("currency");
1472         case MONO_NATIVE_BSTR:
1473                 return g_strdup ("bstr");
1474         case MONO_NATIVE_LPSTR:
1475                 return g_strdup ("lpstr");
1476         case MONO_NATIVE_LPWSTR:
1477                 return g_strdup ("lpwstr");
1478         case MONO_NATIVE_LPTSTR:
1479                 return g_strdup ("lptstr");
1480         case MONO_NATIVE_BYVALTSTR:
1481                 size = mono_metadata_decode_value (blob + 1, &blob);
1482                 return g_strdup_printf ("fixed sysstring [%d]", size);
1483         case MONO_NATIVE_IUNKNOWN:
1484                 return g_strdup ("iunknown");
1485         case MONO_NATIVE_IDISPATCH:
1486                 return g_strdup ("idispatch");
1487         case MONO_NATIVE_STRUCT:
1488                 return g_strdup ("struct");
1489         case MONO_NATIVE_INTERFACE:
1490                 return g_strdup ("interface");
1491         case MONO_NATIVE_SAFEARRAY:
1492                 return g_strdup ("safearray");
1493         case MONO_NATIVE_BYVALARRAY:
1494                 size = mono_metadata_decode_value (blob + 1, &blob);
1495                 return g_strdup_printf ("fixed array [%d]", size);
1496         case MONO_NATIVE_INT:
1497                 return g_strdup ("int");
1498         case MONO_NATIVE_UINT:
1499                 return g_strdup ("unsigned int");
1500         case MONO_NATIVE_VBBYREFSTR:
1501                 return g_strdup ("vbbyrefstr");
1502         case MONO_NATIVE_ANSIBSTR:
1503                 return g_strdup ("ansi bstr");
1504         case MONO_NATIVE_TBSTR:
1505                 return g_strdup ("tbstr");
1506         case MONO_NATIVE_VARIANTBOOL:
1507                 return g_strdup ("variant bool");
1508         case MONO_NATIVE_FUNC:
1509                 return g_strdup ("method");
1510         case MONO_NATIVE_ASANY:
1511                 return g_strdup ("as any");
1512         case MONO_NATIVE_LPARRAY:
1513                 return g_strdup ("[]");
1514         case MONO_NATIVE_LPSTRUCT:
1515                 return g_strdup ("lpstruct");
1516         case MONO_NATIVE_CUSTOM:
1517                 return g_strdup ("custom");
1518         case MONO_NATIVE_ERROR:
1519                 return g_strdup ("error");
1520         default:
1521                 return g_strdup ("unknown");
1522         }
1523 }
1524