Updated.
[mono.git] / mono / dis / get.c
index 62089b6f4949811196f02adbf396a55bbf5de96a..c1a42a4e39d2fb84f384a5d766b9834685bdd74c 100644 (file)
 
 extern gboolean substitute_with_mscorlib_p;
 
+static MonoGenericContext *
+get_memberref_context (MonoImage *m, guint32 mrp_token, MonoGenericContext *context);
+
+static char *
+get_memberref_parent (MonoImage *m, guint32 mrp_token, MonoGenericContext *context);
+
+GHashTable *key_table = NULL;
+gboolean show_method_tokens = FALSE;
+gboolean show_tokens = FALSE;
+
 char *
 get_typedef (MonoImage *m, int idx)
 {
        guint32 cols [MONO_TYPEDEF_SIZE];
        const char *ns;
-
+       char *tstring, *result;
+        guint32 token;
+        
        mono_metadata_decode_row (&m->tables [MONO_TABLE_TYPEDEF], idx - 1, cols, MONO_TYPEDEF_SIZE);
 
-       ns = mono_metadata_string_heap (m, cols [MONO_TYPEDEF_NAMESPACE]);
-       return g_strdup_printf (
-               "%s%s%s", ns, *ns?".":"",
-               mono_metadata_string_heap (m, cols [MONO_TYPEDEF_NAME]));
+        ns = mono_metadata_string_heap (m, cols [MONO_TYPEDEF_NAMESPACE]);
+
+        /* Check if this is a nested type */
+        token = MONO_TOKEN_TYPE_DEF | (idx);
+        token = mono_metadata_nested_in_typedef (m, token);
+       tstring = show_tokens ? g_strdup_printf ("/*%08x*/", token) : NULL;
+        if (token) {
+                char *outer;
+                
+                outer = get_typedef (m, mono_metadata_token_index (token));
+                result = g_strdup_printf (
+                        "%s%s%s/%s%s", ns, *ns?".":"", outer,
+                        mono_metadata_string_heap (m, cols [MONO_TYPEDEF_NAME]),
+                       tstring ? tstring : "");
+               g_free (outer);
+               g_free (tstring);
+               return result;
+        }
+        
+       
+       result = g_strdup_printf (
+               "%s%s%s%s", ns, *ns?".":"",
+               mono_metadata_string_heap (m, cols [MONO_TYPEDEF_NAME]),
+               tstring ? tstring : "");
+       g_free (tstring);
+
+       return result;
 }
 
 char *
@@ -49,6 +84,16 @@ get_module (MonoImage *m, int idx)
        return g_strdup (mono_metadata_string_heap (m, cols [MONO_MODULE_NAME]));
 }
 
+char *
+get_moduleref (MonoImage *m, int idx)
+{
+       guint32 cols [MONO_MODULEREF_SIZE];
+       
+       mono_metadata_decode_row (&m->tables [MONO_TABLE_MODULEREF], idx - 1, cols, MONO_MODULEREF_SIZE);
+
+       return g_strdup (mono_metadata_string_heap (m, cols [MONO_MODULEREF_NAME]));
+}
+
 char *
 get_assemblyref (MonoImage *m, int idx)
 {
@@ -124,7 +169,7 @@ get_array_shape (MonoImage *m, const char *ptr, char **result)
  * Returns the stringified representation of a TypeSpec signature (22.2.17)
  */
 char *
-get_typespec (MonoImage *m, guint32 idx)
+get_typespec (MonoImage *m, guint32 idx, gboolean is_def, MonoGenericContext *context)
 {
        guint32 cols [MONO_TYPESPEC_SIZE];
        const char *ptr;
@@ -132,6 +177,10 @@ get_typespec (MonoImage *m, guint32 idx)
        GString *res = g_string_new ("");
        int len;
 
+       MonoType *type;
+
+       type = mono_type_create_from_typespec_full (m, context, idx);
+
        mono_metadata_decode_row (&m->tables [MONO_TABLE_TYPESPEC], idx-1, cols, MONO_TYPESPEC_SIZE);
        ptr = mono_metadata_blob_heap (m, cols [MONO_TYPESPEC_SIGNATURE]);
        len = mono_metadata_decode_value (ptr, &ptr);
@@ -148,25 +197,22 @@ get_typespec (MonoImage *m, guint32 idx)
                if (*ptr == MONO_TYPE_VOID)
                        g_string_append (res, "void");
                else {
-                       ptr = get_type (m, ptr, &s);
+                       ptr = get_type (m, ptr, &s, context);
                        if (s)
                                g_string_append (res, s);
                }
+               g_string_append (res, "*");
                break;
                
        case MONO_TYPE_FNPTR:
-               g_string_append (res, "FNPTR ");
-               /*
-                * we assume MethodRefSig, as we do not know
-                * whether it is a MethodDefSig or a MethodRefSig.
-                */
-               printf ("\n FNPTR:\n");
-               
-               hex_dump (ptr, 0, 40);
+               s = dis_stringify_function_ptr (m, type->data.method);
+               g_string_append (res, "method ");
+               g_string_append (res, s);
+               g_free (s);
                break;
                        
        case MONO_TYPE_ARRAY:
-               ptr = get_type (m, ptr, &s);
+               ptr = get_type (m, ptr, &s, context);
                g_string_append (res, s);
                g_free (s);
                g_string_append_c (res, ' ');
@@ -182,13 +228,25 @@ get_typespec (MonoImage *m, guint32 idx)
                        g_string_append_c (res, ' ');
                        g_free (s);
                }
-               ptr = get_type (m, ptr, &s);
+               ptr = get_type (m, ptr, &s, context);
                g_string_append (res, s);
                g_string_append (res, "[]");
                g_free (s);
+               break;
+
+       default:
+               s = dis_stringify_type (m, type, is_def);
+               g_string_append (res, s);
+               g_free (s);
+               break;
        }
 
-       result = res->str;
+       if (show_tokens) {
+               int token = mono_metadata_make_token (MONO_TABLE_TYPESPEC, idx);
+               result = g_strdup_printf ("%s/*%08x*/", res->str, token);
+       } else
+               result = res->str;
+
        g_string_free (res, FALSE);
 
        return result;
@@ -207,21 +265,22 @@ get_typeref (MonoImage *m, int idx)
        t = mono_metadata_string_heap (m, cols [MONO_TYPEREF_NAME]);
        s = mono_metadata_string_heap (m, cols [MONO_TYPEREF_NAMESPACE]);
 
-       rs_idx = cols [MONO_TYPEREF_SCOPE] >> RESOLTION_SCOPE_BITS;
-       table = cols [MONO_TYPEREF_SCOPE] & RESOLTION_SCOPE_MASK;
+       rs_idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLTION_SCOPE_BITS;
+       table = cols [MONO_TYPEREF_SCOPE] & MONO_RESOLTION_SCOPE_MASK;
        
        switch (table){
-       case RESOLTION_SCOPE_MODULE: /* Module */
+       case MONO_RESOLTION_SCOPE_MODULE: /* Module */
                x = get_module (m, rs_idx);
                ret = g_strdup_printf ("[%s] %s%s%s", x, s, *s?".":"", t);
                g_free (x);
                break;
 
-       case RESOLTION_SCOPE_MODULEREF: /* ModuleRef */
-               ret = g_strdup_printf ("TODO:TypeRef-ModuleRef (%s.%s)", s, t);
+       case MONO_RESOLTION_SCOPE_MODULEREF: /* ModuleRef */
+               x = get_moduleref (m, rs_idx);
+               ret = g_strdup_printf ("[.module %s]%s%s%s", x, s, *s ? "." : "", t);
                break;
                              
-       case RESOLTION_SCOPE_ASSEMBLYREF: /*
+       case MONO_RESOLTION_SCOPE_ASSEMBLYREF: /*
                 * AssemblyRef (ECMA docs claim it is 3, but it looks to
                 * me like it is 2 (tokens are prefixed with 0x23)
                 */
@@ -230,7 +289,7 @@ get_typeref (MonoImage *m, int idx)
                g_free (x);
                break;
                
-       case RESOLTION_SCOPE_TYPEREF: /* TypeRef */
+       case MONO_RESOLTION_SCOPE_TYPEREF: /* TypeRef */
                x = get_typeref (m, rs_idx);
                ret =  g_strdup_printf ("%s/%s", x, t);
                g_free (x);
@@ -240,6 +299,13 @@ get_typeref (MonoImage *m, int idx)
                ret = g_strdup_printf ("Unknown table in TypeRef %d", table);
        }
 
+       if (show_tokens) {
+               int token = mono_metadata_make_token (MONO_TABLE_TYPEREF, idx);
+               char *temp = g_strdup_printf ("%s/*%08x*/", ret, token);
+               g_free (ret);
+               ret = temp;
+       }
+
        return ret;
 }
 
@@ -255,16 +321,16 @@ get_typeref (MonoImage *m, int idx)
  * at (dor_token >> 2) 
  */
 char *
-get_typedef_or_ref (MonoImage *m, guint32 dor_token)
+get_typedef_or_ref (MonoImage *m, guint32 dor_token, MonoGenericContext *context)
 {
-       char *temp = NULL, *s;
+       char *temp = NULL, *s = NULL;
        int table, idx;
 
        /*
         * low 2 bits contain encoding
         */
-       table = dor_token & 0x03;
-       idx = dor_token >> 2;
+       table = dor_token & MONO_TYPEDEFORREF_MASK;
+       idx = dor_token >> MONO_TYPEDEFORREF_BITS;
        
        switch (table){
        case 0: /* TypeDef */
@@ -278,7 +344,7 @@ get_typedef_or_ref (MonoImage *m, guint32 dor_token)
                break;
                
        case 2: /* TypeSpec */
-               s = get_typespec (m, idx);
+               s = get_typespec (m, idx, FALSE, context);
                break;
 
        default:
@@ -292,6 +358,25 @@ get_typedef_or_ref (MonoImage *m, guint32 dor_token)
        return s;
 }
 
+/**
+ * get_type_or_methdef
+ * @m: metadata context
+ * @dor_token: type or method def encoded index
+ *
+ * Low bit contains the table to lookup from
+ * high bits contain the index into the type def or method def table
+ *
+ * Returns: a stringified version of the TypeOrMethodDef token
+ */
+char *
+get_type_or_methdef (MonoImage *m, guint32 dor_token)
+{
+        if (dor_token & MONO_TYPEORMETHOD_METHOD) /* MethodDef */
+               return get_methoddef (m, dor_token >> MONO_TYPEORMETHOD_BITS);
+        else  /* TypeDef */
+                return get_typedef (m, dor_token >> MONO_TYPEORMETHOD_BITS);
+}
+
 /** 
  * get_encoded_typedef_or_ref:
  * @m: metadata context 
@@ -309,7 +394,7 @@ get_encoded_typedef_or_ref (MonoImage *m, const char *ptr, char **result)
        
        token = mono_metadata_decode_value (ptr, &ptr);
 
-       *result = get_typedef_or_ref (m, token);
+       *result = get_typedef_or_ref (m, token, NULL);
 
        return ptr;
 }
@@ -325,21 +410,26 @@ const char *
 get_custom_mod (MonoImage *m, const char *ptr, char **return_value)
 {
        char *s;
+       const char *reqd;
        
-       if ((*ptr == MONO_TYPE_CMOD_OPT) ||
-           (*ptr == MONO_TYPE_CMOD_REQD)){
+       *return_value = NULL;
+       while ((*ptr == MONO_TYPE_CMOD_OPT) ||
+                  (*ptr == MONO_TYPE_CMOD_REQD)) {
+               reqd = (*ptr == MONO_TYPE_CMOD_REQD) ? "reqd" : "opt";
                ptr++;
                ptr = get_encoded_typedef_or_ref (m, ptr, &s);
 
-               *return_value = g_strconcat ("CMOD ", s, NULL);
+               if (*return_value == NULL)
+                       *return_value = g_strconcat (reqd, " ", s, NULL);
+               else
+                       *return_value = g_strconcat (*return_value, " ", reqd, " ", s, NULL);
                g_free (s);
-       } else
-               *return_value = NULL;
+       }
        return ptr;
 }
 
 
-static map_t element_type_map [] = {
+static dis_map_t element_type_map [] = {
        { MONO_TYPE_END        , "end" },
        { MONO_TYPE_VOID       , "void" },
        { MONO_TYPE_BOOLEAN    , "bool" },
@@ -347,11 +437,11 @@ static map_t element_type_map [] = {
        { MONO_TYPE_I1         , "int8" },
        { MONO_TYPE_U1         , "unsigned int8" }, 
        { MONO_TYPE_I2         , "int16" },
-       { MONO_TYPE_U2         , "uint16" },
+       { MONO_TYPE_U2         , "unsigned int16" },
        { MONO_TYPE_I4         , "int32" },
-       { MONO_TYPE_U4         , "uint32" },
+       { MONO_TYPE_U4         , "unsigned int32" },
        { MONO_TYPE_I8         , "int64" },
-       { MONO_TYPE_U8         , "uint64" },
+       { MONO_TYPE_U8         , "unsigned int64" },
        { MONO_TYPE_R4         , "float32" },
        { MONO_TYPE_R8         , "float64" },
        { MONO_TYPE_STRING     , "string" },
@@ -362,12 +452,12 @@ static map_t element_type_map [] = {
        { 0, NULL }
 };
 
-static map_t call_conv_type_map [] = {
+static dis_map_t call_conv_type_map [] = {
        { MONO_CALL_DEFAULT     , "default" },
-       { MONO_CALL_C           , "c" },
-       { MONO_CALL_STDCALL     , "stdcall" },
-       { MONO_CALL_THISCALL    , "thiscall" },
-       { MONO_CALL_FASTCALL    , "fastcall" },
+       { MONO_CALL_C           , "unmanaged cdecl" },
+       { MONO_CALL_STDCALL     , "unmanaged stdcall" },
+       { MONO_CALL_THISCALL    , "unmanaged thiscall" },
+       { MONO_CALL_FASTCALL    , "unmanaged fastcall" },
        { MONO_CALL_VARARG      , "vararg" },
        { 0, NULL }
 };
@@ -379,7 +469,7 @@ dis_stringify_token (MonoImage *m, guint32 token)
        switch (token >> 24) {
        case MONO_TABLE_TYPEDEF: return get_typedef (m, idx);
        case MONO_TABLE_TYPEREF: return get_typeref (m, idx);
-       case MONO_TABLE_TYPESPEC: return get_typespec (m, idx);
+       case MONO_TABLE_TYPESPEC: return get_typespec (m, idx, FALSE, NULL);
        default:
                 break;
        }
@@ -387,13 +477,13 @@ dis_stringify_token (MonoImage *m, guint32 token)
 }
 
 char*
-dis_stringify_array (MonoImage *m, MonoArrayType *array
+dis_stringify_array (MonoImage *m, MonoArrayType *array, gboolean is_def)
 {
        char *type;
        GString *s = g_string_new("");
        int i;
        
-       type = dis_stringify_type (m, array->type);
+       type = dis_stringify_type (m, &array->eklass->byval_arg, is_def);
        g_string_append (s, type);
        g_free (type);
        g_string_append_c (s, '[');
@@ -421,7 +511,9 @@ dis_stringify_modifiers (MonoImage *m, int n, MonoCustomMod *mod)
        int i;
        for (i = 0; i < n; ++i) {
                char *tok = dis_stringify_token (m, mod[i].token);
-               g_string_sprintfa (s, "%s %s", mod[i].required ? "opt": "reqd", tok);
+               if (i > 0)
+                       g_string_sprintfa (s, " ");
+               g_string_sprintfa (s, "%s (%s)", mod[i].required ? "modreq": "modopt", tok);
                g_free (tok);
        }
        g_string_append_c (s, ' ');
@@ -435,44 +527,144 @@ dis_stringify_param (MonoImage *m, MonoType *param)
 {
        char *t;
        char *result;
-       const char *out = param->attrs & 2 ? "[out] ": "";
-       t = dis_stringify_type (m, param);
-       result = g_strconcat (out, t, NULL);
+       char *attribs;
+       const char *out = param->attrs & PARAM_ATTRIBUTE_OUT ? "[out]": "";
+       const char *opt = param->attrs & PARAM_ATTRIBUTE_OPTIONAL ? "[opt]": "";
+       attribs = g_strconcat(out, opt, NULL);
+       t = dis_stringify_type (m, param, TRUE);
+       result = g_strjoin(attribs[0] ? " ":"", attribs, t, NULL);
        g_free (t);
+       g_free (attribs);
        return result;
 }
 
+/**
+ * get_generic_param
+ * @m: metadata context 
+ * @table_type: The type of table we are getting generics for (0 for typedef, 1 for method)
+ * @row: The row in the table
+ *
+ * Returns: Allocated stringified generic parameters
+ */
+char*
+get_generic_param (MonoImage *m, MonoGenericContainer *container)
+{
+        GString *result;
+       char *retval;
+       int i;
+
+       if (!container)
+               return NULL;
+
+       result = g_string_new ("");
+
+       g_string_append_c (result, '<');
+       for (i = 0; i < container->type_argc; i++) {
+               MonoGenericParam *param = &container->type_params [i];
+               MonoClass **constr;
+               int first = 1;
+               guint16 flags;
+               char *esname;
+
+               if (i > 0)
+                       g_string_append (result, ",");
+
+               flags = param->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
+               if (flags == GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT)
+                       g_string_append (result, "class ");
+               else if (flags == GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT)
+                       g_string_append (result, "valuetype ");
+               else if (flags == GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT)
+                       g_string_append (result, ".ctor ");
+
+               for (constr = param->constraints; constr && *constr; constr++) {
+                       char *sig;
+
+                       if (first) {
+                               g_string_append_c (result, '(');
+                               first = 0;
+                       } else
+                               g_string_append (result, ", ");
+                       sig = dis_stringify_object_with_class (m, *constr, TRUE, TRUE);
+                       g_string_append (result, sig);
+                       g_free (sig);
+                }
+
+               if (!first)
+                       g_string_append (result, ") ");
+
+               esname = get_escaped_name (param->name);
+               g_string_append (result, esname);
+               g_free (esname);
+       }
+
+       g_string_append_c (result, '>');
+
+        retval = result->str;
+        g_string_free (result, FALSE);
+        return retval;
+}
+
 char*
-dis_stringify_method_signature (MonoImage *m, MonoMethodSignature *method, int methoddef_row)
+dis_stringify_method_signature (MonoImage *m, MonoMethodSignature *method, int methoddef_row,
+                               MonoGenericContext *context, gboolean fully_qualified)
 {
        guint32 cols [MONO_METHOD_SIZE];
        guint32 pcols [MONO_PARAM_SIZE];
        guint32 param_index = 0;
        const char *name = "";
        int free_method = 0;
-       char *retval;
+       char *retval, *esname;
+       char *type = NULL;
+       char *gen_param = NULL;
        GString *result = g_string_new ("");
+       MonoGenericContainer *container = NULL;
        int i;
-
+        
        g_assert (method || methoddef_row);
 
        if (methoddef_row) {
                mono_metadata_decode_row (&m->tables [MONO_TABLE_METHOD], methoddef_row -1, cols, MONO_METHOD_SIZE);
+               if (fully_qualified)
+                       type = get_typedef (m, mono_metadata_typedef_from_method (m, methoddef_row));
                name = mono_metadata_string_heap (m, cols [MONO_METHOD_NAME]);
                param_index = cols [MONO_METHOD_PARAMLIST];
                if (!method) {
                        const char *sig = mono_metadata_blob_heap (m, cols [MONO_METHOD_SIGNATURE]);
+
+                       container = mono_metadata_load_generic_params (
+                               m, MONO_TOKEN_METHOD_DEF | methoddef_row, context ? context->container : NULL);
+                       if (container)
+                               context = (MonoGenericContext *) container;
+
                        mono_metadata_decode_blob_size (sig, &sig);
-                       method = mono_metadata_parse_method_signature (m, 1, sig, &sig);
+                       method = mono_metadata_parse_method_signature_full (m, context, methoddef_row, sig, &sig);
                        free_method = 1;
-               }
+               } else if (context)
+                       container = context->container;
+
+               if (container && container->is_method)
+                       gen_param = get_generic_param (m, container);
        }
        
        retval = dis_stringify_param (m, method->ret);
        if (method->hasthis)
                g_string_append (result, "instance ");
        g_string_append (result, map (method->call_convention, call_conv_type_map));
-       g_string_sprintfa (result, " %s %s(", retval, name);
+       g_string_sprintfa (result, " %s ", retval);
+       if (type) {
+               char *estype = get_escaped_name (type);
+               g_string_sprintfa (result, "%s::", estype);
+               g_free (estype);
+       }
+       esname = get_escaped_name (name);
+       g_string_append (result, esname);
+       g_free (esname);
+        if (gen_param) {
+                g_string_append (result, gen_param);
+                g_free (gen_param);
+        }
+       g_string_append (result, " (");
        g_free (retval);
        for (i = 0; i < method->param_count; ++i) {
                if (param_index && param_index <= m->tables [MONO_TABLE_PARAM].rows) {
@@ -486,11 +678,17 @@ dis_stringify_method_signature (MonoImage *m, MonoMethodSignature *method, int m
                if (i)
                        g_string_append (result, ", ");
                retval = dis_stringify_param (m, method->params [i]);
-               g_string_sprintfa (result, "%s %s", retval, name);
+               esname = get_escaped_name (name);
+               g_string_append_printf (result, "%s %s", retval, esname);
                g_free (retval);
+               g_free (esname);
        }
        g_string_append (result, ") ");
 
+       if (show_method_tokens && methoddef_row)
+               g_string_append_printf (result, " /* 0x%X */ ",
+                               (methoddef_row >> MONO_TYPEORMETHOD_BITS) | MONO_TOKEN_METHOD_DEF);
+
        if (free_method)
                mono_metadata_free_method_signature (method);
        retval = result->str;
@@ -499,38 +697,120 @@ dis_stringify_method_signature (MonoImage *m, MonoMethodSignature *method, int m
        return retval;
 }
 
+char*
+dis_stringify_function_ptr (MonoImage *m, MonoMethodSignature *method)
+{
+       char *retval;
+       GString *result = g_string_new ("");
+       int i;
+       
+       g_assert (method);
+
+       g_string_append (result, map (method->call_convention, call_conv_type_map));
+
+       retval = dis_stringify_param (m, method->ret);
+       g_string_sprintfa (result, " %s ", retval);
+       g_free (retval);
+
+       g_string_append (result, " *(");
+       for (i = 0; i < method->param_count; ++i) {
+               if (i)
+                       g_string_append (result, ", ");
+               retval = dis_stringify_param (m, method->params [i]);
+               g_string_append (result, retval);
+               g_free (retval);
+       }
+       g_string_append (result, ") ");
+
+       retval = result->str;
+       g_string_free (result, FALSE);
+
+       return retval;
+}
+
 static char *
-dis_stringify_object_with_class (MonoImage *m, MonoClass *c)
+get_escaped_class_name (MonoClass *c)
+{
+       char *result, *esname;
+
+       esname = get_escaped_name (c->name);
+
+       if (c->nested_in){
+               char *part_a = get_escaped_class_name (c->nested_in);
+
+               result = g_strdup_printf ("%s/%s", part_a, esname);
+               g_free (part_a);
+       } else if (*c->name_space)
+               result = g_strdup_printf ("%s.%s", c->name_space, esname);
+       else
+               result = g_strdup (esname);
+
+       g_free (esname);
+       return result;
+}
+
+char *
+dis_stringify_object_with_class (MonoImage *m, MonoClass *c, gboolean prefix, gboolean is_def)
 {
        /* FIXME: handle MONO_TYPE_OBJECT ... */
-       const char *otype = c->byval_arg.type == MONO_TYPE_CLASS? "class" : "valuetype";
-       char *assemblyref = NULL, *result;
+       const char *otype = c->byval_arg.type == MONO_TYPE_VALUETYPE ? "valuetype " : "class " ;
+       char *assemblyref = NULL, *result, *esname, *generic = NULL;
+       
        if (m != c->image) {
                if (c->image->assembly_name) {
                        /* we cheat */
                        if (substitute_with_mscorlib_p && !strcmp ("corlib", c->image->assembly_name))
                                assemblyref = g_strdup_printf ("[%s]", "mscorlib");
-                       else
-                               assemblyref = g_strdup_printf ("[%s]", c->image->assembly->aname.name);
+                       else {
+                               char *esc = get_escaped_name (c->image->assembly->aname.name);
+                               
+                               assemblyref = g_strdup_printf ("[%s]", esc);
+                               g_free (esc);
+                       }
                } else {
                        assemblyref = g_strdup_printf ("[.module %s]", c->image->module_name);
                }
        }
-       result = g_strdup_printf ("%s %s%s%s%s", otype, assemblyref?assemblyref:"", c->name_space, 
-                               *c->name_space?".":"", c->name);
+
+       esname = get_escaped_class_name (c);
+
+       if (c->generic_class) {
+               MonoGenericClass *gclass = c->generic_class;
+               GString *str = g_string_new ("");
+               int i;
+
+               for (i = 0; i < gclass->inst->type_argc; i++){
+                       char *t = dis_stringify_type (m, gclass->inst->type_argv [i], is_def);
+
+                       g_string_append (str, t);
+                       if (i+1 != gclass->inst->type_argc)
+                               g_string_append (str, ", ");
+                       g_free (t);
+               }
+               generic = g_strdup_printf ("<%s>", str->str);
+               g_string_free (str, TRUE);
+       }
+
+
+       result = g_strdup_printf ("%s%s%s%s", prefix ? otype : "", assemblyref?assemblyref:"",
+                                 esname, generic?generic:"");
+       
+       g_free (generic);
        g_free (assemblyref);
+       g_free (esname);
+       
        return result;
 }
 
 static char *
-dis_stringify_object (MonoImage *m, MonoType *type)
+dis_stringify_object (MonoImage *m, MonoType *type, gboolean is_def)
 {
        MonoClass *c = mono_class_from_mono_type (type);
-       return dis_stringify_object_with_class (m, c);
+       return dis_stringify_object_with_class (m, c, TRUE, is_def);
 }
 
 char*
-dis_stringify_type (MonoImage *m, MonoType *type)
+dis_stringify_type (MonoImage *m, MonoType *type, gboolean is_def)
 {
        const char *pinned = "", *byref = "";
        char *bare = NULL, *mods = NULL;
@@ -562,27 +842,70 @@ dis_stringify_type (MonoImage *m, MonoType *type)
                
        case MONO_TYPE_VALUETYPE:
        case MONO_TYPE_CLASS:
-               bare = dis_stringify_object (m, type);
+               bare = dis_stringify_object (m, type, is_def);
+               break;
+       case MONO_TYPE_FNPTR: {
+               char *child_type;
+               child_type = dis_stringify_function_ptr (m, type->data.method);
+               bare = g_strdup_printf ("method %s", child_type);
+               g_free (child_type);
                break;
+       }
+       case MONO_TYPE_PTR: {
+               char *child_type;
+               child_type = dis_stringify_type (m, type->data.type, is_def);
                
-       case MONO_TYPE_FNPTR:
-               bare = dis_stringify_method_signature (m, type->data.method, 0);
+               bare = g_strdup_printf ("%s*", child_type);
+               g_free (child_type);
                break;
-       case MONO_TYPE_PTR:
+       }
        case MONO_TYPE_SZARRAY: {
                char *child_type;
-               child_type = dis_stringify_type (m, type->data.type);
+               child_type = dis_stringify_type (m, &type->data.klass->byval_arg, is_def);
                
-               bare = g_strdup_printf (type->type == MONO_TYPE_PTR ? "%s*" : "%s[]", child_type);
+               bare = g_strdup_printf ("%s[]", child_type);
                g_free (child_type);
                break;
        }
        case MONO_TYPE_ARRAY:
-               bare = dis_stringify_array (m, type->data.array);
+               bare = dis_stringify_array (m, type->data.array, is_def);
                break;
        case MONO_TYPE_VOID:
                bare = g_strdup ("void");
                break;
+       case MONO_TYPE_MVAR:
+               if (is_def) {
+                       g_assert (type->data.generic_param->name);
+                       bare = g_strdup_printf ("!!%s", type->data.generic_param->name);
+               } else
+                       bare = g_strdup_printf ("!!%d", type->data.generic_param->num);
+               break;
+       case MONO_TYPE_VAR:
+               if (is_def) {
+                       g_assert (type->data.generic_param->name);
+                       bare = g_strdup_printf ("!%s", type->data.generic_param->name);
+               } else
+                       bare = g_strdup_printf ("!%d", type->data.generic_param->num);
+               break;
+       case MONO_TYPE_GENERICINST: {
+               GString *str = g_string_new ("");
+               int i;
+               char *generic_type = dis_stringify_type (
+                       m, &type->data.generic_class->container_class->byval_arg, is_def);
+
+               for (i = 0; i < type->data.generic_class->inst->type_argc; i++){
+                       char *t = dis_stringify_type (m, type->data.generic_class->inst->type_argv [i], is_def);
+
+                       g_string_append (str, t);
+                       if (i+1 != type->data.generic_class->inst->type_argc)
+                               g_string_append (str, ", ");
+                       g_free (t);
+               }
+               bare = g_strdup_printf ("%s<%s>", generic_type, str->str);
+               g_string_free (str, TRUE);
+               break;
+       }
+               
        default:
                g_error ("Do not know how to stringify type 0x%x", type->type);
        }
@@ -612,11 +935,64 @@ dis_stringify_type (MonoImage *m, MonoType *type)
  * Returns: the new ptr to continue decoding
  */
 const char *
-get_type (MonoImage *m, const char *ptr, char **result)
+get_type (MonoImage *m, const char *ptr, char **result, MonoGenericContext *context)
 {
-       MonoType *type = mono_metadata_parse_type (m, MONO_PARSE_TYPE, 0, ptr, &ptr);
-       *result = dis_stringify_type (m, type);
-       mono_metadata_free_type (type);
+       const char *start = ptr;
+       guint32 type;
+       MonoType *t;
+
+       if (*ptr == MONO_TYPE_BYREF)
+               ++ptr;
+
+       type = mono_metadata_decode_value (ptr, &ptr);
+
+       switch (type){
+       case MONO_TYPE_VALUETYPE:
+       case MONO_TYPE_CLASS: {
+               guint32 token = mono_metadata_parse_typedef_or_ref (m, ptr, &ptr);
+               MonoClass *klass = mono_class_get (m, token);
+               char *temp = dis_stringify_object_with_class (m, klass, TRUE, FALSE);
+
+               if (show_tokens) {
+                       *result = g_strdup_printf ("%s/*%08x*/", temp, token);
+                       g_free (temp);
+               } else
+                       *result = temp;
+               break;
+       }
+
+       case MONO_TYPE_GENERICINST: {
+               GString *str = g_string_new ("");
+               int count, i;
+               char *temp;
+
+               ptr = get_type (m, ptr, &temp, context);
+               g_string_append (str, temp);
+               g_free (temp);
+
+               count = mono_metadata_decode_value (ptr, &ptr);
+               g_string_append (str, "<");
+
+               for (i = 0; i < count; i++) {
+                       if (i)
+                               g_string_append (str, ",");
+                       ptr = get_type (m, ptr, &temp, context);
+                       g_string_append (str, temp);
+               }
+
+               g_string_append (str, ">");
+               *result = str->str;
+               g_string_free (str, FALSE);
+               break;
+       }
+
+       default:
+               t = mono_metadata_parse_type_full (m, context, MONO_PARSE_TYPE, 0, start, &ptr);
+               *result = dis_stringify_type (m, t, FALSE);
+               mono_metadata_free_type (t);
+               break;
+       }
+
        return ptr;
 }
 
@@ -625,7 +1001,7 @@ get_type (MonoImage *m, const char *ptr, char **result)
  * Returns a stringified representation of a FieldSig (22.2.4)
  */
 char *
-get_field_signature (MonoImage *m, guint32 blob_signature)
+get_field_signature (MonoImage *m, guint32 blob_signature, MonoGenericContext *context)
 {
        char *allocated_modifier_string, *allocated_type_string;
        const char *ptr = mono_metadata_blob_heap (m, blob_signature);
@@ -641,7 +1017,7 @@ get_field_signature (MonoImage *m, guint32 blob_signature)
        ptr++; len--;
        
        ptr = get_custom_mod (m, ptr, &allocated_modifier_string);
-       ptr = get_type (m, ptr, &allocated_type_string);
+       ptr = get_type (m, ptr, &allocated_type_string, context);
 
        res = g_strdup_printf (
                "%s %s",
@@ -651,7 +1027,7 @@ get_field_signature (MonoImage *m, guint32 blob_signature)
        if (allocated_modifier_string)
                g_free (allocated_modifier_string);
        if (allocated_type_string)
-               g_free (allocated_modifier_string);
+               g_free (allocated_type_string);
        
        return res;
 }
@@ -701,7 +1077,7 @@ decode_literal (MonoImage *m, guint32 token)
  * Returns: the new ptr to continue decoding.
  */
 const char *
-get_ret_type (MonoImage *m, const char *ptr, char **ret_type)
+get_ret_type (MonoImage *m, const char *ptr, char **ret_type, MonoGenericContext *context)
 {
        GString *str = g_string_new ("");
        char *mod = NULL;
@@ -715,19 +1091,18 @@ get_ret_type (MonoImage *m, const char *ptr, char **ret_type)
        }
 
        if (*ptr == MONO_TYPE_TYPEDBYREF){
-               /* TODO: what does `typedbyref' mean? */
-               g_string_append (str, "/* FIXME: What does this mean? */ typedbyref ");
+               g_string_append (str, "typedbyref");
                ptr++;
        } else if (*ptr == MONO_TYPE_VOID){
                 g_string_append (str, "void");
                 ptr++;
        } else {
-               if (*ptr == MONO_TYPE_BYREF){
+                if (*ptr == MONO_TYPE_BYREF){
                        g_string_append (str, "[out] ");
                        ptr++;
                }
 
-               ptr = get_type (m, ptr, &allocated_type_string);
+               ptr = get_type (m, ptr, &allocated_type_string, context);
                g_string_append (str, allocated_type_string);
                g_free (allocated_type_string);
        }
@@ -749,7 +1124,7 @@ get_ret_type (MonoImage *m, const char *ptr, char **ret_type)
  * Returns: the new ptr to continue decoding.
  */
 const char *
-get_param (MonoImage *m, const char *ptr, char **retval)
+get_param (MonoImage *m, const char *ptr, char **retval, MonoGenericContext *context)
 {
        GString *str = g_string_new ("");
        char *allocated_mod_string, *allocated_type_string;
@@ -762,15 +1137,19 @@ get_param (MonoImage *m, const char *ptr, char **retval)
        }
        
        if (*ptr == MONO_TYPE_TYPEDBYREF){
-               g_string_append (str, "/*FIXME: what does typedbyref mean? */ typedbyref ");
+               g_string_append (str, " typedbyref ");
                ptr++;
        } else {
+               gboolean by_ref = 0;
                if (*ptr == MONO_TYPE_BYREF){
                        g_string_append (str, "[out] ");
                        ptr++;
+                       by_ref = 1;
                }
-               ptr = get_type (m, ptr, &allocated_type_string);
+               ptr = get_type (m, ptr, &allocated_type_string, context);
                g_string_append (str, allocated_type_string);
+               if (by_ref)
+                       g_string_append_c (str, '&');
                g_free (allocated_type_string);
        }
 
@@ -779,7 +1158,50 @@ get_param (MonoImage *m, const char *ptr, char **retval)
        return ptr;
 }
 
-static map_t param_map [] = {
+/**
+ * get_escaped_name
+ *
+ * Returns: An allocated escaped name. A name needs to be escaped
+ * because it might be an ilasm keyword.
+ */
+char*
+get_escaped_name (const char *name)
+{
+       const char *s;
+
+       g_assert (key_table);
+
+       if (strlen (name) == 0)
+               return g_strdup (name);
+
+       for (s = name; *s; s++) {
+               char *first, *result;
+
+               if (*s != '/')
+                       continue;
+
+               first = g_strndup (name, s-name);
+               result = g_strdup_printf ("%s/%s", get_escaped_name (first), get_escaped_name (s+1));
+               g_free (first);
+
+               return result;
+       }
+
+       for (s = name; *s; s++) {
+               if (isalnum (*s) || *s == '_' || *s == '$' || *s == '@' ||
+                   *s == '?' || *s == '.' || *s == 0 || *s == '!')
+                       continue;
+
+               return g_strdup_printf ("'%s'", name);
+       }
+       
+       if (g_hash_table_lookup (key_table, name))
+               return g_strdup_printf ("'%s'", name);
+                       
+       return g_strdup (name);
+}
+
+static dis_map_t param_map [] = {
        { PARAM_ATTRIBUTE_IN,                "[in] " },
        { PARAM_ATTRIBUTE_OUT,               "[out] " },
        { PARAM_ATTRIBUTE_OPTIONAL,          "optional " },
@@ -794,8 +1216,8 @@ param_flags (guint32 f)
        return g_strdup (flags (f, param_map));
 }
 
-static map_t field_access_map [] = {
-       { FIELD_ATTRIBUTE_COMPILER_CONTROLLED, "compilercontrolled " },
+static dis_map_t field_access_map [] = {
+       { FIELD_ATTRIBUTE_COMPILER_CONTROLLED, "privatescope " },
        { FIELD_ATTRIBUTE_PRIVATE,             "private " },
        { FIELD_ATTRIBUTE_FAM_AND_ASSEM,       "famandassem " },
        { FIELD_ATTRIBUTE_ASSEMBLY,            "assembly " },
@@ -805,7 +1227,7 @@ static map_t field_access_map [] = {
        { 0, NULL }
 };
 
-static map_t field_flags_map [] = {
+static dis_map_t field_flags_map [] = {
        { FIELD_ATTRIBUTE_STATIC,              "static " },
        { FIELD_ATTRIBUTE_INIT_ONLY,           "initonly " },
        { FIELD_ATTRIBUTE_LITERAL,             "literal " },
@@ -814,8 +1236,6 @@ static map_t field_flags_map [] = {
        { FIELD_ATTRIBUTE_PINVOKE_IMPL,        "FIXME:pinvokeimpl " },
        { FIELD_ATTRIBUTE_RT_SPECIAL_NAME,        "rtspecialname " },
        { FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL,        "hasfieldmarshal " },
-       { FIELD_ATTRIBUTE_HAS_DEFAULT,        "hasdefault " },
-       { FIELD_ATTRIBUTE_HAS_FIELD_RVA,        "hasfieldrva " },
        { 0, NULL }
 };
 
@@ -841,15 +1261,18 @@ field_flags (guint32 f)
  * Returns a stringifed representation of a MethodRefSig (22.2.2)
  */
 char *
-get_methodref_signature (MonoImage *m, guint32 blob_signature, const char *fancy_name)
+get_methodref_signature (MonoImage *m, guint32 blob_signature, const char *fancy_name,
+                        MonoGenericContext *context)
 {
        GString *res = g_string_new ("");
        const char *ptr = mono_metadata_blob_heap (m, blob_signature);
        char *allocated_ret_type, *s;
+       const char *cconv_str;
        gboolean seen_vararg = 0;
        int param_count, signature_len;
-       int i;
-       
+       int i, gen_count = 0;
+       int cconv;
+
        signature_len = mono_metadata_decode_value (ptr, &ptr);
 
        if (*ptr & 0x20){
@@ -859,22 +1282,32 @@ get_methodref_signature (MonoImage *m, guint32 blob_signature, const char *fancy
                        g_string_append (res, "instance "); /* has-this */
        }
 
-       if (*ptr & 0x05)
-               seen_vararg = 1;
+       if (*ptr & 0x10)
+               gen_count = 1;
+       cconv = *ptr & 0x0f;
+       cconv_str = map (cconv, call_conv_type_map);
+       if (strcmp (cconv_str, "default") != 0) {
+               g_string_append (res, cconv_str);
+               g_string_append (res, " ");
+       }
 
        ptr++;
+       if (gen_count)
+               gen_count = mono_metadata_decode_value (ptr, &ptr);
        param_count = mono_metadata_decode_value (ptr, &ptr);
-       ptr = get_ret_type (m, ptr, &allocated_ret_type);
-
-       g_string_append (res, allocated_ret_type);
+       if (cconv != 0xa) {
+               ptr = get_ret_type (m, ptr, &allocated_ret_type, context);
+               g_string_append (res, allocated_ret_type);
+               g_free (allocated_ret_type);
+       }
 
        if (fancy_name){
                g_string_append_c (res, ' ');
                g_string_append (res, fancy_name);
        }
-       
+        
        g_string_append (res, "(");
-       
+
        /*
         * param_count describes parameters *before* and *after*
         * the vararg sentinel
@@ -886,11 +1319,15 @@ get_methodref_signature (MonoImage *m, guint32 blob_signature, const char *fancy
                 * If ptr is a SENTINEL
                 */
                if (*ptr == 0x41){
-                       g_string_append (res, " varargs ");
-                       continue;
+                       if (!seen_vararg){
+                               g_string_append (res, "..., ");
+                               seen_vararg = 1;
+                       }
+
+                       ptr++;
                }
 
-               ptr = get_param (m, ptr, &param);
+               ptr = get_param (m, ptr, &param, context);
                g_string_append (res, param);
                if (i+1 != param_count)
                        g_string_append (res, ", ");
@@ -901,12 +1338,40 @@ get_methodref_signature (MonoImage *m, guint32 blob_signature, const char *fancy
        /*
         * cleanup and return
         */
-       g_free (allocated_ret_type);
        s = res->str;
        g_string_free (res, FALSE);
        return s;
 }
 
+/**
+ * Returns a stringifed representation of a field ref
+ */
+char *
+get_fieldref_signature (MonoImage *m, int idx, MonoGenericContext *context)
+{
+       guint32 cols [MONO_MEMBERREF_SIZE];
+       MonoGenericContext *new_context;
+       char *type, *esname;
+        char *sig;
+       char *full_sig;
+
+        mono_metadata_decode_row (&m->tables [MONO_TABLE_MEMBERREF],
+                                 idx - 1, cols, MONO_MEMBERREF_SIZE);
+
+       new_context = get_memberref_context (m, cols [MONO_MEMBERREF_CLASS], context);
+        sig = get_field_signature (m, cols [MONO_MEMBERREF_SIGNATURE], new_context);
+
+       type = get_memberref_parent (m, cols [MONO_MEMBERREF_CLASS], context);
+       esname = get_escaped_name (mono_metadata_string_heap (m, cols [MONO_MEMBERREF_NAME]));
+
+        full_sig = g_strdup_printf ("%s %s::%s", sig, type, esname);
+        g_free (sig);
+       g_free (type);
+       g_free (esname);
+        
+        return full_sig;
+}
+
 /**
  * get_field:
  * @m: metadata context
@@ -917,11 +1382,11 @@ get_methodref_signature (MonoImage *m, guint32 blob_signature, const char *fancy
  * the TypeDef table and locate the actual "owner" of the field
  */
 char *
-get_field (MonoImage *m, guint32 token)
+get_field (MonoImage *m, guint32 token, MonoGenericContext *context)
 {
        int idx = mono_metadata_token_index (token);
        guint32 cols [MONO_FIELD_SIZE];
-       char *sig, *res, *type;
+       char *sig, *res, *type, *estype, *esname;
        guint32 type_idx;
 
        /*
@@ -929,12 +1394,12 @@ get_field (MonoImage *m, guint32 token)
         * defined in another module/assembly, just like in get_method ()
         */
        if (mono_metadata_token_code (token) == MONO_TOKEN_MEMBER_REF) {
-               return g_strdup_printf ("fieldref-0x%08x", token);
+                return get_fieldref_signature (m, idx, context);
        }
        g_assert (mono_metadata_token_code (token) == MONO_TOKEN_FIELD_DEF);
 
        mono_metadata_decode_row (&m->tables [MONO_TABLE_FIELD], idx - 1, cols, MONO_FIELD_SIZE);
-       sig = get_field_signature (m, cols [MONO_FIELD_SIGNATURE]);
+       sig = get_field_signature (m, cols [MONO_FIELD_SIGNATURE], context);
 
        /*
         * To locate the actual "container" for this field, we have to scan
@@ -943,17 +1408,49 @@ get_field (MonoImage *m, guint32 token)
        type_idx = mono_metadata_typedef_from_field (m, idx);
 
        type = get_typedef (m, type_idx);
+       estype = get_escaped_name (type);
+       esname = get_escaped_name (mono_metadata_string_heap (m, cols [MONO_FIELD_NAME]));
        res = g_strdup_printf ("%s %s::%s",
-                              sig, type,
-                              mono_metadata_string_heap (m, cols [MONO_FIELD_NAME]));
+                       sig, estype, esname);
+
        g_free (type);
        g_free (sig);
+       g_free (estype);
+       g_free (esname);
 
        return res;
 }
 
+static MonoGenericContext *
+get_memberref_context (MonoImage *m, guint32 mrp_token, MonoGenericContext *context)
+{
+       MonoClass *klass;
+
+       /*
+        * mrp_index is a MemberRefParent coded index
+        */
+       guint32 table = mrp_token & 7;
+       guint32 idx = mrp_token >> 3;
+
+       switch (table){
+       case 0: /* TypeDef */
+               return (MonoGenericContext *) mono_metadata_load_generic_params (
+                       m, MONO_TOKEN_TYPE_DEF | idx, NULL);
+               
+       case 1: /* TypeRef */
+               return NULL;
+               
+       case 4: /* TypeSpec */
+               klass = mono_class_get_full (m, MONO_TOKEN_TYPE_SPEC | idx, context);
+               g_assert (klass);
+               return klass->generic_class ? klass->generic_class->context : NULL;
+       }
+       g_assert_not_reached ();
+       return NULL;
+}
+
 static char *
-get_memberref_parent (MonoImage *m, guint32 mrp_token)
+get_memberref_parent (MonoImage *m, guint32 mrp_token, MonoGenericContext *context)
 {
        /*
         * mrp_index is a MemberRefParent coded index
@@ -975,7 +1472,7 @@ get_memberref_parent (MonoImage *m, guint32 mrp_token)
                return g_strdup ("TODO:MethodDef");
                
        case 4: /* TypeSpec */
-               return get_typespec (m, idx);
+               return get_typespec (m, idx, FALSE, context);
        }
        g_assert_not_reached ();
        return NULL;
@@ -991,20 +1488,27 @@ get_memberref_parent (MonoImage *m, guint32 mrp_token)
  * the TypeDef table and locate the actual "owner" of the field
  */
 char *
-get_method (MonoImage *m, guint32 token)
+get_method_core (MonoImage *m, guint32 token, gboolean fullsig, MonoGenericContext *context)
 {
        int idx = mono_metadata_token_index (token);
        guint32 member_cols [MONO_MEMBERREF_SIZE], method_cols [MONO_METHOD_SIZE];
-       char *sig;
-       const char *name;
+       char *sig = NULL, *esname;
+       char *name;
 
        MonoMethod *mh;
 
-       mh = mono_get_method (m, token, NULL);
+       mh = mono_get_method_full (m, token, NULL, context);
        if (mh) {
-               sig = dis_stringify_object_with_class (m, mh->klass);
-               name = g_strdup_printf ("%s::%s", sig, mh->name);
+               if (mh->signature->is_inflated)
+                       context = ((MonoMethodInflated *) mh)->context;
+               esname = get_escaped_name (mh->name);
+               sig = dis_stringify_object_with_class (m, mh->klass, TRUE, TRUE);
+               if (show_tokens)
+                       name = g_strdup_printf ("%s/*%08x*/::%s", sig, token, esname);
+               else
+                       name = g_strdup_printf ("%s::%s", sig, esname);
                g_free (sig);
+               g_free (esname);
        } else
                name = NULL;
 
@@ -1013,29 +1517,207 @@ get_method (MonoImage *m, guint32 token)
                mono_metadata_decode_row (&m->tables [MONO_TABLE_METHOD], 
                                          idx - 1, method_cols, MONO_METHOD_SIZE);
 
-               sig = get_methodref_signature (m, method_cols [MONO_METHOD_SIGNATURE], name);
-               return sig;
+               sig = get_methodref_signature (m, method_cols [MONO_METHOD_SIGNATURE], name, context);
+               break;
                
        case MONO_TOKEN_MEMBER_REF: {
-               
                mono_metadata_decode_row (&m->tables [MONO_TABLE_MEMBERREF],
                                          idx - 1, member_cols, MONO_MEMBERREF_SIZE);
                if (!name)
                        name = g_strdup_printf ("%s::%s",
-                                       get_memberref_parent (m, member_cols [MONO_MEMBERREF_CLASS]),
-                                       mono_metadata_string_heap (m, member_cols [MONO_MEMBERREF_NAME]));
+                                               get_memberref_parent (m, member_cols [MONO_MEMBERREF_CLASS], context),
+                                               mono_metadata_string_heap (m, member_cols [MONO_MEMBERREF_NAME]));
                sig = get_methodref_signature (
-                       m, member_cols [MONO_MEMBERREF_SIGNATURE], name);
+                       m, member_cols [MONO_MEMBERREF_SIGNATURE], name, context);
+               break;
+       }
+       case MONO_TOKEN_METHOD_SPEC: {
+                mono_metadata_decode_row (&m->tables [MONO_TABLE_METHODSPEC],
+                                idx - 1, member_cols, MONO_METHODSPEC_SIZE);
+               token = member_cols [MONO_METHODSPEC_METHOD];
+                sig = get_methodspec (m, idx, token, name, context);
+               break;
+       }
+
+       default:
+               g_assert_not_reached ();
+       }
+
+       if (fullsig)
+               g_free (name);
+       else {
+               g_free (sig);
+               return name;
+       }
+       
+       if (show_tokens) {
+               char *retval = g_strdup_printf ("%s /* %08x */", sig, token);
+               g_free (sig);
+               return retval;
+       } else
                return sig;
+}
+
+char *
+get_method (MonoImage *m, guint32 token, MonoGenericContext *context)
+{
+       return get_method_core (m, token, TRUE, context);
+}
+
+/**
+ * get_methoddef
+ * @m: metadata context
+ * @idx: index into the method table
+ *
+ * Returns: A stringified version of the method signature.
+ */
+char *
+get_methoddef (MonoImage *m, guint32 idx)
+{
+        guint32 cols [MONO_METHOD_SIZE];
+       char *sig;
+       const char *name;
+
+       MonoMethod *mh;
+
+       mh = mono_get_method (m, MONO_TOKEN_METHOD_DEF | idx, NULL);
+       if (mh) {
+               sig = dis_stringify_object_with_class (m, mh->klass, TRUE, FALSE);
+               name = g_strdup_printf ("%s::%s", sig, mh->name);
+               g_free (sig);
+       } else
+               name = NULL;
+        mono_metadata_decode_row (&m->tables [MONO_TABLE_METHOD], 
+                        idx - 1, cols, MONO_METHOD_SIZE);
+        sig = get_methodref_signature (m, cols [MONO_METHOD_SIGNATURE], name, NULL);
+        
+        return sig;
+}
+
+char *
+get_method_type_param (MonoImage *m, guint32 blob_signature, MonoGenericContext *context)
+{
+       GString *res = g_string_new ("");
+       const char *ptr = mono_metadata_blob_heap (m, blob_signature);
+       int param_count;
+       int i = 0;
+       char *s;
+       
+       mono_metadata_decode_value (ptr, &ptr);
+       ptr++;
+       param_count = mono_metadata_decode_value (ptr, &ptr);
+       
+       g_string_append_c (res, '<');
+        
+       for (i = 0; i < param_count; i++){
+               char *param = NULL;
+
+               ptr = get_param (m, ptr, &param, context);
+               g_string_append (res, param);
+               if (i+1 != param_count)
+                       g_string_append (res, ", ");
+               g_free (param);
        }
-              
+       g_string_append_c (res, '>');
+        
+       s = res->str;
+       g_string_free (res, FALSE);
+       return s;
+}
+
+/**
+ * get_methodspec
+ *
+ * Returns: An allocated stringified version of the methodspec signature.
+ */
+
+char *
+get_methodspec (MonoImage *m, int idx, guint32 token, const char *fancy_name, MonoGenericContext *context)
+{
+        GString *res = g_string_new ("");
+       guint32 member_cols [MONO_MEMBERREF_SIZE], method_cols [MONO_METHOD_SIZE];
+        char *s, *type_param;
+        const char *ptr;
+       guint32 sig = 0;
+       int param_count, cconv, i, gen_count = 0;
+
+       switch (token & MONO_METHODDEFORREF_MASK) {
+       case MONO_METHODDEFORREF_METHODDEF:
+               mono_metadata_decode_row (&m->tables [MONO_TABLE_METHOD], 
+                                         (token >> MONO_METHODDEFORREF_BITS) - 1,
+                                         method_cols, MONO_METHOD_SIZE);
+               sig = method_cols [MONO_METHOD_SIGNATURE];
+               break;
+       case MONO_METHODDEFORREF_METHODREF:
+               mono_metadata_decode_row (&m->tables [MONO_TABLE_MEMBERREF], 
+                                         (token >> MONO_METHODDEFORREF_BITS) - 1,
+                                         member_cols, MONO_MEMBERREF_SIZE);
+               sig = member_cols [MONO_MEMBERREF_SIGNATURE];
+               break;
        default:
                g_assert_not_reached ();
        }
-       g_assert_not_reached ();
-       return NULL;
+
+       ptr = mono_metadata_blob_heap (m, sig);
+       mono_metadata_decode_value (ptr, &ptr);
+
+       if (*ptr & 0x20){
+               if (*ptr & 0x40)
+                       g_string_append (res, "explicit-this ");
+               else
+                       g_string_append (res, "instance "); /* has-this */
+       }
+
+       if (*ptr & 0x10)
+               gen_count = 1;
+       cconv = *ptr & 0x0f;
+       ptr++;
+       if (gen_count)
+               gen_count = mono_metadata_decode_value (ptr, &ptr);
+       param_count = mono_metadata_decode_value (ptr, &ptr);
+       if (cconv != 0xa) {
+                char *allocated_ret_type;
+               ptr = get_ret_type (m, ptr, &allocated_ret_type, context);
+               g_string_append (res, allocated_ret_type);
+               g_free (allocated_ret_type);
+       }
+
+       if (fancy_name){
+               g_string_append_c (res, ' ');
+               g_string_append (res, fancy_name);
+       }
+
+        mono_metadata_decode_row (&m->tables [MONO_TABLE_METHODSPEC],
+                        idx - 1, member_cols, MONO_METHODSPEC_SIZE);
+        token = member_cols [MONO_METHODSPEC_SIGNATURE];
+        type_param = get_method_type_param (m, token, context);
+        g_string_append (res, type_param);
+       g_string_append (res, " (");
+
+       /*
+         * methodspecs can not be varargs so we don't need to worry about that here
+         */
+         
+       for (i = 0; i < param_count; i++){
+               char *param = NULL;
+               
+               ptr = get_param (m, ptr, &param, context);
+               g_string_append (res, param);
+               if (i+1 != param_count)
+                       g_string_append (res, ", ");
+               g_free (param);
+       }
+       g_string_append (res, ")");
+       
+       /*
+        * cleanup and return
+        */
+       s = res->str;
+       g_string_free (res, FALSE);
+       return s;
 }
 
+
 /**
  * get_constant:
  * @m: metadata context
@@ -1047,17 +1729,17 @@ get_method (MonoImage *m, guint32 token)
 char *
 get_constant (MonoImage *m, MonoTypeEnum t, guint32 blob_index)
 {
-       const char *ptr = mono_metadata_blob_heap (m, blob_index);
+       const unsigned char *ptr = mono_metadata_blob_heap (m, blob_index);
        int len;
        
-       len = mono_metadata_decode_value (ptr, &ptr);
+       len = mono_metadata_decode_value (ptr, (const char**)&ptr);
        
        switch (t){
        case MONO_TYPE_BOOLEAN:
-               return g_strdup_printf ("%s", *ptr ? "true" : "false");
+               return g_strdup_printf ("%s", *ptr ? "bool(true)" : "bool(false)");
                
        case MONO_TYPE_CHAR:
-               return g_strdup_printf ("%c", *ptr); /* FIXME: unicode char */
+               return g_strdup_printf ("char(0x%04x)", read16(ptr)); 
                
        case MONO_TYPE_U1:
        case MONO_TYPE_I1:
@@ -1076,7 +1758,7 @@ get_constant (MonoImage *m, MonoTypeEnum t, guint32 blob_index)
                guint32 low, high;
                low = read32 (ptr);
                high = read32 (ptr + 4);
-               return g_strdup_printf ("0x%08x%08x", high, low);
+               return g_strdup_printf ("int64(0x%08x%08x)", high, low);
        }
        case MONO_TYPE_U8: {
                guint32 low, high;
@@ -1087,54 +1769,51 @@ get_constant (MonoImage *m, MonoTypeEnum t, guint32 blob_index)
        case MONO_TYPE_R4: {
                float r;
                readr4 (ptr, &r);
-               return g_strdup_printf ("%g", (double) r);
+               return g_strdup_printf ("float32(%g)", (double) r);
        }
        case MONO_TYPE_R8: {
                double r;
                readr8 (ptr, &r);
-               return g_strdup_printf ("%g", r);
+               return g_strdup_printf ("float64(%g)", r);
        }
        case MONO_TYPE_STRING: {
-               int i, j, e;
-               char *res;
-               e = len = 0;
-               for (i = 0; !ptr [i+1]; i += 2){
-                       len++;
-                       switch (ptr [i]) {
-                       case '"':
-                       case '\\':
-                       case '\n': /* add more */
-                               e++;
+               gchar *str;
+               int i, j, tspaces = (len%16);
+               GString *res = g_string_new ("bytearray (\n\t");
+
+               for(i = 1; i <= len; ++i) {
+                       g_string_append_printf(res, "%02x ", ptr[i-1]);
+
+                       if(i%16 == 0) {
+                               if(i == len)
+                                       g_string_append(res, ")// ");
+                               else
+                                       g_string_append(res, " // ");
+
+                               for(j = i-16; j < i; ++j) 
+                                       g_string_append_printf(res, "%c", isprint(ptr[j]) ? ptr[j] : '.');
+                               g_string_append(res, "\n\t");
                        }
                }
-               res = g_malloc (len + e + 3);
-               j = 1;
-               res [0] = '"';
-
-               for (i = 0; i < len; i += 2){
-                       switch(ptr[i]) {
-                       case '"': 
-                               res[j++] = '\\';
-                               res[j++] = '"';
-                       case '\\': 
-                               res[j++] = '\\';
-                               res[j++] = '\\';
-                       case '\n':
-                               res[j++] = '\\';
-                               res[j++] = 'n';
-                               break;
-                       default:
-                               res[j++] = isprint (ptr [i]) ? ptr [i] : '.';
-                               break;
-                       }
-               }
-               res[j++] = '"';
-               res[j] = 0;
-               return res;
+
+               if(tspaces) {
+                       g_string_append(res, ")  ");
+                       for(i = tspaces+1; i < 16; ++i)
+                               g_string_append_printf(res, "   ");
+
+                       g_string_append(res, " // ");
+                       for(i = len-tspaces; i < len; ++i)
+                               g_string_append_printf(res, "%c", isprint(ptr[i]) ? ptr[i] : '.');
+                       g_string_append(res, "\n\t");
+               } 
+
+               str = res->str;
+               g_string_free(res, FALSE);
+               return str;
        }
                
        case MONO_TYPE_CLASS:
-               return g_strdup ("CLASS CONSTANT.  MUST BE ZERO");
+               return g_strdup ("nullref");
                
        default:
                g_error ("Unknown MONO_TYPE (%d) on constant at Blob index (0x%08x)\n",
@@ -1153,19 +1832,43 @@ get_constant (MonoImage *m, MonoTypeEnum t, guint32 blob_index)
  * constant.
  */
 char *
-get_token (MonoImage *m, guint32 token)
+get_token (MonoImage *m, guint32 token, MonoGenericContext *context)
 {
+       char *temp, *result;
        guint32 idx = mono_metadata_token_index (token);
 
        switch (mono_metadata_token_code (token)){
        case MONO_TOKEN_FIELD_DEF:
-               return (get_field (m, token));
+               temp = get_field (m, token, context);
+               result = g_strdup_printf ("field %s", temp);
+               g_free (temp);
+               return result;
        case MONO_TOKEN_TYPE_DEF:
-               return get_typedef (m, idx);
+               temp = get_typedef (m, idx);
+               result = get_escaped_name (temp);
+               g_free (temp);
+               return result;
        case MONO_TOKEN_TYPE_REF:
                return get_typeref (m, idx);
        case MONO_TOKEN_TYPE_SPEC:
-               return get_typespec (m, idx);
+               return get_typespec (m, idx, TRUE, context);
+       case MONO_TOKEN_MEMBER_REF: {
+               guint32 cols [MONO_MEMBERREF_SIZE];
+               const char *sig;
+               mono_metadata_decode_row (&m->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
+               sig = mono_metadata_blob_heap (m, cols [MONO_MEMBERREF_SIGNATURE]);
+               mono_metadata_decode_blob_size (sig, &sig);
+               if (*sig == 0x6) { /* it's a field */
+                       temp = get_field (m, token, context);
+                       result = g_strdup_printf ("field %s", temp);
+                       g_free (temp);
+                       return result;
+               }
+               else {
+                       g_error ("Do not know how to decode tokens of type 0x%08x", token);
+               }
+               break;
+       }
        default:                
                g_error ("Do not know how to decode tokens of type 0x%08x", token);
        }
@@ -1184,9 +1887,9 @@ get_token (MonoImage *m, guint32 token)
  * at (token & 0xffffff) 
  */
 char *
-get_token_type (MonoImage *m, guint32 token)
+get_token_type (MonoImage *m, guint32 token, MonoGenericContext *context)
 {
-       char *temp = NULL, *s;
+       char *temp = NULL, *s = NULL;
        int idx;
 
        idx = mono_metadata_token_index (token);
@@ -1203,7 +1906,7 @@ get_token_type (MonoImage *m, guint32 token)
                break;
                
        case MONO_TOKEN_TYPE_SPEC:
-               s = get_typespec (m, idx);
+               s = get_typespec (m, idx, FALSE, context);
                break;
 
        default:
@@ -1235,7 +1938,7 @@ GList *
 dis_get_custom_attrs (MonoImage *m, guint32 token)
 {
        GList *list = NULL;
-       guint32 idx, i, j, len, mtoken;
+       guint32 idx, i, len, mtoken;
        guint32 cols [MONO_CUSTOM_ATTR_SIZE];
        MonoTableInfo *ca;
        char *method;
@@ -1243,29 +1946,32 @@ dis_get_custom_attrs (MonoImage *m, guint32 token)
        const char *val;
 
        idx = mono_metadata_token_index (token);
-       idx <<= CUSTOM_ATTR_BITS;
+       idx <<= MONO_CUSTOM_ATTR_BITS;
        
        switch (mono_metadata_token_table (token)) {
        case MONO_TABLE_TYPEDEF:
-               idx |= CUSTOM_ATTR_TYPEDEF;
+               idx |= MONO_CUSTOM_ATTR_TYPEDEF;
                break;
        case MONO_TABLE_ASSEMBLY:
-               idx |= CUSTOM_ATTR_ASSEMBLY;
+               idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
+               break;
+       case MONO_TABLE_MODULE:
+               idx |= MONO_CUSTOM_ATTR_MODULE;
                break;
        case MONO_TABLE_PROPERTY:
-               idx |= CUSTOM_ATTR_PROPERTY;
+               idx |= MONO_CUSTOM_ATTR_PROPERTY;
                break;
        case MONO_TABLE_EVENT:
-               idx |= CUSTOM_ATTR_EVENT;
+               idx |= MONO_CUSTOM_ATTR_EVENT;
                break;
        case MONO_TABLE_FIELD:
-               idx |= CUSTOM_ATTR_FIELDDEF;
+               idx |= MONO_CUSTOM_ATTR_FIELDDEF;
                break;
        case MONO_TABLE_METHOD:
-               idx |= CUSTOM_ATTR_METHODDEF;
+               idx |= MONO_CUSTOM_ATTR_METHODDEF;
                break;
        case MONO_TABLE_PARAM:
-               idx |= CUSTOM_ATTR_PARAMDEF;
+               idx |= MONO_CUSTOM_ATTR_PARAMDEF;
                break;
        default:
                g_print ("Missing custom attr get support for token 0x%08x\n", token);
@@ -1275,32 +1981,29 @@ dis_get_custom_attrs (MonoImage *m, guint32 token)
        ca = &m->tables [MONO_TABLE_CUSTOMATTRIBUTE];
        /* the table is not sorted */
        for (i = 0; i < ca->rows; ++i) {
+               char *dump;
                mono_metadata_decode_row (ca, i, cols, MONO_CUSTOM_ATTR_SIZE);
                if (cols [MONO_CUSTOM_ATTR_PARENT] != idx)
                        continue;
-               mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> CUSTOM_ATTR_TYPE_BITS;
-               switch (cols [MONO_CUSTOM_ATTR_TYPE] & CUSTOM_ATTR_TYPE_MASK) {
-               case CUSTOM_ATTR_TYPE_METHODDEF:
+               mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
+               switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
+               case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
                        mtoken |= MONO_TOKEN_METHOD_DEF;
                        break;
-               case CUSTOM_ATTR_TYPE_MEMBERREF:
+               case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
                        mtoken |= MONO_TOKEN_MEMBER_REF;
                        break;
                default:
                        g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
                        break;
                }
-               method = get_method (m, mtoken);
+               method = get_method (m, mtoken, NULL);
                val = mono_metadata_blob_heap (m, cols [MONO_CUSTOM_ATTR_VALUE]);
                len = mono_metadata_decode_value (val, &val);
                attr = g_string_new (".custom ");
-               g_string_sprintfa (attr, "%s = (", method);
-               for (j = 0; j < len; ++j) {
-                       if (len > 4 && !(j % 16))
-                               g_string_append (attr, "\n\t\t");
-                       g_string_sprintfa (attr, " %02X", (val [j] & 0xff));
-               }
-               g_string_append_c (attr, ')');
+               dump = data_dump (val, len, "\t\t");
+               g_string_sprintfa (attr, "%s = %s", method, dump);
+               g_free (dump);
                list = g_list_append (list, attr->str);
                g_string_free (attr, FALSE);
                g_free (method);
@@ -1348,6 +2051,7 @@ get_marshal_info (MonoImage *m, const char *blob) {
        case MONO_NATIVE_LPTSTR:
                return g_strdup ("lptstr");
        case MONO_NATIVE_BYVALTSTR:
+               size = mono_metadata_decode_value (blob + 1, &blob);
                return g_strdup_printf ("fixed sysstring [%d]", size);
        case MONO_NATIVE_IUNKNOWN:
                return g_strdup ("iunknown");
@@ -1360,6 +2064,7 @@ get_marshal_info (MonoImage *m, const char *blob) {
        case MONO_NATIVE_SAFEARRAY:
                return g_strdup ("safearray");
        case MONO_NATIVE_BYVALARRAY:
+               size = mono_metadata_decode_value (blob + 1, &blob);
                return g_strdup_printf ("fixed array [%d]", size);
        case MONO_NATIVE_INT:
                return g_strdup ("int");
@@ -1377,7 +2082,7 @@ get_marshal_info (MonoImage *m, const char *blob) {
                return g_strdup ("method");
        case MONO_NATIVE_ASANY:
                return g_strdup ("as any");
-       case MONO_NATIVE_ARRAY:
+       case MONO_NATIVE_LPARRAY:
                return g_strdup ("[]");
        case MONO_NATIVE_LPSTRUCT:
                return g_strdup ("lpstruct");
@@ -1390,3 +2095,435 @@ get_marshal_info (MonoImage *m, const char *blob) {
        }
 }
 
+void
+init_key_table (void)
+{
+       key_table = g_hash_table_new (g_str_hash, g_str_equal);
+
+       g_hash_table_insert (key_table, (char *) "9", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "abstract", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "add", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "add.ovf", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "add.ovf.un", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "algorithm", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "alignment", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "and", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ansi", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "any", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "arglist", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "array", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "as", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "assembly", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "assert", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "at", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "autochar", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "auto", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "beforefieldinit", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "beq", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "beq.s", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "bge", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "bge.s", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "bge.un", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "bge.un.s", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "bgt", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "bgt.s", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "bgt.un", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "bgt.un.s", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ble", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ble.s", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ble.un", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ble.un.s", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "blob", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "blob_object", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "blt", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "blt.s", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "blt.un", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "blt.un.s", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "bne.un", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "bne.un.s", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "bool", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "box", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "break", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "brfalse", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "brfalse.s", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "br", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "brinst", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "brinst.s", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "brnull", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "brnull.s", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "br.s", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "brtrue", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "brtrue.s", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "brzero", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "brzero.s", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "bstr", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "bytearray", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "byvalstr", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "call", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "calli", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "callmostderived", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "callvirt", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "carray", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "castclass", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "catch", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "cdecl", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ceq", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "cf", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "cgt", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "cgt.un", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "char", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "cil", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ckfinite", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "class", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "clsid", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "clt", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "clt.un", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "Compilercontrolled", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "const", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "conv.i1", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "conv.i2", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "conv.i4", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "conv.i8", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "conv.i", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "conv.ovf.i1", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "conv.ovf.i1.un", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "conv.ovf.i2", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "conv.ovf.i2.un", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "conv.ovf.i4", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "conv.ovf.i4.un", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "conv.ovf.i8", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "conv.ovf.i8.un", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "conv.ovf.i", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "conv.ovf.i.un", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "conv.ovf.u1", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "conv.ovf.u1.un", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "conv.ovf.u2", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "conv.ovf.u2.un", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "conv.ovf.u4", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "conv.ovf.u4.un", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "conv.ovf.u8", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "conv.ovf.u8.un", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "conv.ovf.u", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "conv.ovf.u.un", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "conv.r4", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "conv.r8", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "conv.r.un", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "conv.u1", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "conv.u2", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "conv.u4", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "conv.u8", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "conv.u", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "cpblk", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "cpobj", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "currency", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "custom", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "date", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "decimal", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "default", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "demand", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "deny", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "div", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "div.un", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "dup", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "endfault", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "endfilter", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "endfinally", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "endmac", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "enum", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "error", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "explicit", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "extends", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "extern", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "false", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "famandassem", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "family", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "famorassem", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "fastcall", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "fault", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "field", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "filetime", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "filter", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "final", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "finally", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "fixed", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "float32", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "float64", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "float", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "forwardref", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "fromunmanaged", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "handler", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "hidebysig", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "hresult", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "idispatch", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "il", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "illegal", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "implements", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "implicitcom", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "implicitres", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "import", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "in", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "inheritcheck", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "initblk", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "init", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "initobj", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "initonly", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "instance", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "int16", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "int32", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "int64", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "int8", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "interface", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "internalcall", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "int", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "isinst", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "iunknown", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "jmp", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "lasterr", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "lcid", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldarg.0", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldarg.1", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldarg.2", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldarg.3", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldarga", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldarga.s", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldarg", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldarg.s", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldc.i4.0", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldc.i4.1", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldc.i4.2", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldc.i4.3", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldc.i4.4", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldc.i4.5", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldc.i4.6", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldc.i4.7", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldc.i4.8", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldc.i4", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldc.i4.m1", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldc.i4.M1", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldc.i4.s", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldc.i8", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldc.r4", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldc.r8", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldelema", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldelem.i1", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldelem.i2", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldelem.i4", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldelem.i8", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldelem.i", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldelem.r4", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldelem.r8", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldelem.ref", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldelem.u1", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldelem.u2", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldelem.u4", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldelem.u8", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldflda", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldfld", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldftn", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldind.i1", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldind.i2", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldind.i4", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldind.i8", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldind.i", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldind.r4", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldind.r8", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldind.ref", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldind.u1", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldind.u2", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldind.u4", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldind.u8", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldlen", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldloc.0", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldloc.1", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldloc.2", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldloc.3", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldloca", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldloca.s", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldloc", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldloc.s", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldnull", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldobj", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldsflda", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldsfld", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldstr", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldtoken", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ldvirtftn", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "leave", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "leave.s", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "linkcheck", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "literal", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "localloc", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "lpstr", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "lpstruct", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "lptstr", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "lpvoid", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "lpwstr", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "managed", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "marshal", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "method", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "mkrefany", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "modopt", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "modreq", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "mul", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "mul.ovf", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "mul.ovf.un", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "native", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "neg", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "nested", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "newarr", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "newobj", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "newslot", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "noappdomain", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "noinlining", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "nomachine", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "nomangle", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "nometadata", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "noncasdemand", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "noncasinheritance", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "noncaslinkdemand", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "nop", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "noprocess", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "not", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "not_in_gc_heap", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "notremotable", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "notserialized", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "null", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "nullref", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "object", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "objectref", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "opt", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "optil", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "or", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "out", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "permitonly", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "pinned", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "pinvokeimpl", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "pop", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "prefix1", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "prefix2", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "prefix3", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "prefix4", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "prefix5", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "prefix6", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "prefix7", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "prefixref", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "prejitdeny", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "prejitgrant", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "preservesig", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "private", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "privatescope", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "protected", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "public", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "readonly", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "record", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "refany", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "refanytype", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "refanyval", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "rem", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "rem.un", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "reqmin", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "reqopt", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "reqrefuse", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "reqsecobj", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "request", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "ret", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "rethrow", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "retval", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "rtspecialname", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "runtime", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "safearray", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "sealed", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "sequential", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "serializable", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "shl", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "shr", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "shr.un", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "sizeof", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "special", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "specialname", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "starg", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "starg.s", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "static", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "stdcall", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "stelem.i1", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "stelem.i2", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "stelem.i4", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "stelem.i8", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "stelem.i", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "stelem.r4", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "stelem.r8", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "stelem.ref", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "stfld", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "stind.i1", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "stind.i2", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "stind.i4", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "stind.i8", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "stind.i", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "stind.r4", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "stind.r8", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "storage", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "stored_object", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "streamed_object", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "stream", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "strict", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "string", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "struct", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "synchronized", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "syschar", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "sysstring", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "tbstr", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "thiscall", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "tls", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "to", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "true", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "type", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "typedref", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "unicode", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "unmanagedexp", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "unmanaged", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "unsigned", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "userdefined", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "value", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "valuetype", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "vararg", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "variant", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "vector", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "virtual", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "void", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "wchar", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "winapi", GINT_TO_POINTER (TRUE));
+       g_hash_table_insert (key_table, (char *) "with", GINT_TO_POINTER (TRUE));
+}
+
+guint32
+method_dor_to_token (guint32 idx) {
+       switch (idx & MONO_METHODDEFORREF_MASK) {
+       case MONO_METHODDEFORREF_METHODDEF:
+               return MONO_TOKEN_METHOD_DEF | (idx >> MONO_METHODDEFORREF_BITS);
+       case MONO_METHODDEFORREF_METHODREF:
+               return MONO_TOKEN_MEMBER_REF | (idx >> MONO_METHODDEFORREF_BITS);
+       }
+       return -1;
+}
+
+char *
+get_method_override (MonoImage *m, guint32 token, MonoGenericContext *context)
+{
+       MonoTableInfo *t = &m->tables [MONO_TABLE_METHODIMPL];
+       int i;
+
+       for (i = 1; i <= t->rows; i++){
+               guint32 cols [MONO_METHODIMPL_SIZE];
+               guint32 decl, impl;
+
+               mono_metadata_decode_row (t, i - 1, cols, MONO_METHODIMPL_SIZE);
+
+               impl = method_dor_to_token (cols [MONO_METHODIMPL_BODY]);
+               decl = method_dor_to_token (cols [MONO_METHODIMPL_DECLARATION]);
+
+               if (token == impl)
+                       return get_method_core (m, decl, FALSE, context);
+       }
+
+       return NULL;
+}