Merge pull request #5353 from jonpryor/jonp-mono-api-html-ignore-class-removal
[mono.git] / mono / dis / get.c
index de99c35081dcc99cba3815b5d8562b57ec664c28..f5b64acdd0dab72058234fb16f54291d593a7e47 100755 (executable)
@@ -6,6 +6,7 @@
  *
  * (C) 2001 Ximian, Inc.
  * Copyright 2012 Xamarin Inc
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 #include <config.h>
 #include <stdio.h>
 #include <mono/utils/mono-compiler.h>
 #include <mono/metadata/class.h>
 #include <mono/metadata/marshal.h>
+#include <mono/metadata/metadata-internals.h>
 
 extern gboolean substitute_with_mscorlib_p;
 
+static char *
+get_token_comment (const char *prefix, guint32 token);
+
 static MonoGenericContainer *
 get_memberref_container (MonoImage *m, guint32 mrp_token, MonoGenericContainer *container);
 
@@ -57,7 +62,7 @@ get_typedef (MonoImage *m, int idx)
         /* 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;
+       tstring = get_token_comment (NULL, token);
         if (token) {
                 char *outer;
                 
@@ -256,11 +261,12 @@ get_typespec (MonoImage *m, guint32 idx, gboolean is_def, MonoGenericContainer *
 
        if (show_tokens) {
                int token = mono_metadata_make_token (MONO_TABLE_TYPESPEC, idx);
-               result = g_strdup_printf ("%s/*%08x*/", res->str, token);
-       } else
+               result = get_token_comment (res->str, token);
+               g_string_free (res, TRUE);
+       } else {
                result = res->str;
-
-       g_string_free (res, FALSE);
+               g_string_free (res, FALSE);
+       }
 
        return result;
 }
@@ -314,7 +320,7 @@ get_typeref (MonoImage *m, int idx)
 
        if (show_tokens) {
                int token = mono_metadata_make_token (MONO_TABLE_TYPEREF, idx);
-               char *temp = g_strdup_printf ("%s/*%08x*/", ret, token);
+               char *temp = get_token_comment (ret, token);
                g_free (ret);
                ret = temp;
        }
@@ -1101,8 +1107,8 @@ dis_stringify_object_with_class (MonoImage *m, MonoClass *c, gboolean prefix, gb
 
        esname = get_escaped_class_name (c);
 
-       if (c->generic_class) {
-               MonoGenericClass *gclass = c->generic_class;
+       if (mono_class_is_ginst (c)) {
+               MonoGenericClass *gclass = mono_class_get_generic_class (c);
                MonoGenericInst *inst = gclass->context.class_inst;
                GString *str = g_string_new ("");
                int i;
@@ -1268,6 +1274,7 @@ dis_stringify_type (MonoImage *m, MonoType *type, gboolean is_def)
 const char *
 get_type (MonoImage *m, const char *ptr, char **result, gboolean is_def, MonoGenericContainer *container)
 {
+       MonoError error;
        const char *start = ptr;
        guint32 type;
        MonoType *t;
@@ -1281,15 +1288,17 @@ get_type (MonoImage *m, const char *ptr, char **result, gboolean is_def, MonoGen
        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);
+               MonoClass *klass = mono_class_get_checked (m, token, &error);
                char *temp;
-               if (klass)
+               if (klass) {
                        temp = dis_stringify_object_with_class (m, klass, TRUE, FALSE);
-               else
-                       temp = g_strdup_printf ("<BROKEN CLASS token_%8x>", token);
+               } else  {
+                       temp = g_strdup_printf ("<BROKEN CLASS token_%8x due to %s>", token, mono_error_get_message (&error));
+                       mono_error_cleanup (&error);
+               }
 
                if (show_tokens) {
-                       *result = g_strdup_printf ("%s/*%08x*/", temp, token);
+                       *result = get_token_comment (temp, token);
                        g_free (temp);
                } else
                        *result = temp;
@@ -1322,23 +1331,12 @@ get_type (MonoImage *m, const char *ptr, char **result, gboolean is_def, MonoGen
        }
 
        default:
-               t = mono_metadata_parse_type_full (m, container, 0, start, &ptr);
+               t = mono_metadata_parse_type_checked (m, container, 0, FALSE, start, &ptr, &error);
                if (t) {
                        *result = dis_stringify_type (m, t, is_def);
                } else {
-                       GString *err = g_string_new ("@!#$<InvalidType>$#!@");
-                       if (container)
-                               t = mono_metadata_parse_type_full (m, NULL, 0, start, &ptr);
-                       if (t) {
-                               char *name = dis_stringify_type (m, t, is_def);
-                               g_warning ("Encountered a generic type inappropriate for its context");
-                               g_string_append (err, " // ");
-                               g_string_append (err, name);
-                               g_free (name);
-                       } else {
-                               g_warning ("Encountered an invalid type");
-                       }
-                       *result = g_string_free (err, FALSE);
+                       *result = g_strdup_printf ("Invalid type due to %s", mono_error_get_message (&error));
+                       mono_error_cleanup (&error);
                }
 
                break;
@@ -1775,6 +1773,25 @@ get_fieldref_signature (MonoImage *m, int idx, MonoGenericContainer *container)
         return full_sig;
 }
 
+/**
+ * get_token_comment:
+ *
+ * If show_tokens is TRUE, return "prefix""token(table)".
+ * If show_tokens is FALSE, return "prefix" or NULL if prefix is NULL.
+ * Caller is responsible for freeing.
+ */
+char *
+get_token_comment (const char *prefix, guint32 token)
+{
+       if (!show_tokens)
+               return prefix ? g_strdup_printf ("%s", prefix) : NULL;
+       gint32 tableidx = mono_metadata_token_table (token);
+       if ((tableidx < 0) || (tableidx > MONO_TABLE_LAST))
+               return g_strdup_printf ("%s/*%08x*/", prefix ? prefix : "", token);
+       else
+               return g_strdup_printf ("%s/*%08x(%s)*/", prefix ? prefix : "", token, mono_meta_table_name (tableidx));
+}
+
 /**
  * get_field:
  * @m: metadata context
@@ -1789,7 +1806,7 @@ get_field (MonoImage *m, guint32 token, MonoGenericContainer *container)
 {
        int idx = mono_metadata_token_index (token);
        guint32 cols [MONO_FIELD_SIZE];
-       char *sig, *res, *type, *estype, *esname;
+       char *sig, *res, *type, *estype, *esname, *token_comment;
        guint32 type_idx;
 
        /*
@@ -1818,16 +1835,20 @@ get_field (MonoImage *m, guint32 token, MonoGenericContainer *container)
        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%s",
+       token_comment = get_token_comment (NULL, token);
+       res = g_strdup_printf ("%s %s%s%s%s",
                        sig, 
                        estype ? estype : "",
                        estype ? "::" : "",
-                       esname);
+                       esname,
+                       token_comment ? token_comment : ""
+               );
 
        g_free (type);
        g_free (sig);
        g_free (estype);
        g_free (esname);
+       g_free (token_comment);
 
        return res;
 }
@@ -1853,7 +1874,7 @@ get_memberref_container (MonoImage *m, guint32 mrp_token, MonoGenericContainer *
        case 4: /* TypeSpec */
                klass = mono_class_get_full (m, MONO_TOKEN_TYPE_SPEC | idx, (MonoGenericContext *) container);
                g_assert (klass);
-               return klass->generic_class ? klass->generic_class->container_class->generic_container : NULL;
+               return mono_class_is_ginst (klass) ? mono_class_get_generic_container (mono_class_get_generic_class (klass)->container_class) : NULL;
        }
        g_assert_not_reached ();
        return NULL;
@@ -1900,6 +1921,7 @@ get_memberref_parent (MonoImage *m, guint32 mrp_token, MonoGenericContainer *con
 static char *
 get_method_core (MonoImage *m, guint32 token, gboolean fullsig, MonoGenericContainer *container)
 {
+       MonoError error;
        int idx = mono_metadata_token_index (token);
        guint32 member_cols [MONO_MEMBERREF_SIZE], method_cols [MONO_METHOD_SIZE];
        char *sig = NULL, *esname;
@@ -1908,20 +1930,21 @@ get_method_core (MonoImage *m, guint32 token, gboolean fullsig, MonoGenericConta
        MonoMethod *mh;
        MonoGenericContainer *type_container = container;
 
-       mh = mono_get_method_full (m, token, NULL, (MonoGenericContext *) container);
+       mh = mono_get_method_checked (m, token, NULL, (MonoGenericContext *) container, &error);
        if (mh) {
                if (mono_method_signature (mh)->is_inflated)
                        container = mono_method_get_generic_container (((MonoMethodInflated *) mh)->declaring);
                esname = get_escaped_name (mh->name);
                sig = dis_stringify_type (m, &mh->klass->byval_arg, TRUE);
-               if (show_tokens)
-                       name = g_strdup_printf ("%s/*%08x*/%s%s", sig ? sig : "", token, sig ? "::" : "", esname);
-               else
-                       name = g_strdup_printf ("%s%s%s", sig ? sig : "", sig ? "::" : "", esname);
+               char *token_comment = get_token_comment (NULL, token);
+               name = g_strdup_printf ("%s%s%s%s", sig ? sig : "", token_comment ? token_comment : "", sig ? "::" : "", esname);
                g_free (sig);
                g_free (esname);
-       } else
+               g_free (token_comment);
+       } else {
                name = NULL;
+               mono_error_cleanup (&error);
+       }
 
        switch (mono_metadata_token_code (token)){
        case MONO_TOKEN_METHOD_DEF:
@@ -1982,7 +2005,7 @@ get_method_core (MonoImage *m, guint32 token, gboolean fullsig, MonoGenericConta
        }
        
        if (show_tokens) {
-               char *retval = g_strdup_printf ("%s /* %08x */", sig, token);
+               char *retval = get_token_comment (sig, token);
                g_free (sig);
                return retval;
        } else
@@ -2005,13 +2028,14 @@ get_method (MonoImage *m, guint32 token, MonoGenericContainer *container)
 char *
 get_methoddef (MonoImage *m, guint32 idx)
 {
-        guint32 cols [MONO_METHOD_SIZE];
+       MonoError error;
+       guint32 cols [MONO_METHOD_SIZE];
        char *sig;
        const char *name;
 
        MonoMethod *mh;
 
-       mh = mono_get_method (m, MONO_TOKEN_METHOD_DEF | idx, NULL);
+       mh = mono_get_method_checked (m, MONO_TOKEN_METHOD_DEF | idx, NULL, NULL, &error);
        if (mh) {
                sig = dis_stringify_type (m, &mh->klass->byval_arg, FALSE);
                name = g_strdup_printf ("%s%s%s", 
@@ -2019,13 +2043,15 @@ get_methoddef (MonoImage *m, guint32 idx)
                                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);
+       } else {
+               name = g_strdup_printf ("!bad-method-name!");
+               mono_error_cleanup (&error);
+       }
+    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);
         
-        return sig;
+       return sig;
 }
 
 char *
@@ -2068,7 +2094,8 @@ get_method_type_param (MonoImage *m, guint32 blob_signature, MonoGenericContaine
 char *
 get_methodspec (MonoImage *m, int idx, guint32 token, const char *fancy_name, MonoGenericContainer *type_container)
 {
-        GString *res = g_string_new ("");
+       MonoError error;
+       GString *res = g_string_new ("");
        guint32 member_cols [MONO_MEMBERREF_SIZE], method_cols [MONO_METHOD_SIZE];
         char *s, *type_param;
         const char *ptr;
@@ -2097,8 +2124,13 @@ get_methodspec (MonoImage *m, int idx, guint32 token, const char *fancy_name, Mo
        ptr = mono_metadata_blob_heap (m, sig);
        mono_metadata_decode_value (ptr, &ptr);
        
-       mh = mono_get_method_full (m, method_dor_to_token (token), NULL, (MonoGenericContext *) type_container);
-       g_assert (mh);
+       mh = mono_get_method_checked (m, method_dor_to_token (token), NULL, (MonoGenericContext *) type_container, &error);
+       if (!mh) {
+               g_string_append_printf (res, "Could not decode method token 0x%x due to %s", token, mono_error_get_message (&error));
+               mono_error_cleanup (&error);
+               return g_string_free (res, FALSE);
+       }
+
        container = mono_method_get_generic_container (mh);
        if (!container)
                container = type_container;
@@ -3098,10 +3130,11 @@ get_method_override (MonoImage *m, guint32 token, MonoGenericContainer *containe
                decl = method_dor_to_token (cols [MONO_METHODIMPL_DECLARATION]);
 
                if (token == impl) {
+                       MonoError error;
                        MonoMethod *mh = NULL;
-                       mh = mono_get_method_full (m, decl, NULL, (MonoGenericContext *) container);
+                       mh = mono_get_method_checked (m, decl, NULL, (MonoGenericContext *) container, &error);
 
-                       if (mh && (mh->klass && (mh->klass->generic_class || mh->klass->generic_container))) {
+                       if (mh && (mh->klass && (mono_class_is_ginst (mh->klass) || mono_class_is_gtd (mh->klass)))) {
                                char *meth_str;
                                char *ret;
                                
@@ -3110,7 +3143,16 @@ get_method_override (MonoImage *m, guint32 token, MonoGenericContainer *containe
                                g_free (meth_str);
                                return ret;
                        } else {
-                               return get_method_core (m, decl, FALSE, container);
+                               if (!mono_error_ok (&error)) {
+                                       char *meth_str = get_method_core (m, decl, FALSE, container);
+                                       char *ret = g_strdup_printf ("Could not decode method override %s due to %s", meth_str, mono_error_get_message (&error));
+
+                                       mono_error_cleanup (&error);
+                                       g_free (meth_str);
+                                       return ret;
+                               } else {
+                                       return get_method_core (m, decl, FALSE, container);
+                               }
                        }
                }
        }
@@ -3171,7 +3213,7 @@ cant_print_generic_param_name (MonoGenericParam *gparam)
        container = mono_generic_param_owner (gparam);
        check_ambiguous_genparams (container);
        return (!container || (mono_generic_params_with_ambiguous_names &&
-                       g_hash_table_lookup (mono_generic_params_with_ambiguous_names, gparam)));
+                       g_hash_table_lookup (mono_generic_params_with_ambiguous_names, gparam)) || !mono_generic_param_info (gparam));
 }