X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fdebug-helpers.c;h=87f336b9194e5c7a483bd0deaa2104d4574efcd7;hb=a5f3c441eef82a7e0e38bbe30e3b5577eebcaf77;hp=c4491b852a5058385bfb810308803c9ae86272b9;hpb=f1f8b8a867c800b21b6a03767252403c2f72cae2;p=mono.git diff --git a/mono/metadata/debug-helpers.c b/mono/metadata/debug-helpers.c index c4491b852a5..87f336b9194 100644 --- a/mono/metadata/debug-helpers.c +++ b/mono/metadata/debug-helpers.c @@ -1,7 +1,16 @@ +/* + * console-io.c: ConsoleDriver internal calls + * + * Author: + * Mono Project (http://www.mono-project.com) + * + * Copyright (C) 2005-2008 Novell, Inc. (http://www.novell.com) + */ #include #include "mono/metadata/tokentype.h" #include "mono/metadata/opcodes.h" +#include "mono/metadata/metadata-internals.h" #include "mono/metadata/class-internals.h" #include "mono/metadata/mono-endian.h" #include "mono/metadata/debug-helpers.h" @@ -14,40 +23,53 @@ struct MonoMethodDesc { char *name; char *args; guint num_args; - gboolean include_namespace; + gboolean include_namespace, klass_glob, name_glob; +}; + +#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_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 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) { @@ -60,12 +82,15 @@ append_class_name (GString *res, MonoClass *class, gboolean 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); + g_string_append_printf (res, "%s.", class->name_space); + g_string_append_printf (res, "%s", class->name); } 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,8 +133,8 @@ 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); - g_string_sprintfa (res, "[%d]", type->data.array->rank); + mono_type_get_desc (res, &type->data.array->eklass->byval_arg, include_namespace); + g_string_append_printf (res, "[%d]", type->data.array->rank); break; case MONO_TYPE_SZARRAY: mono_type_get_desc (res, &type->data.klass->byval_arg, include_namespace); @@ -119,12 +144,45 @@ 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); + if (type->data.generic_param) { + MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param); + if (info) + g_string_append (res, info->name); + else + g_string_append_printf (res, "%s%d", type->type == MONO_TYPE_VAR ? "!" : "!!", mono_generic_param_num (type->data.generic_param)); + } else { + g_string_append (res, ""); + } + break; + case MONO_TYPE_TYPEDBYREF: + g_string_append (res, "typedbyref"); break; default: break; @@ -137,14 +195,10 @@ 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; + return g_string_free (str, FALSE); } char* @@ -152,7 +206,12 @@ mono_signature_get_desc (MonoMethodSignature *sig, gboolean include_namespace) { int i; char *result; - GString *res = g_string_new (""); + GString *res; + + if (!sig) + return g_strdup (""); + + res = g_string_new (""); for (i = 0; i < sig->param_count; ++i) { if (i > 0) @@ -164,6 +223,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. @@ -176,6 +270,8 @@ mono_signature_get_desc (MonoMethodSignature *sig, gboolean include_namespace) * * in all the loaded assemblies. * + * Both classname and methodname can contain '*' which matches anything. + * * Returns: a parsed representation of the method description. */ MonoMethodDesc* @@ -219,6 +315,10 @@ mono_method_desc_new (const char *name, gboolean include_namespace) result->klass = class_name; result->namespace = use_namespace? class_nspace: NULL; result->args = use_args? use_args: NULL; + if (strstr (result->name, "*")) + result->name_glob = TRUE; + if (strstr (result->klass, "*")) + result->klass_glob = TRUE; if (use_args) { end = use_args; if (*end) @@ -270,7 +370,14 @@ gboolean mono_method_desc_match (MonoMethodDesc *desc, MonoMethod *method) { char *sig; - if (strcmp (desc->name, method->name)) + gboolean name_match; + + name_match = strcmp (desc->name, method->name) == 0; +#ifndef _EGLIB_MAJOR + if (!name_match && desc->name_glob) + name_match = g_pattern_match_simple (desc->name, method->name); +#endif + if (!name_match) return FALSE; if (!desc->args) return TRUE; @@ -285,13 +392,56 @@ 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; + + if (desc->klass_glob && !strcmp (desc->klass, "*")) + return TRUE; +#ifndef _EGLIB_MAJOR + if (desc->klass_glob && g_pattern_match_simple (desc->klass, klass->name)) + return TRUE; +#endif + 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); } @@ -356,12 +506,12 @@ dis_one (GString *str, MonoDisHelper *dh, MonoMethod *method, const unsigned cha g_free (tmp); } if (dh->label_format) - g_string_sprintfa (str, dh->label_format, label); + g_string_append_printf (str, dh->label_format, label); i = mono_opcode_value (&ip, end); ip++; opcode = &mono_opcodes [i]; - g_string_sprintfa (str, "%-10s", mono_opcode_name (i)); + g_string_append_printf (str, "%-10s", mono_opcode_name (i)); switch (opcode->argument) { case MonoInlineNone: @@ -377,37 +527,76 @@ dis_one (GString *str, MonoDisHelper *dh, MonoMethod *method, const unsigned cha g_string_append (str, tmp); g_free (tmp); } else { - g_string_sprintfa (str, "0x%08x", token); + g_string_append_printf (str, "0x%08x", token); } ip += 4; break; - case MonoInlineString: - /* TODO */ + case MonoInlineString: { + const char *blob; + char *s; + size_t len2; + char *blob2 = NULL; + + if (!method->klass->image->dynamic) { + token = read32 (ip); + blob = mono_metadata_user_string (method->klass->image, mono_metadata_token_index (token)); + + len2 = mono_metadata_decode_blob_size (blob, &blob); + len2 >>= 1; + +#ifdef NO_UNALIGNED_ACCESS + /* The blob might not be 2 byte aligned */ + blob2 = g_malloc ((len2 * 2) + 1); + memcpy (blob2, blob, len2 * 2); +#else + blob2 = (char*)blob; +#endif + +#if G_BYTE_ORDER != G_LITTLE_ENDIAN + { + guint16 *buf = g_new (guint16, len2 + 1); + int i; + + for (i = 0; i < len2; ++i) + buf [i] = GUINT16_FROM_LE (((guint16*)blob2) [i]); + s = g_utf16_to_utf8 (buf, len2, NULL, NULL, NULL); + g_free (buf); + } +#else + s = g_utf16_to_utf8 ((gunichar2*)blob2, len2, NULL, NULL, NULL); +#endif + + g_string_append_printf (str, "\"%s\"", s); + g_free (s); + if (blob != blob2) + g_free (blob2); + } ip += 4; break; + } case MonoInlineVar: - g_string_sprintfa (str, "%d", read16 (ip)); + g_string_append_printf (str, "%d", read16 (ip)); ip += 2; break; case MonoShortInlineVar: - g_string_sprintfa (str, "%d", (*ip)); + g_string_append_printf (str, "%d", (*ip)); ip ++; break; case MonoInlineBrTarget: sval = read32 (ip); ip += 4; if (dh->label_target) - g_string_sprintfa (str, dh->label_target, ip + sval - il_code); + g_string_append_printf (str, dh->label_target, ip + sval - il_code); else - g_string_sprintfa (str, "%d", sval); + g_string_append_printf (str, "%d", sval); break; case MonoShortInlineBrTarget: sval = *(const signed char*)ip; ip ++; if (dh->label_target) - g_string_sprintfa (str, dh->label_target, ip + sval - il_code); + g_string_append_printf (str, dh->label_target, ip + sval - il_code); else - g_string_sprintfa (str, "%d", sval); + g_string_append_printf (str, "%d", sval); break; case MonoInlineSwitch: { const unsigned char *end; @@ -420,9 +609,9 @@ 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 - il_code); + g_string_append_printf (str, dh->label_target, end + label - il_code); else - g_string_sprintfa (str, "%d", label); + g_string_append_printf (str, "%d", label); ip += 4; } g_string_append_c (str, ')'); @@ -431,23 +620,23 @@ dis_one (GString *str, MonoDisHelper *dh, MonoMethod *method, const unsigned cha case MonoInlineR: { double r; readr8 (ip, &r); - g_string_sprintfa (str, "%g", r); + g_string_append_printf (str, "%g", r); ip += 8; break; } case MonoShortInlineR: { float r; readr4 (ip, &r); - g_string_sprintfa (str, "%g", r); + g_string_append_printf (str, "%g", r); ip += 4; break; } case MonoInlineI: - g_string_sprintfa (str, "%d", (gint32)read32 (ip)); + g_string_append_printf (str, "%d", (gint32)read32 (ip)); ip += 4; break; case MonoShortInlineI: - g_string_sprintfa (str, "%d", *(const signed char*)ip); + g_string_append_printf (str, "%d", *(const signed char*)ip); ip ++; break; case MonoInlineI8: @@ -507,12 +696,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, mono_field_get_name (field)); + + return res; } char * @@ -520,7 +713,33 @@ 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); + } else if (method->is_generic) { + MonoGenericContainer *container = mono_method_get_generic_container (method); + + GString *str = g_string_new (""); + g_string_append (str, "<"); + ginst_get_desc (str, container->context.method_inst); + g_string_append (str, ">"); + + inst_desc = str->str; + g_string_free (str, FALSE); + } + + if (method->wrapper_type != MONO_WRAPPER_NONE) + sprintf (wrapper, "(wrapper %s) ", wrapper_type_to_str (method->wrapper_type)); + else + strcpy (wrapper, ""); if (signature) { char *tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE); @@ -529,17 +748,17 @@ 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 ("%s%s:%s%s", wrapper, klass_desc, + method->name, inst_desc ? inst_desc : ""); } + g_free (klass_desc); + g_free (inst_desc); + return res; } @@ -548,11 +767,11 @@ print_name_space (MonoClass *klass) { if (klass->nested_in) { print_name_space (klass->nested_in); - g_print (klass->nested_in->name); + g_print ("%s", klass->nested_in->name); return "/"; } if (klass->name_space [0]) { - g_print (klass->name_space); + g_print ("%s", klass->name_space); return "."; } return ""; @@ -601,7 +820,7 @@ 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); + g_print ("At %p (ofs: %2d) %s: ", field_ptr, field->offset + type_offset, mono_field_get_name (field)); type = mono_type_get_underlying_type (field->type); switch (type->type) { @@ -649,10 +868,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 +897,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); @@ -742,8 +961,12 @@ 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) + MonoVTable *vtable = mono_class_vtable_full (mono_domain_get (), klass, FALSE); + const char *addr; + + if (!vtable) + return; + if (!(addr = vtable->data)) return; for (p = klass; p != NULL; p = p->parent) {