2008-10-21 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mono / metadata / debug-helpers.c
index c4491b852a5058385bfb810308803c9ae86272b9..3d2282baad84853a943396a03a784b24b7a0d474 100644 (file)
@@ -17,36 +17,49 @@ 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"
+#ifdef HAVE_ARRAY_ELEM_INIT
+#define MSGSTRFIELD(line) MSGSTRFIELD1(line)
+#define MSGSTRFIELD1(line) str##line
+static const struct msgstr_t {
+#define WRAPPER(a,b) char MSGSTRFIELD(__LINE__) [sizeof (b)];
+#include "wrapper-types.h"
+#undef WRAPPER
+} opstr = {
+#define WRAPPER(a,b) b,
+#include "wrapper-types.h"
+#undef WRAPPER
 };
+static const gint16 opidx [] = {
+#define WRAPPER(a,b) [MONO_WRAPPER_ ## a] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
+#include "wrapper-types.h"
+#undef WRAPPER
+};
+
+static const char*
+wrapper_type_to_str (guint32 wrapper_type)
+{
+       g_assert (wrapper_type < MONO_WRAPPER_NUM);
+
+       return (const char*)&opstr + opidx [wrapper_type];
+}
+
+#else
+#define WRAPPER(a,b) b,
+static const char* const
+wrapper_type_names [MONO_WRAPPER_NUM + 1] = {
+#include "wrapper-types.h"
+       NULL
+};
+
+static const char*
+wrapper_type_to_str (guint32 wrapper_type)
+{
+       g_assert (wrapper_type < MONO_WRAPPER_NUM);
+
+       return wrapper_type_names [wrapper_type];
+}
+
+#endif
 
 static void
 append_class_name (GString *res, MonoClass *class, gboolean include_namespace)
@@ -65,7 +78,10 @@ append_class_name (GString *res, MonoClass *class, gboolean include_namespace)
 }
 
 void
-mono_type_get_desc (GString *res, MonoType *type, gboolean include_namespace) {
+mono_type_get_desc (GString *res, MonoType *type, gboolean include_namespace)
+{
+       int i;
+
        switch (type->type) {
        case MONO_TYPE_VOID:
                g_string_append (res, "void"); break;
@@ -108,7 +124,7 @@ mono_type_get_desc (GString *res, MonoType *type, gboolean include_namespace) {
                g_string_append_c (res, '*');
                break;
        case MONO_TYPE_ARRAY:
-               append_class_name (res, type->data.array->eklass, include_namespace);
+               mono_type_get_desc (res, &type->data.array->eklass->byval_arg, include_namespace);
                g_string_sprintfa (res, "[%d]", type->data.array->rank);
                break;
        case MONO_TYPE_SZARRAY:
@@ -119,9 +135,31 @@ mono_type_get_desc (GString *res, MonoType *type, gboolean include_namespace) {
        case MONO_TYPE_VALUETYPE:
                append_class_name (res, type->data.klass, include_namespace);
                break;
-       case MONO_TYPE_GENERICINST:
+       case MONO_TYPE_GENERICINST: {
+               MonoGenericContext *context;
+
                mono_type_get_desc (res, &type->data.generic_class->container_class->byval_arg, include_namespace);
+               g_string_append (res, "<");
+               context = &type->data.generic_class->context;
+               if (context->class_inst) {
+                       for (i = 0; i < context->class_inst->type_argc; ++i) {
+                               if (i > 0)
+                                       g_string_append (res, ", ");
+                               mono_type_get_desc (res, context->class_inst->type_argv [i], include_namespace);
+                       }
+               }
+               if (context->method_inst) {
+                       if (context->class_inst)
+                                       g_string_append (res, "; ");
+                       for (i = 0; i < context->method_inst->type_argc; ++i) {
+                               if (i > 0)
+                                       g_string_append (res, ", ");
+                               mono_type_get_desc (res, context->method_inst->type_argv [i], include_namespace);
+                       }
+               }
+               g_string_append (res, ">");
                break;
+       }
        case MONO_TYPE_VAR:
        case MONO_TYPE_MVAR:
                g_string_append (res, type->data.generic_param->name);
@@ -164,6 +202,41 @@ mono_signature_get_desc (MonoMethodSignature *sig, gboolean include_namespace)
        return result;
 }
 
+static void
+ginst_get_desc (GString *str, MonoGenericInst *ginst)
+{
+       int i;
+
+       for (i = 0; i < ginst->type_argc; ++i) {
+               if (i > 0)
+                       g_string_append (str, ", ");
+               mono_type_get_desc (str, ginst->type_argv [i], TRUE);
+       }
+}
+
+char*
+mono_context_get_desc (MonoGenericContext *context)
+{
+       GString *str;
+       char *res;
+
+       str = g_string_new ("");
+       g_string_append (str, "<");
+
+       if (context->class_inst)
+               ginst_get_desc (str, context->class_inst);
+       if (context->method_inst) {
+               if (context->class_inst)
+                       g_string_append (str, "; ");
+               ginst_get_desc (str, context->method_inst);
+       }
+
+       g_string_append (str, ">");
+       res = g_strdup (str->str);
+       g_string_free (str, TRUE);
+       return res;
+}      
+
 /**
  * mono_method_desc_new:
  * @name: the method name.
@@ -285,13 +358,50 @@ mono_method_desc_match (MonoMethodDesc *desc, MonoMethod *method)
        return TRUE;
 }
 
+static const char *
+my_strrchr (const char *str, char ch, int *len)
+{
+       int pos;
+
+       for (pos = (*len)-1; pos >= 0; pos--) {
+               if (str [pos] != ch)
+                       continue;
+
+               *len = pos;
+               return str + pos;
+       }
+
+       return NULL;
+}
+
+static gboolean
+match_class (MonoMethodDesc *desc, int pos, MonoClass *klass)
+{
+       const char *p;
+
+       p = my_strrchr (desc->klass, '/', &pos);
+       if (!p) {
+               if (strncmp (desc->klass, klass->name, pos))
+                       return FALSE;
+               if (desc->namespace && strcmp (desc->namespace, klass->name_space))
+                       return FALSE;
+               return TRUE;
+       }
+
+       if (strcmp (p+1, klass->name))
+               return FALSE;
+       if (!klass->nested_in)
+               return FALSE;
+
+       return match_class (desc, pos, klass->nested_in);
+}
+
 gboolean
 mono_method_desc_full_match (MonoMethodDesc *desc, MonoMethod *method)
 {
-       if (strcmp (desc->klass, method->klass->name))
-               return FALSE;
-       if (desc->namespace && strcmp (desc->namespace, method->klass->name_space))
+       if (!match_class (desc, strlen (desc->klass), method->klass))
                return FALSE;
+
        return mono_method_desc_match (desc, method);
 }
 
@@ -507,12 +617,16 @@ mono_disasm_code (MonoDisHelper *dh, MonoMethod *method, const guchar *ip, const
        return result;
 }
 
-static const char*
-wrapper_type_to_str (guint32 wrapper_type)
+char *
+mono_field_full_name (MonoClassField *field)
 {
-       g_assert (wrapper_type < sizeof (wrapper_type_names) / sizeof (char*));
+       char *res;
+       const char *nspace = field->parent->name_space;
 
-       return wrapper_type_names [wrapper_type];
+       res = g_strdup_printf ("%s%s%s:%s", nspace, *nspace ? "." : "",
+                                                  field->parent->name, field->name);
+
+       return res;
 }
 
 char *
@@ -520,7 +634,18 @@ mono_method_full_name (MonoMethod *method, gboolean signature)
 {
        char *res;
        char wrapper [64];
-       const char *nspace = method->klass->name_space;
+       char *klass_desc = mono_type_full_name (&method->klass->byval_arg);
+       char *inst_desc = NULL;
+
+       if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
+               GString *str = g_string_new ("");
+               g_string_append (str, "<");
+               ginst_get_desc (str, ((MonoMethodInflated*)method)->context.method_inst);
+               g_string_append (str, ">");
+
+               inst_desc = str->str;
+               g_string_free (str, FALSE);
+       }
 
        if (signature) {
                char *tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
@@ -529,17 +654,18 @@ mono_method_full_name (MonoMethod *method, gboolean signature)
                        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);
+               res = g_strdup_printf ("%s%s:%s%s (%s)", wrapper, klass_desc, 
+                                                          method->name, inst_desc ? inst_desc : "", tmpsig);
                g_free (tmpsig);
        } else {
 
-               res = g_strdup_printf ("%02d %s%s%s:%s", method->wrapper_type,
-                                                          nspace, *nspace ? "." : "",
-                                                          method->klass->name, method->name);
+               res = g_strdup_printf ("%02d %s:%s%s", method->wrapper_type, klass_desc,
+                                                          method->name, inst_desc ? inst_desc : "");
        }
 
+       g_free (klass_desc);
+       g_free (inst_desc);
+
        return res;
 }
 
@@ -649,10 +775,10 @@ print_field_value (const char *field_ptr, MonoClassField *field, int type_offset
                g_print ("%u\n", *(guint32*)field_ptr);
                break;
        case MONO_TYPE_I8:
-               g_print ("%lld\n", *(gint64*)field_ptr);
+               g_print ("%lld\n", (long long int)*(gint64*)field_ptr);
                break;
        case MONO_TYPE_U8:
-               g_print ("%llu\n", *(guint64*)field_ptr);
+               g_print ("%llu\n", (long long unsigned int)*(guint64*)field_ptr);
                break;
        case MONO_TYPE_R4:
                g_print ("%f\n", *(gfloat*)field_ptr);
@@ -678,7 +804,7 @@ objval_describe (MonoClass *class, const char *addr)
        MonoClassField *field;
        MonoClass *p;
        const char *field_ptr;
-       int type_offset = 0;
+       gssize type_offset = 0;
        if (class->valuetype)
                type_offset = -sizeof (MonoObject);