Updated.
[mono.git] / mono / dis / get.c
index 3edb95a6ad0cd86c57a48127ae7a79d33c8099d8..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);
+get_memberref_parent (MonoImage *m, guint32 mrp_token, MonoGenericContext *context);
 
 GHashTable *key_table = NULL;
 gboolean show_method_tokens = FALSE;
@@ -166,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;
@@ -176,8 +179,8 @@ get_typespec (MonoImage *m, guint32 idx)
 
        MonoType *type;
 
-       type = mono_type_create_from_typespec (m, idx);
-               
+       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);
@@ -194,7 +197,7 @@ 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);
                }
@@ -209,7 +212,7 @@ get_typespec (MonoImage *m, guint32 idx)
                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, ' ');
@@ -225,21 +228,14 @@ 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;
 
-       case MONO_TYPE_VAR:
-       case MONO_TYPE_MVAR:
-               ptr = get_type (m, ptr-1, &s);
-               g_string_append (res, s);
-               g_free (s);
-               break;
-               
        default:
-               s = dis_stringify_type (m, type);
+               s = dis_stringify_type (m, type, is_def);
                g_string_append (res, s);
                g_free (s);
                break;
@@ -325,7 +321,7 @@ 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 = NULL;
        int table, idx;
@@ -348,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:
@@ -398,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;
 }
@@ -473,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;
        }
@@ -481,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->eklass->byval_arg);
+       type = dis_stringify_type (m, &array->eklass->byval_arg, is_def);
        g_string_append (s, type);
        g_free (type);
        g_string_append_c (s, '[');
@@ -535,7 +531,7 @@ dis_stringify_param (MonoImage *m, MonoType *param)
        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);
+       t = dis_stringify_type (m, param, TRUE);
        result = g_strjoin(attribs[0] ? " ":"", attribs, t, NULL);
        g_free (t);
        g_free (attribs);
@@ -551,44 +547,67 @@ dis_stringify_param (MonoImage *m, MonoType *param)
  * Returns: Allocated stringified generic parameters
  */
 char*
-get_generic_param (MonoImage *m, int table_type, guint32 row)
+get_generic_param (MonoImage *m, MonoGenericContainer *container)
 {
-        MonoTableInfo *t = &m->tables [MONO_TABLE_GENERICPARAM];
-        GString *result = g_string_new ("");
-        char *retval;
-       guint32 cols [MONO_GENERICPARAM_SIZE];
-       int i, own_tok, table, idx, found_count;
+        GString *result;
+       char *retval;
+       int i;
 
-        g_assert (table_type != MONO_TYPEORMETHOD_TYPE || table_type != MONO_TYPEORMETHOD_METHOD);
-        
-        found_count = 0;
-       for (i = 1; i <= t->rows; i++) {
-               mono_metadata_decode_row (t, i-1, cols, MONO_GENERICPARAM_SIZE);
-                own_tok = cols [MONO_GENERICPARAM_OWNER];
-                table = own_tok & MONO_TYPEORMETHOD_MASK;
-                idx = own_tok >> MONO_TYPEORMETHOD_BITS;
-                
-                if (table != table_type || idx != row)
-                        continue;
-
-                if (found_count == 0)
-                        g_string_append_printf (result, "<%s",
-                                        mono_metadata_string_heap (m, cols [MONO_GENERICPARAM_NAME]));
-                else
-                        g_string_append_printf (result, ", %s",
-                                        mono_metadata_string_heap (m, cols [MONO_GENERICPARAM_NAME]));
-                found_count++;
+       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);
        }
 
-        if (found_count)
-                g_string_append_c (result, '>');
+       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, gboolean fully_qualified)
+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];
@@ -599,6 +618,7 @@ dis_stringify_method_signature (MonoImage *m, MonoMethodSignature *method, int m
        char *type = NULL;
        char *gen_param = NULL;
        GString *result = g_string_new ("");
+       MonoGenericContainer *container = NULL;
        int i;
         
        g_assert (method || methoddef_row);
@@ -611,11 +631,20 @@ dis_stringify_method_signature (MonoImage *m, MonoMethodSignature *method, int m
                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, methoddef_row, sig, &sig);
+                       method = mono_metadata_parse_method_signature_full (m, context, methoddef_row, sig, &sig);
                        free_method = 1;
-               }      
-                gen_param = get_generic_param (m, 1, methoddef_row);
+               } 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);
@@ -699,12 +728,34 @@ dis_stringify_function_ptr (MonoImage *m, MonoMethodSignature *method)
        return retval;
 }
 
+static char *
+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)
+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_VALUETYPE ? "valuetype" : "class" ;
+       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 */
@@ -721,28 +772,18 @@ dis_stringify_object_with_class (MonoImage *m, MonoClass *c, gboolean prefix)
                }
        }
 
-       if (c->nested_in) {
-               result = g_strdup_printf ("%s%s%s/%s", c->nested_in->name_space, 
-                               *c->nested_in->name_space?".":"", c->nested_in->name,
-                               c->name);
-       } else {
-               result = g_strdup_printf ("%s%s%s", c->name_space, 
-                               *c->name_space?".":"", c->name);
-       }
-       
-       esname = get_escaped_name (result);
-       g_free (result);
+       esname = get_escaped_class_name (c);
 
-       if (c->generic_inst) {
-               MonoGenericInst *ginst = c->generic_inst;
+       if (c->generic_class) {
+               MonoGenericClass *gclass = c->generic_class;
                GString *str = g_string_new ("");
                int i;
 
-               for (i = 0; i < ginst->type_argc; i++){
-                       char *t = dis_stringify_type (m, ginst->type_argv [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 != ginst->type_argc)
+                       if (i+1 != gclass->inst->type_argc)
                                g_string_append (str, ", ");
                        g_free (t);
                }
@@ -751,7 +792,7 @@ dis_stringify_object_with_class (MonoImage *m, MonoClass *c, gboolean prefix)
        }
 
 
-       result = g_strdup_printf ("%s %s%s%s", prefix ? otype : "", assemblyref?assemblyref:"",
+       result = g_strdup_printf ("%s%s%s%s", prefix ? otype : "", assemblyref?assemblyref:"",
                                  esname, generic?generic:"");
        
        g_free (generic);
@@ -762,14 +803,14 @@ dis_stringify_object_with_class (MonoImage *m, MonoClass *c, gboolean prefix)
 }
 
 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, TRUE);
+       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;
@@ -801,7 +842,7 @@ 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;
@@ -812,7 +853,7 @@ dis_stringify_type (MonoImage *m, MonoType *type)
        }
        case MONO_TYPE_PTR: {
                char *child_type;
-               child_type = dis_stringify_type (m, type->data.type);
+               child_type = dis_stringify_type (m, type->data.type, is_def);
                
                bare = g_strdup_printf ("%s*", child_type);
                g_free (child_type);
@@ -820,34 +861,43 @@ dis_stringify_type (MonoImage *m, MonoType *type)
        }
        case MONO_TYPE_SZARRAY: {
                char *child_type;
-               child_type = dis_stringify_type (m, &type->data.klass->byval_arg);
+               child_type = dis_stringify_type (m, &type->data.klass->byval_arg, is_def);
                
                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:
-               bare = g_strdup_printf ("!!%d", type->data.generic_param->num);
+               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:
-               bare = g_strdup_printf ("!%d", type->data.generic_param->num);
+               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_inst->generic_type);
+               char *generic_type = dis_stringify_type (
+                       m, &type->data.generic_class->container_class->byval_arg, is_def);
 
-               for (i = 0; i < type->data.generic_inst->type_argc; i++){
-                       char *t = dis_stringify_type (m, type->data.generic_inst->type_argv [i]);
+               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_inst->type_argc)
+                       if (i+1 != type->data.generic_class->inst->type_argc)
                                g_string_append (str, ", ");
                        g_free (t);
                }
@@ -885,7 +935,7 @@ 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)
 {
        const char *start = ptr;
        guint32 type;
@@ -901,7 +951,7 @@ get_type (MonoImage *m, const char *ptr, char **result)
        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);
+               char *temp = dis_stringify_object_with_class (m, klass, TRUE, FALSE);
 
                if (show_tokens) {
                        *result = g_strdup_printf ("%s/*%08x*/", temp, token);
@@ -916,7 +966,7 @@ get_type (MonoImage *m, const char *ptr, char **result)
                int count, i;
                char *temp;
 
-               ptr = get_type (m, ptr, &temp);
+               ptr = get_type (m, ptr, &temp, context);
                g_string_append (str, temp);
                g_free (temp);
 
@@ -926,7 +976,7 @@ get_type (MonoImage *m, const char *ptr, char **result)
                for (i = 0; i < count; i++) {
                        if (i)
                                g_string_append (str, ",");
-                       ptr = get_type (m, ptr, &temp);
+                       ptr = get_type (m, ptr, &temp, context);
                        g_string_append (str, temp);
                }
 
@@ -937,8 +987,8 @@ get_type (MonoImage *m, const char *ptr, char **result)
        }
 
        default:
-               t = mono_metadata_parse_type (m, MONO_PARSE_TYPE, 0, start, &ptr);
-               *result = dis_stringify_type (m, t);
+               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;
        }
@@ -951,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);
@@ -967,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",
@@ -1027,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;
@@ -1052,7 +1102,7 @@ get_ret_type (MonoImage *m, const char *ptr, char **ret_type)
                        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);
        }
@@ -1074,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;
@@ -1091,12 +1141,12 @@ get_param (MonoImage *m, const char *ptr, char **retval)
                ptr++;
        } else {
                gboolean by_ref = 0;
-                if (*ptr == MONO_TYPE_BYREF){
+               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, '&');
@@ -1125,7 +1175,21 @@ get_escaped_name (const char *name)
                return g_strdup (name);
 
        for (s = name; *s; s++) {
-               if (isalnum (*s) || *s == '_' || *s == '$' || *s == '@' || *s == '?' || *s == '.' || *s == 0)
+               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);
@@ -1153,7 +1217,7 @@ param_flags (guint32 f)
 }
 
 static dis_map_t field_access_map [] = {
-       { FIELD_ATTRIBUTE_COMPILER_CONTROLLED, "compilercontrolled " },
+       { FIELD_ATTRIBUTE_COMPILER_CONTROLLED, "privatescope " },
        { FIELD_ATTRIBUTE_PRIVATE,             "private " },
        { FIELD_ATTRIBUTE_FAM_AND_ASSEM,       "famandassem " },
        { FIELD_ATTRIBUTE_ASSEMBLY,            "assembly " },
@@ -1197,7 +1261,8 @@ 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);
@@ -1207,7 +1272,7 @@ get_methodref_signature (MonoImage *m, guint32 blob_signature, const char *fancy
        int param_count, signature_len;
        int i, gen_count = 0;
        int cconv;
-       
+
        signature_len = mono_metadata_decode_value (ptr, &ptr);
 
        if (*ptr & 0x20){
@@ -1231,7 +1296,7 @@ get_methodref_signature (MonoImage *m, guint32 blob_signature, const char *fancy
                gen_count = mono_metadata_decode_value (ptr, &ptr);
        param_count = mono_metadata_decode_value (ptr, &ptr);
        if (cconv != 0xa) {
-               ptr = get_ret_type (m, ptr, &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);
        }
@@ -1262,7 +1327,7 @@ get_methodref_signature (MonoImage *m, guint32 blob_signature, const char *fancy
                        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, ", ");
@@ -1282,20 +1347,27 @@ get_methodref_signature (MonoImage *m, guint32 blob_signature, const char *fancy
  * Returns a stringifed representation of a field ref
  */
 char *
-get_fieldref_signature (MonoImage *m, int idx)
+get_fieldref_signature (MonoImage *m, int idx, MonoGenericContext *context)
 {
-        guint32 cols [MONO_MEMBERREF_SIZE];
+       guint32 cols [MONO_MEMBERREF_SIZE];
+       MonoGenericContext *new_context;
+       char *type, *esname;
         char *sig;
-        char *full_sig;
+       char *full_sig;
 
         mono_metadata_decode_row (&m->tables [MONO_TABLE_MEMBERREF],
-                        idx - 1, cols, MONO_MEMBERREF_SIZE);
+                                 idx - 1, cols, MONO_MEMBERREF_SIZE);
 
-        sig = get_field_signature (m, cols [MONO_MEMBERREF_SIGNATURE]);
-        full_sig = g_strdup_printf ("%s %s::%s", sig,
-                        get_memberref_parent (m, cols [MONO_MEMBERREF_CLASS]),
-                        mono_metadata_string_heap (m, cols [MONO_MEMBERREF_NAME]));
+       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;
 }
@@ -1310,7 +1382,7 @@ get_fieldref_signature (MonoImage *m, int idx)
  * 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];
@@ -1322,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 get_fieldref_signature (m, idx);
+                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
@@ -1349,8 +1421,36 @@ get_field (MonoImage *m, guint32 token)
        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
@@ -1372,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;
@@ -1388,19 +1488,21 @@ get_memberref_parent (MonoImage *m, guint32 mrp_token)
  * the TypeDef table and locate the actual "owner" of the field
  */
 char *
-get_method_core (MonoImage *m, guint32 token, gboolean fullsig)
+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 = NULL, *esname;
-       const char *name;
+       char *name;
 
        MonoMethod *mh;
 
-       mh = mono_get_method (m, token, NULL);
+       mh = mono_get_method_full (m, token, NULL, context);
        if (mh) {
+               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);
+               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
@@ -1415,7 +1517,7 @@ get_method_core (MonoImage *m, guint32 token, gboolean fullsig)
                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);
+               sig = get_methodref_signature (m, method_cols [MONO_METHOD_SIGNATURE], name, context);
                break;
                
        case MONO_TOKEN_MEMBER_REF: {
@@ -1423,17 +1525,17 @@ get_method_core (MonoImage *m, guint32 token, gboolean fullsig)
                                          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);
+                sig = get_methodspec (m, idx, token, name, context);
                break;
        }
 
@@ -1457,9 +1559,9 @@ get_method_core (MonoImage *m, guint32 token, gboolean fullsig)
 }
 
 char *
-get_method (MonoImage *m, guint32 token)
+get_method (MonoImage *m, guint32 token, MonoGenericContext *context)
 {
-       return get_method_core (m, token, TRUE);
+       return get_method_core (m, token, TRUE, context);
 }
 
 /**
@@ -1480,20 +1582,20 @@ get_methoddef (MonoImage *m, guint32 idx)
 
        mh = mono_get_method (m, MONO_TOKEN_METHOD_DEF | idx, NULL);
        if (mh) {
-               sig = dis_stringify_object_with_class (m, mh->klass, TRUE);
+               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);
+        sig = get_methodref_signature (m, cols [MONO_METHOD_SIGNATURE], name, NULL);
         
         return sig;
 }
 
 char *
-get_method_type_param (MonoImage *m, guint32 blob_signature)
+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);
@@ -1509,8 +1611,8 @@ get_method_type_param (MonoImage *m, guint32 blob_signature)
         
        for (i = 0; i < param_count; i++){
                char *param = NULL;
-               
-               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, ", ");
@@ -1530,7 +1632,7 @@ get_method_type_param (MonoImage *m, guint32 blob_signature)
  */
 
 char *
-get_methodspec (MonoImage *m, int idx, guint32 token, const char *fancy_name)
+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];
@@ -1575,7 +1677,7 @@ get_methodspec (MonoImage *m, int idx, guint32 token, const char *fancy_name)
        param_count = mono_metadata_decode_value (ptr, &ptr);
        if (cconv != 0xa) {
                 char *allocated_ret_type;
-               ptr = get_ret_type (m, ptr, &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);
        }
@@ -1588,7 +1690,7 @@ get_methodspec (MonoImage *m, int idx, guint32 token, const char *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);
+        type_param = get_method_type_param (m, token, context);
         g_string_append (res, type_param);
        g_string_append (res, " (");
 
@@ -1599,7 +1701,7 @@ get_methodspec (MonoImage *m, int idx, guint32 token, const char *fancy_name)
        for (i = 0; i < param_count; i++){
                char *param = NULL;
                
-               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, ", ");
@@ -1730,23 +1832,26 @@ 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:
-               temp = 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;
@@ -1754,7 +1859,7 @@ get_token (MonoImage *m, guint32 token)
                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);
+                       temp = get_field (m, token, context);
                        result = g_strdup_printf ("field %s", temp);
                        g_free (temp);
                        return result;
@@ -1782,7 +1887,7 @@ 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 = NULL;
        int idx;
@@ -1801,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:
@@ -1892,7 +1997,7 @@ dis_get_custom_attrs (MonoImage *m, guint32 token)
                        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 ");
@@ -1995,7 +2100,7 @@ init_key_table (void)
 {
        key_table = g_hash_table_new (g_str_hash, g_str_equal);
 
-       /* auto generated */
+       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));
@@ -2011,8 +2116,8 @@ init_key_table (void)
        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 *) "auto", 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));
@@ -2023,7 +2128,6 @@ init_key_table (void)
        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 *) "9", 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));
@@ -2039,15 +2143,15 @@ init_key_table (void)
        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 *) "br", GINT_TO_POINTER (TRUE));
-       g_hash_table_insert (key_table, (char *) "br.s", 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));
@@ -2074,14 +2178,13 @@ init_key_table (void)
        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.i", 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.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.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));
@@ -2090,8 +2193,8 @@ init_key_table (void)
        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.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.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));
@@ -2100,14 +2203,16 @@ init_key_table (void)
        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.r.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.u", 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));
@@ -2115,7 +2220,6 @@ init_key_table (void)
        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 *) "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));
@@ -2135,7 +2239,6 @@ init_key_table (void)
        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 *) "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));
@@ -2143,9 +2246,9 @@ init_key_table (void)
        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 *) "float", 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));
@@ -2160,32 +2263,31 @@ init_key_table (void)
        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 *) "init", 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 *) "int", 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", 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 *) "ldarg.s", 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 *) "ldc.i4", 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));
@@ -2195,17 +2297,19 @@ init_key_table (void)
        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.M1", 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 *) "ldelem.i", 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));
@@ -2213,15 +2317,14 @@ init_key_table (void)
        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 *) "ldelema", GINT_TO_POINTER (TRUE));
-       g_hash_table_insert (key_table, (char *) "ldfld", 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.i", 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));
@@ -2230,18 +2333,18 @@ init_key_table (void)
        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", 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 *) "ldloc.s", 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 *) "ldsfld", 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));
@@ -2308,7 +2411,7 @@ init_key_table (void)
        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 *) "Compilercontrolled", 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));
@@ -2342,25 +2445,54 @@ init_key_table (void)
        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 *) "stdcall", 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.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.i", 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
@@ -2375,7 +2507,7 @@ method_dor_to_token (guint32 idx) {
 }
 
 char *
-get_method_override (MonoImage *m, guint32 token)
+get_method_override (MonoImage *m, guint32 token, MonoGenericContext *context)
 {
        MonoTableInfo *t = &m->tables [MONO_TABLE_METHODIMPL];
        int i;
@@ -2390,7 +2522,7 @@ get_method_override (MonoImage *m, guint32 token)
                decl = method_dor_to_token (cols [MONO_METHODIMPL_DECLARATION]);
 
                if (token == impl)
-                       return get_method_core (m, decl, FALSE);
+                       return get_method_core (m, decl, FALSE, context);
        }
 
        return NULL;