* RegistryKeyTest.cs: Modified GetValueNamesTest and GetSubKeyNamesTest
[mono.git] / mono / metadata / debug-helpers.c
index 4e0fe7cf17f1a2652d4e3cb0bc46c8cd1686a474..712b8023a039a25ff8f7d784e8525f7d0bdfc2a1 100644 (file)
@@ -2,6 +2,7 @@
 #include <string.h>
 #include "mono/metadata/tokentype.h"
 #include "mono/metadata/opcodes.h"
+#include "mono/metadata/class-internals.h"
 #include "mono/metadata/mono-endian.h"
 #include "mono/metadata/debug-helpers.h"
 
@@ -14,6 +15,53 @@ struct MonoMethodDesc {
        gboolean include_namespace;
 };
 
+static const char *wrapper_type_names [] = {
+       "none",
+       "delegate-invoke",
+       "delegate-begin-invoke",
+       "delegate-end-invoke",
+       "runtime-invoke",
+       "native-to-managed",
+       "managed-to-native",
+       "managed-to-managed",
+       "remoting-invoke",
+       "remoting-invoke-with-check",
+       "xdomain-invoke",
+       "xdomain-dispatch",
+       "ldfld",
+       "stfld",
+       "ldfld-remote",
+       "stfld-remote",
+       "synchronized",
+       "dynamic-method",
+       "isinst",
+       "cancast",
+       "proxy_isinst",
+       "stelemref",
+       "unbox",
+       "ldflda",
+       "write-barrier",
+       "unknown",
+       "cominterop-invoke",
+       "cominterop"
+};
+
+static void
+append_class_name (GString *res, MonoClass *class, gboolean include_namespace)
+{
+       if (!class) {
+               g_string_append (res, "Unknown");
+               return;
+       }
+       if (class->nested_in) {
+               append_class_name (res, class->nested_in, include_namespace);
+               g_string_append_c (res, '/');
+       }
+       if (include_namespace && *(class->name_space))
+               g_string_sprintfa (res, "%s.", class->name_space);
+       g_string_sprintfa (res, "%s", class->name);
+}
+
 void
 mono_type_get_desc (GString *res, MonoType *type, gboolean include_namespace) {
        switch (type->type) {
@@ -58,25 +106,24 @@ mono_type_get_desc (GString *res, MonoType *type, gboolean include_namespace) {
                g_string_append_c (res, '*');
                break;
        case MONO_TYPE_ARRAY:
-               mono_type_get_desc (res, type->data.array->type, include_namespace);
+               append_class_name (res, type->data.array->eklass, include_namespace);
                g_string_sprintfa (res, "[%d]", type->data.array->rank);
                break;
        case MONO_TYPE_SZARRAY:
-               mono_type_get_desc (res, type->data.type, include_namespace);
+               mono_type_get_desc (res, &type->data.klass->byval_arg, include_namespace);
                g_string_append (res, "[]");
                break;
        case MONO_TYPE_CLASS:
-       case MONO_TYPE_VALUETYPE: {
-               MonoClass *class = type->data.klass;
-               if (!class) {
-                       g_string_append (res, "Unknown");
-                       break;
-               }
-               if (include_namespace && *(class->name_space))
-                       g_string_sprintfa (res, "%s.", class->name_space);
-               g_string_sprintfa (res, "%s", class->name);
+       case MONO_TYPE_VALUETYPE:
+               append_class_name (res, type->data.klass, include_namespace);
+               break;
+       case MONO_TYPE_GENERICINST:
+               mono_type_get_desc (res, &type->data.generic_class->container_class->byval_arg, include_namespace);
+               break;
+       case MONO_TYPE_VAR:
+       case MONO_TYPE_MVAR:
+               g_string_append (res, type->data.generic_param->name);
                break;
-       }
        default:
                break;
        }
@@ -84,6 +131,20 @@ mono_type_get_desc (GString *res, MonoType *type, gboolean include_namespace) {
                g_string_append_c (res, '&');
 }
 
+char*
+mono_type_full_name (MonoType *type)
+{
+       GString *str;
+       char *res;
+
+       str = g_string_new ("");
+       mono_type_get_desc (str, type, TRUE);
+
+       res = g_strdup (str->str);
+       g_string_free (str, TRUE);
+       return res;
+}
+
 char*
 mono_signature_get_desc (MonoMethodSignature *sig, gboolean include_namespace)
 {
@@ -101,10 +162,19 @@ mono_signature_get_desc (MonoMethodSignature *sig, gboolean include_namespace)
        return result;
 }
 
-/*
- * The allowed format of a method description string is:
+/**
+ * mono_method_desc_new:
+ * @name: the method name.
+ * @include_namespace: whether the name includes a namespace or not.
+ *
+ * Creates a method description for @name, which conforms to the following
+ * specification:
+ *
  * [namespace.]classname:methodname[(args...)]
- * TODO: describe instance methods.
+ *
+ * in all the loaded assemblies.
+ *
+ * Returns: a parsed representation of the method description.
  */
 MonoMethodDesc*
 mono_method_desc_new (const char *name, gboolean include_namespace)
@@ -154,6 +224,7 @@ mono_method_desc_new (const char *name, gboolean include_namespace)
                while (*end) {
                        if (*end == ',')
                                result->num_args++;
+                       ++end;
                }
        }
 
@@ -174,6 +245,12 @@ mono_method_desc_from_method (MonoMethod *method)
        return result;
 }
 
+/**
+ * mono_method_desc_free:
+ * @desc: method description to be released
+ *
+ * Releases the MonoMethodDesc object @desc.
+ */
 void
 mono_method_desc_free (MonoMethodDesc *desc)
 {
@@ -195,9 +272,9 @@ mono_method_desc_match (MonoMethodDesc *desc, MonoMethod *method)
                return FALSE;
        if (!desc->args)
                return TRUE;
-       if (desc->num_args != method->signature->param_count)
+       if (desc->num_args != mono_method_signature (method)->param_count)
                return FALSE;
-       sig = mono_signature_get_desc (method->signature, desc->include_namespace);
+       sig = mono_signature_get_desc (mono_method_signature (method), desc->include_namespace);
        if (strcmp (sig, desc->args)) {
                g_free (sig);
                return FALSE;
@@ -219,13 +296,12 @@ mono_method_desc_full_match (MonoMethodDesc *desc, MonoMethod *method)
 MonoMethod*
 mono_method_desc_search_in_class (MonoMethodDesc *desc, MonoClass *klass)
 {
-       int i;
-
-       mono_class_init (klass);
-       for (i = 0; i < klass->method.count; ++i) {
-               if (mono_method_desc_match (desc, klass->methods [i]))
-                       return klass->methods [i];
-       }
+       MonoMethod* m;
+       gpointer iter = NULL;
+       
+       while ((m = mono_class_get_methods (klass, &iter)))
+               if (mono_method_desc_match (desc, m))
+                       return m;
        return NULL;
 }
 
@@ -233,8 +309,8 @@ MonoMethod*
 mono_method_desc_search_in_image (MonoMethodDesc *desc, MonoImage *image)
 {
        MonoClass *klass;
-       MonoTableInfo *tdef;
-       MonoTableInfo *methods;
+       const MonoTableInfo *tdef;
+       const MonoTableInfo *methods;
        MonoMethod *method;
        int i;
 
@@ -245,9 +321,9 @@ mono_method_desc_search_in_image (MonoMethodDesc *desc, MonoImage *image)
                return mono_method_desc_search_in_class (desc, klass);
        }
 
-       tdef = &image->tables [MONO_TABLE_TYPEDEF];
-       methods = &image->tables [MONO_TABLE_METHOD];
-       for (i = 0; i < methods->rows; ++i) {
+       tdef = mono_image_get_table_info (image, MONO_TABLE_TYPEDEF);
+       methods = mono_image_get_table_info (image, MONO_TABLE_METHOD);
+       for (i = 0; i < mono_table_info_get_rows (methods); ++i) {
                guint32 token = mono_metadata_decode_row_col (methods, i, MONO_METHOD_NAME);
                const char *n = mono_metadata_string_heap (image, token);
 
@@ -261,15 +337,17 @@ mono_method_desc_search_in_image (MonoMethodDesc *desc, MonoImage *image)
 }
 
 static const unsigned char*
-dis_one (GString *str, MonoDisHelper *dh, MonoMethod *method, const unsigned char *ip)
+dis_one (GString *str, MonoDisHelper *dh, MonoMethod *method, const unsigned char *ip, const unsigned char *end)
 {
-       MonoMethodHeader *header = ((MonoMethodNormal*)method)->header;
+       MonoMethodHeader *header = mono_method_get_header (method);
        const MonoOpcode *opcode;
-       guint32 i, label, token;
+       guint32 label, token;
        gint32 sval;
+       int i;
        char *tmp;
+       const unsigned char* il_code = mono_method_header_get_code (header, NULL, NULL);
 
-       label = ip - header->code;
+       label = ip - il_code;
        if (dh->indenter) {
                tmp = dh->indenter (dh, method, label);
                g_string_append (str, tmp);
@@ -278,10 +356,10 @@ dis_one (GString *str, MonoDisHelper *dh, MonoMethod *method, const unsigned cha
        if (dh->label_format)
                g_string_sprintfa (str, dh->label_format, label);
        
-       i = mono_opcode_value (&ip);
+       i = mono_opcode_value (&ip, end);
        ip++;
        opcode = &mono_opcodes [i];
-       g_string_sprintfa (str, "%-10s", mono_opcode_names [i]);
+       g_string_sprintfa (str, "%-10s", mono_opcode_name (i));
 
        switch (opcode->argument) {
        case MonoInlineNone:
@@ -317,7 +395,7 @@ dis_one (GString *str, MonoDisHelper *dh, MonoMethod *method, const unsigned cha
                sval = read32 (ip);
                ip += 4;
                if (dh->label_target)
-                       g_string_sprintfa (str, dh->label_target, ip + sval - header->code);
+                       g_string_sprintfa (str, dh->label_target, ip + sval - il_code);
                else
                        g_string_sprintfa (str, "%d", sval);
                break;
@@ -325,7 +403,7 @@ dis_one (GString *str, MonoDisHelper *dh, MonoMethod *method, const unsigned cha
                sval = *(const signed char*)ip;
                ip ++;
                if (dh->label_target)
-                       g_string_sprintfa (str, dh->label_target, ip + sval - header->code);
+                       g_string_sprintfa (str, dh->label_target, ip + sval - il_code);
                else
                        g_string_sprintfa (str, "%d", sval);
                break;
@@ -340,7 +418,7 @@ dis_one (GString *str, MonoDisHelper *dh, MonoMethod *method, const unsigned cha
                                g_string_append (str, ", ");
                        label = read32 (ip);
                        if (dh->label_target)
-                               g_string_sprintfa (str, dh->label_target, end + label - header->code);
+                               g_string_sprintfa (str, dh->label_target, end + label - il_code);
                        else
                                g_string_sprintfa (str, "%d", label);
                        ip += 4;
@@ -400,7 +478,8 @@ mono_disasm_code_one (MonoDisHelper *dh, MonoMethod *method, const guchar *ip, c
 
        if (!dh)
                dh = &default_dh;
-       ip = dis_one (res, dh, method, ip);
+       /* set ip + 2 as the end: this is just a debugging method */
+       ip = dis_one (res, dh, method, ip, ip + 2);
        if (endp)
                *endp = ip;
        
@@ -418,7 +497,7 @@ mono_disasm_code (MonoDisHelper *dh, MonoMethod *method, const guchar *ip, const
        if (!dh)
                dh = &default_dh;
        while (ip < end) {
-               ip = dis_one (res, dh, method, ip);
+               ip = dis_one (res, dh, method, ip, end);
        }
        
        result = res->str;
@@ -426,24 +505,38 @@ mono_disasm_code (MonoDisHelper *dh, MonoMethod *method, const guchar *ip, const
        return result;
 }
 
+static const char*
+wrapper_type_to_str (guint32 wrapper_type)
+{
+       g_assert (wrapper_type < sizeof (wrapper_type_names) / sizeof (char*));
+
+       return wrapper_type_names [wrapper_type];
+}
+
 char *
 mono_method_full_name (MonoMethod *method, gboolean signature)
 {
        char *res;
+       char wrapper [64];
+       const char *nspace = method->klass->name_space;
 
        if (signature) {
-               char *tmpsig = mono_signature_get_desc (method->signature, TRUE);
+               char *tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
 
-               res = g_strdup_printf ("%02d %s.%s:%s (%s)", method->wrapper_type, method->klass->name_space, 
-                                      method->klass->name, method->name, tmpsig);
+               if (method->wrapper_type != MONO_WRAPPER_NONE)
+                       sprintf (wrapper, "(wrapper %s) ", wrapper_type_to_str (method->wrapper_type));
+               else
+                       strcpy (wrapper, "");
+               res = g_strdup_printf ("%s%s%s%s:%s (%s)", wrapper, 
+                                                          nspace, *nspace ? "." : "",
+                                                          method->klass->name, method->name, tmpsig);
                g_free (tmpsig);
        } else {
 
-               res = g_strdup_printf ("%02d %s.%s:%s", method->wrapper_type, method->klass->name_space, 
-                                      method->klass->name, method->name);
+               res = g_strdup_printf ("%02d %s%s%s:%s", method->wrapper_type,
+                                                          nspace, *nspace ? "." : "",
+                                                          method->klass->name, method->name);
        }
 
        return res;
 }
-
-