Grasshopper project system now uses csproj extension
[mono.git] / mono / metadata / debug-helpers.c
index 5a22906b7e3bc62f071e1219815ab0526e476e57..af4ef825232eebc5bbc424ac22e8cca9dce5a523 100644 (file)
@@ -5,6 +5,8 @@
 #include "mono/metadata/class-internals.h"
 #include "mono/metadata/mono-endian.h"
 #include "mono/metadata/debug-helpers.h"
+#include "mono/metadata/tabledefs.h"
+#include "mono/metadata/appdomain.h"
 
 struct MonoMethodDesc {
        char *namespace;
@@ -15,29 +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",
-       "remoting-invoke",
-       "remoting-invoke-with-check",
-       "xdomain-invoke",
-       "xdomain-dispatch",
-       "ldfld",
-       "stfld",
-       "synchronized",
-       "dynamic-method",
-       "isinst",
-       "cancast",
-       "proxy_isinst",
-       "stelemref",
-       "unbox",
-       "unknown"
+#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)
@@ -111,7 +133,11 @@ mono_type_get_desc (GString *res, MonoType *type, gboolean include_namespace) {
                append_class_name (res, type->data.klass, include_namespace);
                break;
        case MONO_TYPE_GENERICINST:
-               mono_type_get_desc (res, type->data.generic_class->generic_type, include_namespace);
+               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;
@@ -261,9 +287,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;
@@ -285,13 +311,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;
 }
 
@@ -331,11 +356,13 @@ dis_one (GString *str, MonoDisHelper *dh, MonoMethod *method, const unsigned cha
 {
        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);
@@ -383,7 +410,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;
@@ -391,7 +418,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;
@@ -406,7 +433,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;
@@ -493,14 +520,6 @@ 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)
 {
@@ -509,7 +528,7 @@ mono_method_full_name (MonoMethod *method, gboolean signature)
        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);
 
                if (method->wrapper_type != MONO_WRAPPER_NONE)
                        sprintf (wrapper, "(wrapper %s) ", wrapper_type_to_str (method->wrapper_type));
@@ -529,22 +548,221 @@ mono_method_full_name (MonoMethod *method, gboolean signature)
        return res;
 }
 
-MonoMethod *
-mono_find_method_by_name (MonoClass *klass, const char *name, int param_count)
+static const char*
+print_name_space (MonoClass *klass)
 {
-       MonoMethod *res = NULL;
-       int i;
+       if (klass->nested_in) {
+               print_name_space (klass->nested_in);
+               g_print (klass->nested_in->name);
+               return "/";
+       }
+       if (klass->name_space [0]) {
+               g_print (klass->name_space);
+               return ".";
+       }
+       return "";
+}
+
+/**
+ * mono_object_describe:
+ *
+ * Prints to stdout a small description of the object @obj.
+ * For use in a debugger.
+ */
+void
+mono_object_describe (MonoObject *obj)
+{
+       MonoClass* klass;
+       const char* sep;
+       if (!obj) {
+               g_print ("(null)\n");
+               return;
+       }
+       klass = mono_object_class (obj);
+       if (klass == mono_defaults.string_class) {
+               char *utf8 = mono_string_to_utf8 ((MonoString*)obj);
+               if (strlen (utf8) > 60) {
+                       utf8 [57] = '.';
+                       utf8 [58] = '.';
+                       utf8 [59] = '.';
+                       utf8 [60] = 0;
+               }
+               g_print ("String at %p, length: %d, '%s'\n", obj, mono_string_length ((MonoString*) obj), utf8);
+               g_free (utf8);
+       } else if (klass->rank) {
+               MonoArray *array = (MonoArray*)obj;
+               sep = print_name_space (klass);
+               g_print ("%s%s", sep, klass->name);
+               g_print (" at %p, rank: %d, length: %d\n", obj, klass->rank, mono_array_length (array));
+       } else {
+               sep = print_name_space (klass);
+               g_print ("%s%s", sep, klass->name);
+               g_print (" object at %p (klass: %p)\n", obj, klass);
+       }
 
-       mono_class_init (klass);
+}
 
-       for (i = 0; i < klass->method.count; ++i) {
-               if (klass->methods [i]->name[0] == name [0] && 
-                   !strcmp (name, klass->methods [i]->name) &&
-                   klass->methods [i]->signature->param_count == param_count) {
-                       res = klass->methods [i];
+static void
+print_field_value (const char *field_ptr, MonoClassField *field, int type_offset)
+{
+       MonoType *type;
+       g_print ("At %p (ofs: %2d) %s: ", field_ptr, field->offset + type_offset, field->name);
+       type = mono_type_get_underlying_type (field->type);
+
+       switch (type->type) {
+       case MONO_TYPE_I:
+       case MONO_TYPE_U:
+       case MONO_TYPE_PTR:
+       case MONO_TYPE_FNPTR:
+               g_print ("%p\n", *(const void**)field_ptr);
+               break;
+       case MONO_TYPE_STRING:
+       case MONO_TYPE_SZARRAY:
+       case MONO_TYPE_CLASS:
+       case MONO_TYPE_OBJECT:
+       case MONO_TYPE_ARRAY:
+               mono_object_describe (*(MonoObject**)field_ptr);
+               break;
+       case MONO_TYPE_GENERICINST:
+               if (!mono_type_generic_inst_is_valuetype (type)) {
+                       mono_object_describe (*(MonoObject**)field_ptr);
                        break;
+               } else {
+                       /* fall through */
+               }
+       case MONO_TYPE_VALUETYPE: {
+               MonoClass *k = mono_class_from_mono_type (type);
+               g_print ("%s ValueType (type: %p) at %p\n", k->name, k, field_ptr);
+               break;
+       }
+       case MONO_TYPE_I1:
+               g_print ("%d\n", *(gint8*)field_ptr);
+               break;
+       case MONO_TYPE_U1:
+               g_print ("%d\n", *(guint8*)field_ptr);
+               break;
+       case MONO_TYPE_I2:
+               g_print ("%d\n", *(gint16*)field_ptr);
+               break;
+       case MONO_TYPE_U2:
+               g_print ("%d\n", *(guint16*)field_ptr);
+               break;
+       case MONO_TYPE_I4:
+               g_print ("%d\n", *(gint32*)field_ptr);
+               break;
+       case MONO_TYPE_U4:
+               g_print ("%u\n", *(guint32*)field_ptr);
+               break;
+       case MONO_TYPE_I8:
+               g_print ("%lld\n", *(gint64*)field_ptr);
+               break;
+       case MONO_TYPE_U8:
+               g_print ("%llu\n", *(guint64*)field_ptr);
+               break;
+       case MONO_TYPE_R4:
+               g_print ("%f\n", *(gfloat*)field_ptr);
+               break;
+       case MONO_TYPE_R8:
+               g_print ("%f\n", *(gdouble*)field_ptr);
+               break;
+       case MONO_TYPE_BOOLEAN:
+               g_print ("%s (%d)\n", *(guint8*)field_ptr? "True": "False", *(guint8*)field_ptr);
+               break;
+       case MONO_TYPE_CHAR:
+               g_print ("'%c' (%d 0x%04x)\n", *(guint16*)field_ptr, *(guint16*)field_ptr, *(guint16*)field_ptr);
+               break;
+       default:
+               g_assert_not_reached ();
+               break;
+       }
+}
+
+static void
+objval_describe (MonoClass *class, const char *addr)
+{
+       MonoClassField *field;
+       MonoClass *p;
+       const char *field_ptr;
+       int type_offset = 0;
+       if (class->valuetype)
+               type_offset = -sizeof (MonoObject);
+
+       for (p = class; p != NULL; p = p->parent) {
+               gpointer iter = NULL;
+               int printed_header = FALSE;
+               while ((field = mono_class_get_fields (p, &iter))) {
+                       if (field->type->attrs & (FIELD_ATTRIBUTE_STATIC | FIELD_ATTRIBUTE_HAS_FIELD_RVA))
+                               continue;
+
+                       if (p != class && !printed_header) {
+                               const char *sep;
+                               g_print ("In class ");
+                               sep = print_name_space (p);
+                               g_print ("%s%s:\n", sep, p->name);
+                               printed_header = TRUE;
+                       }
+                       field_ptr = (const char*)addr + field->offset + type_offset;
+
+                       print_field_value (field_ptr, field, type_offset);
+               }
+       }
+}
+
+/**
+ * mono_object_describe_fields:
+ *
+ * Prints to stdout a small description of each field of the object @obj.
+ * For use in a debugger.
+ */
+void
+mono_object_describe_fields (MonoObject *obj)
+{
+       MonoClass *class = mono_object_class (obj);
+       objval_describe (class, (char*)obj);
+}
+
+/**
+ * mono_value_describe_fields:
+ *
+ * Prints to stdout a small description of each field of the value type
+ * stored at @addr of type @klass.
+ * For use in a debugger.
+ */
+void
+mono_value_describe_fields (MonoClass* klass, const char* addr)
+{
+       objval_describe (klass, addr);
+}
+
+/**
+ * mono_class_describe_statics:
+ *
+ * Prints to stdout a small description of each static field of the type @klass
+ * in the current application domain.
+ * For use in a debugger.
+ */
+void
+mono_class_describe_statics (MonoClass* klass)
+{
+       MonoClassField *field;
+       MonoClass *p;
+       const char *field_ptr;
+       const char *addr = mono_class_vtable (mono_domain_get (), klass)->data;
+       if (!addr)
+               return;
+
+       for (p = klass; p != NULL; p = p->parent) {
+               gpointer iter = NULL;
+               while ((field = mono_class_get_fields (p, &iter))) {
+                       if (field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
+                               continue;
+                       if (!(field->type->attrs & (FIELD_ATTRIBUTE_STATIC | FIELD_ATTRIBUTE_HAS_FIELD_RVA)))
+                               continue;
+
+                       field_ptr = (const char*)addr + field->offset;
+
+                       print_field_value (field_ptr, field, 0);
                }
        }
-       return res;
 }