X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fdis%2Fget.c;h=3c629bb9891641c664de8d9e9ffd4cfe56a0cf70;hb=e698ebe6355598c0a4a52338dd5cacfce2a2d9d7;hp=0142d90ed9f9600b2f3e39f26dcc9f876cc63de1;hpb=ff228e1c801bda9666b6edab3ee962e05edcf480;p=mono.git diff --git a/mono/dis/get.c b/mono/dis/get.c index 0142d90ed9f..3c629bb9891 100644 --- a/mono/dis/get.c +++ b/mono/dis/get.c @@ -12,21 +12,28 @@ #include #include #include +#include #include "meta.h" #include "util.h" #include "get.h" +#include #include #include extern gboolean substitute_with_mscorlib_p; -static MonoGenericContext * -get_memberref_context (MonoImage *m, guint32 mrp_token, MonoGenericContext *context); +static MonoGenericContainer * +get_memberref_container (MonoImage *m, guint32 mrp_token, MonoGenericContainer *container); static char * -get_memberref_parent (MonoImage *m, guint32 mrp_token, MonoGenericContext *context); +get_memberref_parent (MonoImage *m, guint32 mrp_token, MonoGenericContainer *container); + +static gboolean +cant_print_generic_param_name (MonoGenericParam *gparam); GHashTable *key_table = NULL; +GHashTable *mono_generic_params_with_ambiguous_names = NULL; +GHashTable *generic_containers = NULL; gboolean show_method_tokens = FALSE; gboolean show_tokens = FALSE; @@ -38,6 +45,10 @@ get_typedef (MonoImage *m, int idx) char *tstring, *result; guint32 token; + if (idx == 1) + /* */ + return NULL; + mono_metadata_decode_row (&m->tables [MONO_TABLE_TYPEDEF], idx - 1, cols, MONO_TYPEDEF_SIZE); ns = mono_metadata_string_heap (m, cols [MONO_TYPEDEF_NAMESPACE]); @@ -81,7 +92,7 @@ get_module (MonoImage *m, int idx) mono_metadata_decode_row (&m->tables [MONO_TABLE_MODULE], idx - 1, cols, MONO_MODULE_SIZE); - return g_strdup (mono_metadata_string_heap (m, cols [MONO_MODULE_NAME])); + return get_escaped_name (mono_metadata_string_heap (m, cols [MONO_MODULE_NAME])); } char * @@ -91,7 +102,7 @@ get_moduleref (MonoImage *m, int idx) mono_metadata_decode_row (&m->tables [MONO_TABLE_MODULEREF], idx - 1, cols, MONO_MODULEREF_SIZE); - return g_strdup (mono_metadata_string_heap (m, cols [MONO_MODULEREF_NAME])); + return get_escaped_name (mono_metadata_string_heap (m, cols [MONO_MODULEREF_NAME])); } char * @@ -101,7 +112,31 @@ get_assemblyref (MonoImage *m, int idx) mono_metadata_decode_row (&m->tables [MONO_TABLE_ASSEMBLYREF], idx - 1, cols, MONO_ASSEMBLYREF_SIZE); - return g_strdup (mono_metadata_string_heap (m, cols [MONO_ASSEMBLYREF_NAME])); + return get_escaped_name (mono_metadata_string_heap (m, cols [MONO_ASSEMBLYREF_NAME])); +} + +static char * +stringify_array (guint32 rank, guint32 num_sizes, guint32 num_lo_bounds, gint32 *sizes, gint32 *lo_bounds) +{ + GString *res = g_string_new ("["); + int i; + + for (i = 0; i < rank; i++) { + if (i) + g_string_append_c (res, ','); + if (i < num_lo_bounds) + g_string_sprintfa (res, "%d...", lo_bounds [i]); + if (i < num_sizes) { + if (i < num_lo_bounds) + g_string_sprintfa (res, "%d", lo_bounds [i] + sizes [i] - 1); + else + g_string_sprintfa (res, "%d", sizes [i]); + } + + } + g_string_append (res, "]"); + + return g_string_free (res, FALSE); } /* @@ -111,52 +146,30 @@ get_assemblyref (MonoImage *m, int idx) static const char * get_array_shape (MonoImage *m, const char *ptr, char **result) { - GString *res = g_string_new ("["); guint32 rank, num_sizes, num_lo_bounds; - guint32 *sizes = NULL, *lo_bounds = NULL; - int i, r; - char buffer [80]; + gint32 *sizes = NULL, *lo_bounds = NULL; + int i; rank = mono_metadata_decode_value (ptr, &ptr); num_sizes = mono_metadata_decode_value (ptr, &ptr); if (num_sizes > 0) - sizes = g_new (guint32, num_sizes); + sizes = g_new (gint32, num_sizes); for (i = 0; i < num_sizes; i++) sizes [i] = mono_metadata_decode_value (ptr, &ptr); num_lo_bounds = mono_metadata_decode_value (ptr, &ptr); if (num_lo_bounds > 0) - lo_bounds = g_new (guint32, num_lo_bounds); + lo_bounds = g_new (gint32, num_lo_bounds); for (i = 0; i < num_lo_bounds; i++) - lo_bounds [i] = mono_metadata_decode_value (ptr, &ptr); + lo_bounds [i] = mono_metadata_decode_signed_value (ptr, &ptr); - for (r = 0; r < rank; r++){ - if (r < num_sizes){ - if (r < num_lo_bounds){ - sprintf (buffer, "%d..%d", lo_bounds [r], lo_bounds [r] + sizes [r] - 1); - } else { - sprintf (buffer, "0..%d", sizes [r] - 1); - } - } else - buffer [0] = 0; - - g_string_append (res, buffer); - if ((r + 1) != rank) - g_string_append (res, ", "); - } - g_string_append (res, "]"); - - if (sizes) - g_free (sizes); - - if (lo_bounds) - g_free (lo_bounds); + *result = stringify_array (rank, num_sizes, num_lo_bounds, sizes, lo_bounds); - *result = res->str; - g_string_free (res, FALSE); + g_free (sizes); + g_free (lo_bounds); return ptr; } @@ -169,22 +182,19 @@ get_array_shape (MonoImage *m, const char *ptr, char **result) * Returns the stringified representation of a TypeSpec signature (22.2.17) */ char * -get_typespec (MonoImage *m, guint32 idx, gboolean is_def, MonoGenericContext *context) +get_typespec (MonoImage *m, guint32 idx, gboolean is_def, MonoGenericContainer *container) { guint32 cols [MONO_TYPESPEC_SIZE]; const char *ptr; char *s, *result; GString *res = g_string_new (""); int len; - - MonoType *type; - - type = mono_type_create_from_typespec_full (m, context, idx); + MonoMethodSignature *sig; mono_metadata_decode_row (&m->tables [MONO_TABLE_TYPESPEC], idx-1, cols, MONO_TYPESPEC_SIZE); ptr = mono_metadata_blob_heap (m, cols [MONO_TYPESPEC_SIGNATURE]); len = mono_metadata_decode_value (ptr, &ptr); - + switch (*ptr++){ case MONO_TYPE_PTR: ptr = get_custom_mod (m, ptr, &s); @@ -193,26 +203,27 @@ get_typespec (MonoImage *m, guint32 idx, gboolean is_def, MonoGenericContext *co g_string_append_c (res, ' '); g_free (s); } - + if (*ptr == MONO_TYPE_VOID) g_string_append (res, "void"); else { - ptr = get_type (m, ptr, &s, context); + ptr = get_type (m, ptr, &s, is_def, container); if (s) g_string_append (res, s); } g_string_append (res, "*"); break; - + case MONO_TYPE_FNPTR: - s = dis_stringify_function_ptr (m, type->data.method); + sig = mono_metadata_parse_method_signature_full (m, container, 0, ptr, &ptr); + s = dis_stringify_function_ptr (m, sig); g_string_append (res, "method "); g_string_append (res, s); g_free (s); break; - + case MONO_TYPE_ARRAY: - ptr = get_type (m, ptr, &s, context); + ptr = get_type (m, ptr, &s, is_def, container); g_string_append (res, s); g_free (s); g_string_append_c (res, ' '); @@ -220,7 +231,7 @@ get_typespec (MonoImage *m, guint32 idx, gboolean is_def, MonoGenericContext *co g_string_append (res, s); g_free (s); break; - + case MONO_TYPE_SZARRAY: ptr = get_custom_mod (m, ptr, &s); if (s){ @@ -228,14 +239,14 @@ get_typespec (MonoImage *m, guint32 idx, gboolean is_def, MonoGenericContext *co g_string_append_c (res, ' '); g_free (s); } - ptr = get_type (m, ptr, &s, context); + ptr = get_type (m, ptr, &s, is_def, container); g_string_append (res, s); g_string_append (res, "[]"); g_free (s); break; default: - s = dis_stringify_type (m, type, is_def); + ptr = get_type (m, ptr - 1, &s, is_def, container); g_string_append (res, s); g_free (s); break; @@ -321,7 +332,7 @@ get_typeref (MonoImage *m, int idx) * at (dor_token >> 2) */ char * -get_typedef_or_ref (MonoImage *m, guint32 dor_token, MonoGenericContext *context) +get_typedef_or_ref (MonoImage *m, guint32 dor_token, MonoGenericContainer *container) { char *temp = NULL, *s = NULL; int table, idx; @@ -344,7 +355,7 @@ get_typedef_or_ref (MonoImage *m, guint32 dor_token, MonoGenericContext *context break; case 2: /* TypeSpec */ - s = get_typespec (m, idx, FALSE, context); + s = get_typespec (m, idx, FALSE, container); break; default: @@ -410,19 +421,19 @@ const char * get_custom_mod (MonoImage *m, const char *ptr, char **return_value) { char *s; - const char *reqd; + const char *mod; *return_value = NULL; while ((*ptr == MONO_TYPE_CMOD_OPT) || (*ptr == MONO_TYPE_CMOD_REQD)) { - reqd = (*ptr == MONO_TYPE_CMOD_REQD) ? "reqd" : "opt"; + mod = (*ptr == MONO_TYPE_CMOD_REQD) ? "modreq" : "modopt"; ptr++; ptr = get_encoded_typedef_or_ref (m, ptr, &s); if (*return_value == NULL) - *return_value = g_strconcat (reqd, " ", s, NULL); + *return_value = g_strconcat (" ", mod, " (", s, ")", NULL); else - *return_value = g_strconcat (*return_value, " ", reqd, " ", s, NULL); + *return_value = g_strconcat (*return_value, " ", mod, " (", s, ")", NULL); g_free (s); } return ptr; @@ -445,7 +456,7 @@ static dis_map_t element_type_map [] = { { MONO_TYPE_R4 , "float32" }, { MONO_TYPE_R8 , "float64" }, { MONO_TYPE_STRING , "string" }, - { MONO_TYPE_TYPEDBYREF , "TypedByRef" }, + { MONO_TYPE_TYPEDBYREF , "typedref" }, { MONO_TYPE_I , "native int" }, { MONO_TYPE_U , "native unsigned int" }, { MONO_TYPE_OBJECT , "object" }, @@ -479,28 +490,16 @@ dis_stringify_token (MonoImage *m, guint32 token) char* dis_stringify_array (MonoImage *m, MonoArrayType *array, gboolean is_def) { - char *type; - GString *s = g_string_new(""); - int i; + char *type, *arr_str, *ret; type = dis_stringify_type (m, &array->eklass->byval_arg, is_def); - g_string_append (s, type); + arr_str = stringify_array (array->rank, array->numsizes, array->numlobounds, array->sizes, array->lobounds); + + ret = g_strconcat (type, arr_str, NULL); + + g_free (arr_str); g_free (type); - g_string_append_c (s, '['); - for (i = 0; i < array->rank; ++i) { - if (i) - g_string_append_c (s, ','); - if (i < array->numsizes) { - if (i < array->numlobounds && array->lobounds[i] != 0) - g_string_sprintfa (s, "%d..%d", array->lobounds[i], array->sizes[i]); - else - g_string_sprintfa (s, "%d", array->sizes[i]); - } - } - g_string_append_c (s, ']'); - type = s->str; - g_string_free (s, FALSE); - return type; + return ret; } char* @@ -513,7 +512,7 @@ dis_stringify_modifiers (MonoImage *m, int n, MonoCustomMod *mod) char *tok = dis_stringify_token (m, mod[i].token); if (i > 0) g_string_sprintfa (s, " "); - g_string_sprintfa (s, "%s (%s)", mod[i].required ? "modreq": "modopt", tok); + g_string_sprintfa (s, " %s (%s)", mod[i].required ? "modreq": "modopt", tok); g_free (tok); } g_string_append_c (s, ' '); @@ -539,6 +538,106 @@ dis_stringify_param (MonoImage *m, MonoType *param) return result; } +static char* +dis_stringify_variant_type (MonoMarshalVariant variant) +{ + switch (variant) { + case MONO_VARIANT_EMPTY: + return g_strdup (""); + case MONO_VARIANT_NULL: + return g_strdup ("null"); + case MONO_VARIANT_I2: + return g_strdup ("int16"); + case MONO_VARIANT_I4: + return g_strdup ("int32"); + case MONO_VARIANT_R4: + return g_strdup ("float32"); + case MONO_VARIANT_R8: + return g_strdup ("float64"); + case MONO_VARIANT_CY: + return g_strdup ("currency"); + case MONO_VARIANT_DATE: + return g_strdup ("date"); + case MONO_VARIANT_BSTR: + return g_strdup ("bstr"); + case MONO_VARIANT_DISPATCH: + return g_strdup ("idispatch"); + case MONO_VARIANT_ERROR: + return g_strdup ("error"); + case MONO_VARIANT_BOOL: + return g_strdup ("bool"); + case MONO_VARIANT_VARIANT: + return g_strdup ("variant"); + case MONO_VARIANT_UNKNOWN: + return g_strdup ("iunknown"); + case MONO_VARIANT_DECIMAL: + return g_strdup ("decimal"); + case MONO_VARIANT_I1: + return g_strdup ("int8"); + case MONO_VARIANT_UI1: + return g_strdup ("unsigned int8"); + case MONO_VARIANT_UI2: + return g_strdup ("unsigned int16"); + case MONO_VARIANT_UI4: + return g_strdup ("unsigned int32"); + case MONO_VARIANT_I8: + return g_strdup ("int64"); + case MONO_VARIANT_UI8: + return g_strdup ("unsigned int64"); + case MONO_VARIANT_INT: + return g_strdup ("int"); + case MONO_VARIANT_UINT: + return g_strdup ("unsigned int"); + case MONO_VARIANT_VOID: + return g_strdup ("void"); + case MONO_VARIANT_HRESULT: + return g_strdup ("hresult"); + case MONO_VARIANT_PTR: + return g_strdup ("*"); + case MONO_VARIANT_SAFEARRAY: + return g_strdup ("safearray"); + case MONO_VARIANT_CARRAY: + return g_strdup ("carray"); + case MONO_VARIANT_USERDEFINED: + return g_strdup ("userdefined"); + case MONO_VARIANT_LPSTR: + return g_strdup ("lpstr"); + case MONO_VARIANT_LPWSTR: + return g_strdup ("lpwstr"); + case MONO_VARIANT_RECORD: + return g_strdup ("record"); + case MONO_VARIANT_FILETIME: + return g_strdup ("filetime"); + case MONO_VARIANT_BLOB: + return g_strdup ("blob"); + case MONO_VARIANT_STREAM: + return g_strdup ("stream"); + case MONO_VARIANT_STORAGE: + return g_strdup ("storage"); + case MONO_VARIANT_STREAMED_OBJECT: + return g_strdup ("streamed_object"); + case MONO_VARIANT_STORED_OBJECT: + return g_strdup ("stored_object"); + case MONO_VARIANT_BLOB_OBJECT: + return g_strdup ("blob_object"); + case MONO_VARIANT_CF: + return g_strdup ("cf"); + case MONO_VARIANT_CLSID: + return g_strdup ("clsid"); + case MONO_VARIANT_VECTOR: + /* FIXME: output: vector */ + return g_strdup ("vector"); + case MONO_VARIANT_ARRAY: + /* FIXME: output: [ ] */ + return g_strdup ("[]"); + case MONO_VARIANT_BYREF: + /* FIXME: output: & */ + return g_strdup ("&"); + default: + return g_strdup ("unknown"); + } +} + static char* dis_stringify_native_type (MonoMarshalNative native) { @@ -614,16 +713,16 @@ dis_stringify_native_type (MonoMarshalNative native) } } -static char* +char* dis_stringify_marshal_spec (MonoMarshalSpec *spec) { switch (spec->native) { case MONO_NATIVE_BYVALTSTR: - return g_strdup_printf ("fixed sysstring [%d]", spec->data.array_data.num_elem); + return g_strdup_printf (" marshal (fixed sysstring [%d])", spec->data.array_data.num_elem); case MONO_NATIVE_BYVALARRAY: - return g_strdup_printf ("fixed array [%d]", spec->data.array_data.num_elem); + return g_strdup_printf (" marshal (fixed array [%d])", spec->data.array_data.num_elem); case MONO_NATIVE_LPARRAY: { - char *elem_type, *elems; + char *elem_type, *elems, *ret; guint32 num_elem = spec->data.array_data.num_elem; guint32 param_num = spec->data.array_data.param_num; @@ -636,11 +735,33 @@ dis_stringify_marshal_spec (MonoMarshalSpec *spec) elems = g_strdup_printf ("+ %d", param_num); else elems = g_strdup_printf ("%d + %d", num_elem, param_num); - - return g_strdup_printf ("%s[%s]", elem_type, elems); + + ret = g_strdup_printf (" marshal (%s[%s])", elem_type, elems); + g_free (elem_type); + g_free (elems); + return ret; } - default: - return dis_stringify_native_type (spec->native); + case MONO_NATIVE_SAFEARRAY: { + char *elem_type = NULL, *ret; + + if (spec->data.safearray_data.elem_type != 0) + elem_type = dis_stringify_variant_type (spec->data.safearray_data.elem_type); + ret = g_strdup_printf (" marshal (safearray %s)", elem_type ? elem_type : ""); + + g_free (elem_type); + return ret; + } + case MONO_NATIVE_CUSTOM: + return g_strdup_printf (" marshal (custom (\"%s\", \"%s\"))", + spec->data.custom_data.custom_name ? spec->data.custom_data.custom_name : "", + spec->data.custom_data.cookie ? spec->data.custom_data.cookie : ""); + default: { + char *native_type, *ret; + native_type = dis_stringify_native_type (spec->native); + ret = g_strdup_printf (" marshal (%s)", native_type); + g_free (native_type); + return ret; + } } } @@ -674,13 +795,19 @@ get_generic_param (MonoImage *m, MonoGenericContainer *container) if (i > 0) g_string_append (result, ","); + + flags = param->flags & GENERIC_PARAMETER_ATTRIBUTE_VARIANCE_MASK; + if ((flags & GENERIC_PARAMETER_ATTRIBUTE_COVARIANT) == GENERIC_PARAMETER_ATTRIBUTE_COVARIANT) + g_string_append (result, "+ "); + if ((flags & GENERIC_PARAMETER_ATTRIBUTE_CONTRAVARIANT) == GENERIC_PARAMETER_ATTRIBUTE_CONTRAVARIANT) + g_string_append (result, "- "); flags = param->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK; - if (flags == GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) + if ((flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) g_string_append (result, "class "); - else if (flags == GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) + if ((flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) == GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) g_string_append (result, "valuetype "); - else if (flags == GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) + if ((flags & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) == GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) g_string_append (result, ".ctor "); for (constr = param->constraints; constr && *constr; constr++) { @@ -713,20 +840,38 @@ get_generic_param (MonoImage *m, MonoGenericContainer *container) char* dis_stringify_method_signature (MonoImage *m, MonoMethodSignature *method, int methoddef_row, - MonoGenericContext *context, gboolean fully_qualified) + MonoGenericContainer *container, gboolean fully_qualified) +{ + return dis_stringify_method_signature_full (m, method, methoddef_row, container, fully_qualified, TRUE); +} + +/* + * @m: metadata context + * @method: MonoMethodSignature to dis-stringify + * @methoddef_row: row index in the Method table + * @context: generic context, generic method's context in case of a Generic method + * or a generic type's context. if !@context, treats it as a non-generic method + * @fully_qualified: TRUE to print type name also. + * + * Returns: Allocated stringified method signature + */ +char* +dis_stringify_method_signature_full (MonoImage *m, MonoMethodSignature *method, int methoddef_row, + MonoGenericContainer *container, gboolean fully_qualified, gboolean with_marshal_info) { guint32 cols [MONO_METHOD_SIZE]; guint32 pcols [MONO_PARAM_SIZE]; - guint32 param_index = 0; - const char *name = ""; + guint32 param_index = 0, next_param_index = 0; + gboolean has_param_row; + const char *method_name = ""; int free_method = 0; char *retval, *esname; char *type = NULL; - char *marshal_info = NULL; + char *marshal_info = NULL, *ret_marshal_info = NULL; char *gen_param = NULL; GString *result = g_string_new (""); - MonoGenericContainer *container = NULL; - int i; + GString *result_ret = g_string_new (""); + int i, start; g_assert (method || methoddef_row); @@ -734,76 +879,109 @@ dis_stringify_method_signature (MonoImage *m, MonoMethodSignature *method, int m mono_metadata_decode_row (&m->tables [MONO_TABLE_METHOD], methoddef_row -1, cols, MONO_METHOD_SIZE); if (fully_qualified) type = get_typedef (m, mono_metadata_typedef_from_method (m, methoddef_row)); - name = mono_metadata_string_heap (m, cols [MONO_METHOD_NAME]); + method_name = mono_metadata_string_heap (m, cols [MONO_METHOD_NAME]); param_index = cols [MONO_METHOD_PARAMLIST]; if (!method) { const char *sig = mono_metadata_blob_heap (m, cols [MONO_METHOD_SIGNATURE]); - container = mono_metadata_load_generic_params ( - m, MONO_TOKEN_METHOD_DEF | methoddef_row, context ? context->container : NULL); + container = mono_metadata_load_generic_params (m, MONO_TOKEN_METHOD_DEF | methoddef_row, container); if (container) - context = (MonoGenericContext *) container; + mono_metadata_load_generic_param_constraints (m, MONO_TOKEN_METHOD_DEF | methoddef_row, container); mono_metadata_decode_blob_size (sig, &sig); - method = mono_metadata_parse_method_signature_full (m, context, methoddef_row, sig, &sig); + method = mono_metadata_parse_method_signature_full (m, container, methoddef_row, sig, &sig); free_method = 1; - } else if (context) - container = context->container; + } if (container && container->is_method) gen_param = get_generic_param (m, container); - } - - retval = dis_stringify_param (m, method->ret); - if (method->hasthis) - g_string_append (result, "instance "); - g_string_append (result, map (method->call_convention, call_conv_type_map)); - g_string_sprintfa (result, " %s ", retval); - if (type) { - char *estype = get_escaped_name (type); - g_string_sprintfa (result, "%s::", estype); - g_free (estype); - } - esname = get_escaped_name (name); - g_string_append (result, esname); - g_free (esname); - if (gen_param) { - g_string_append (result, gen_param); - g_free (gen_param); - } - g_string_append (result, " ("); - g_free (retval); - for (i = 0; i < method->param_count; ++i) { - if (param_index && param_index <= m->tables [MONO_TABLE_PARAM].rows) { + + if (methoddef_row < m->tables [MONO_TABLE_METHOD].rows) { + mono_metadata_decode_row (&m->tables [MONO_TABLE_METHOD], methoddef_row, cols, MONO_METHOD_SIZE); + next_param_index = cols [MONO_METHOD_PARAMLIST]; + } else { + next_param_index = m->tables [MONO_TABLE_PARAM].rows + 1; + } + } + + start = method->hasthis ? 0 : 1; + for (i = 0; i < method->param_count + 1; ++i) { + marshal_info = NULL; + has_param_row = param_index && param_index < next_param_index; + esname = NULL; + + if (method->param_count == 0 && !has_param_row) + /* method has zero parameters, and no row for return val in the PARAM table */ + continue; + + if (has_param_row) mono_metadata_decode_row (&m->tables [MONO_TABLE_PARAM], param_index - 1, pcols, MONO_PARAM_SIZE); - name = mono_metadata_string_heap (m, pcols [MONO_PARAM_NAME]); - method->params [i]->attrs = pcols [MONO_PARAM_FLAGS]; + + if (has_param_row && i == pcols [MONO_PARAM_SEQUENCE]) { + if (i) + esname = get_escaped_name ( + mono_metadata_string_heap (m, pcols [MONO_PARAM_NAME])); - if (pcols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_FIELD_MARSHAL) { + if (with_marshal_info && (pcols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_FIELD_MARSHAL)) { const char *tp; MonoMarshalSpec *spec; tp = mono_metadata_get_marshal_info (m, param_index - 1, FALSE); g_assert (tp); spec = mono_metadata_parse_marshal_spec (m, tp); - marshal_info = g_strdup_printf (" marshal (%s)", dis_stringify_marshal_spec (spec)); + if (i) + marshal_info = dis_stringify_marshal_spec (spec); + else + ret_marshal_info = dis_stringify_marshal_spec (spec); } - - param_index++; + param_index ++; } else { - name = ""; + if (i) + /* A_[0-9]* does not require escaping */ + esname = g_strdup_printf ("A_%i", i - start); } - if (i) + + if (!i) + continue; + + if (i > 1) g_string_append (result, ", "); - retval = dis_stringify_param (m, method->params [i]); - esname = get_escaped_name (name); - g_string_append_printf (result, "%s %s%s", retval, esname, marshal_info ? marshal_info : ""); + retval = dis_stringify_param (m, method->params [i - 1]); + + g_string_append_printf (result, "%s%s %s", retval, marshal_info ? marshal_info : "", esname); g_free (retval); g_free (esname); + g_free (marshal_info); } g_string_append (result, ") "); + retval = dis_stringify_param (m, method->ret); + + if (method->hasthis) + g_string_append (result_ret, "instance "); + g_string_append (result_ret, map (method->call_convention, call_conv_type_map)); + g_string_sprintfa (result_ret, " %s%s ", retval, ret_marshal_info ? ret_marshal_info :""); + g_free (ret_marshal_info); + if (type) { + char *estype = get_escaped_name (type); + g_string_sprintfa (result_ret, "%s::", estype); + g_free (estype); + g_free (type); + } + esname = get_escaped_name (method_name); + g_string_append (result_ret, esname); + g_free (esname); + if (gen_param) { + g_string_append (result_ret, gen_param); + g_free (gen_param); + } + g_string_append (result_ret, " ("); + g_free (retval); + + g_string_prepend (result, result_ret->str); + g_string_free (result_ret, FALSE); + if (show_method_tokens && methoddef_row) g_string_append_printf (result, " /* 0x%X */ ", (methoddef_row >> MONO_TYPEORMETHOD_BITS) | MONO_TOKEN_METHOD_DEF); @@ -852,6 +1030,10 @@ get_escaped_class_name (MonoClass *c) { char *result, *esname; + if (c->type_token == mono_metadata_make_token (MONO_TABLE_TYPEDEF, 1)) + /* */ + return NULL; + if (c->rank || c->byval_arg.type == MONO_TYPE_PTR) g_assert (0); @@ -879,6 +1061,10 @@ dis_stringify_object_with_class (MonoImage *m, MonoClass *c, gboolean prefix, gb const char *otype = type->type == MONO_TYPE_VALUETYPE ? "valuetype " : "class " ; char *assemblyref = NULL, *result, *esname, *generic = NULL; + if (c->type_token == mono_metadata_make_token (MONO_TABLE_TYPEDEF, 1)) + /* */ + return NULL; + if (m != c->image) { if (c->image->assembly_name) { /* we cheat */ @@ -899,14 +1085,15 @@ dis_stringify_object_with_class (MonoImage *m, MonoClass *c, gboolean prefix, gb if (c->generic_class) { MonoGenericClass *gclass = c->generic_class; + MonoGenericInst *inst = gclass->context.class_inst; GString *str = g_string_new (""); int i; - for (i = 0; i < gclass->inst->type_argc; i++){ - char *t = dis_stringify_type (m, gclass->inst->type_argv [i], is_def); + for (i = 0; i < inst->type_argc; i++){ + char *t = dis_stringify_type (m, inst->type_argv [i], is_def); g_string_append (str, t); - if (i+1 != gclass->inst->type_argc) + if (i+1 != inst->type_argc) g_string_append (str, ", "); g_free (t); } @@ -997,30 +1184,29 @@ dis_stringify_type (MonoImage *m, MonoType *type, gboolean is_def) bare = g_strdup ("void"); break; case MONO_TYPE_MVAR: - if (is_def) { - g_assert (type->data.generic_param->name); - bare = g_strdup_printf ("!!%s", type->data.generic_param->name); - } else + if (is_def && !cant_print_generic_param_name (type->data.generic_param)) + bare = g_strdup_printf ("!!%s", get_escaped_name (type->data.generic_param->name)); + else bare = g_strdup_printf ("!!%d", type->data.generic_param->num); break; case MONO_TYPE_VAR: - if (is_def) { - g_assert (type->data.generic_param->name); - bare = g_strdup_printf ("!%s", type->data.generic_param->name); - } else + if (is_def && !cant_print_generic_param_name (type->data.generic_param)) + bare = g_strdup_printf ("!%s", get_escaped_name (type->data.generic_param->name)); + else bare = g_strdup_printf ("!%d", type->data.generic_param->num); break; case MONO_TYPE_GENERICINST: { GString *str = g_string_new (""); + MonoGenericInst *inst; int i; char *generic_type = dis_stringify_type ( m, &type->data.generic_class->container_class->byval_arg, is_def); - - for (i = 0; i < type->data.generic_class->inst->type_argc; i++){ - char *t = dis_stringify_type (m, type->data.generic_class->inst->type_argv [i], is_def); + inst = type->data.generic_class->context.class_inst; + for (i = 0; i < inst->type_argc; i++){ + char *t = dis_stringify_type (m, inst->type_argv [i], is_def); g_string_append (str, t); - if (i+1 != type->data.generic_class->inst->type_argc) + if (i+1 != inst->type_argc) g_string_append (str, ", "); g_free (t); } @@ -1038,8 +1224,12 @@ dis_stringify_type (MonoImage *m, MonoType *type, gboolean is_def) if (type->byref) byref = "&"; + + if (!bare) + /* bare is NULL, for */ + return bare; - result = g_strconcat (mods ? mods : "", bare, byref, pinned, NULL); + result = g_strconcat (bare, byref, pinned, mods ? mods : "", NULL); g_free (bare); @@ -1058,7 +1248,7 @@ dis_stringify_type (MonoImage *m, MonoType *type, gboolean is_def) * Returns: the new ptr to continue decoding */ const char * -get_type (MonoImage *m, const char *ptr, char **result, MonoGenericContext *context) +get_type (MonoImage *m, const char *ptr, char **result, gboolean is_def, MonoGenericContainer *container) { const char *start = ptr; guint32 type; @@ -1089,7 +1279,7 @@ get_type (MonoImage *m, const char *ptr, char **result, MonoGenericContext *cont int count, i; char *temp; - ptr = get_type (m, ptr, &temp, context); + ptr = get_type (m, ptr, &temp, is_def, container); g_string_append (str, temp); g_free (temp); @@ -1099,7 +1289,7 @@ get_type (MonoImage *m, const char *ptr, char **result, MonoGenericContext *cont for (i = 0; i < count; i++) { if (i) g_string_append (str, ","); - ptr = get_type (m, ptr, &temp, context); + ptr = get_type (m, ptr, &temp, is_def, container); g_string_append (str, temp); } @@ -1110,9 +1300,8 @@ get_type (MonoImage *m, const char *ptr, char **result, MonoGenericContext *cont } default: - t = mono_metadata_parse_type_full (m, context, MONO_PARSE_TYPE, 0, start, &ptr); - *result = dis_stringify_type (m, t, FALSE); - mono_metadata_free_type (t); + t = mono_metadata_parse_type_full (m, container, MONO_PARSE_TYPE, 0, start, &ptr); + *result = dis_stringify_type (m, t, is_def); break; } @@ -1124,7 +1313,7 @@ get_type (MonoImage *m, const char *ptr, char **result, MonoGenericContext *cont * Returns a stringified representation of a FieldSig (22.2.4) */ char * -get_field_signature (MonoImage *m, guint32 blob_signature, MonoGenericContext *context) +get_field_signature (MonoImage *m, guint32 blob_signature, MonoGenericContainer *container) { char *allocated_modifier_string, *allocated_type_string; const char *ptr = mono_metadata_blob_heap (m, blob_signature); @@ -1140,12 +1329,12 @@ get_field_signature (MonoImage *m, guint32 blob_signature, MonoGenericContext *c ptr++; len--; ptr = get_custom_mod (m, ptr, &allocated_modifier_string); - ptr = get_type (m, ptr, &allocated_type_string, context); + ptr = get_type (m, ptr, &allocated_type_string, FALSE, container); res = g_strdup_printf ( - "%s %s", - allocated_modifier_string ? allocated_modifier_string : "", - allocated_type_string); + "%s%s", + allocated_type_string, + allocated_modifier_string ? allocated_modifier_string : ""); if (allocated_modifier_string) g_free (allocated_modifier_string); @@ -1200,36 +1389,40 @@ decode_literal (MonoImage *m, guint32 token) * Returns: the new ptr to continue decoding. */ const char * -get_ret_type (MonoImage *m, const char *ptr, char **ret_type, MonoGenericContext *context) +get_ret_type (MonoImage *m, const char *ptr, char **ret_type, MonoGenericContainer *container) { GString *str = g_string_new (""); char *mod = NULL; char *allocated_type_string; + int has_byref = 0; ptr = get_custom_mod (m, ptr, &mod); - if (mod){ - g_string_append (str, mod); - g_string_append_c (str, ' '); - g_free (mod); - } if (*ptr == MONO_TYPE_TYPEDBYREF){ - g_string_append (str, "typedbyref"); + g_string_append (str, "typedref"); ptr++; } else if (*ptr == MONO_TYPE_VOID){ g_string_append (str, "void"); ptr++; } else { if (*ptr == MONO_TYPE_BYREF){ - g_string_append (str, "[out] "); + has_byref = 1; ptr++; } - ptr = get_type (m, ptr, &allocated_type_string, context); + ptr = get_type (m, ptr, &allocated_type_string, FALSE, container); g_string_append (str, allocated_type_string); + if (has_byref) + g_string_append (str, "& "); g_free (allocated_type_string); } + if (mod){ + g_string_append (str, mod); + g_string_append_c (str, ' '); + g_free (mod); + } + *ret_type = str->str; g_string_free (str, FALSE); @@ -1247,20 +1440,15 @@ get_ret_type (MonoImage *m, const char *ptr, char **ret_type, MonoGenericContext * Returns: the new ptr to continue decoding. */ const char * -get_param (MonoImage *m, const char *ptr, char **retval, MonoGenericContext *context) +get_param (MonoImage *m, const char *ptr, char **retval, MonoGenericContainer *container) { GString *str = g_string_new (""); char *allocated_mod_string, *allocated_type_string; ptr = get_custom_mod (m, ptr, &allocated_mod_string); - if (allocated_mod_string){ - g_string_append (str, allocated_mod_string); - g_string_append_c (str, ' '); - g_free (allocated_mod_string); - } if (*ptr == MONO_TYPE_TYPEDBYREF){ - g_string_append (str, " typedbyref "); + g_string_append (str, " typedref "); ptr++; } else { gboolean by_ref = 0; @@ -1269,18 +1457,54 @@ get_param (MonoImage *m, const char *ptr, char **retval, MonoGenericContext *con ptr++; by_ref = 1; } - ptr = get_type (m, ptr, &allocated_type_string, context); + ptr = get_type (m, ptr, &allocated_type_string, FALSE, container); g_string_append (str, allocated_type_string); if (by_ref) g_string_append_c (str, '&'); g_free (allocated_type_string); } + if (allocated_mod_string){ + g_string_append (str, allocated_mod_string); + g_string_append_c (str, ' '); + g_free (allocated_mod_string); + } + *retval = str->str; g_string_free (str, FALSE); return ptr; } +/** + * str_escape + * + * @str: string to process + * @list: list of chars to escape + * + * Returns: an allocated escaped string. + */ +static char* +str_escape (const char *str, const char *list) +{ + const char *p = str; + GString *res; + + res = g_string_sized_new (strlen (str)); + + for (;;) { + while (*p && !strchr (list, *p)) + ++p; + g_string_append_len (res, str, p - str); + if (!*p) + break; + g_string_append_c (res, '\\'); + str = p; + ++p; + } + + return g_string_free (res, FALSE); +} + /** * get_escaped_name * @@ -1291,7 +1515,10 @@ char* get_escaped_name (const char *name) { const char *s; - char *tmp, *tmp2; + char *ret, *esc; + + if (!name) + return NULL; g_assert (key_table); @@ -1313,16 +1540,19 @@ get_escaped_name (const char *name) for (s = name; *s; s++) { if (isalnum (*s) || *s == '_' || *s == '$' || *s == '@' || - *s == '?' || *s == '.' || *s == 0 || *s == '!') + *s == '?' || (*s == '.' && s != name) || *s == 0 || *s == '!' || *s == '`') continue; - return g_strdup_printf ("'%s'", name); + esc = str_escape (name, "'\\"); + ret = g_strdup_printf ("'%s'", esc); + g_free (esc); + return ret; } if (g_hash_table_lookup (key_table, name)) return g_strdup_printf ("'%s'", name); - return g_strdup (name); + return str_escape (name, "'\\"); } static dis_map_t param_map [] = { @@ -1359,7 +1589,7 @@ static dis_map_t field_flags_map [] = { { FIELD_ATTRIBUTE_SPECIAL_NAME, "specialname " }, { FIELD_ATTRIBUTE_PINVOKE_IMPL, "FIXME:pinvokeimpl " }, { FIELD_ATTRIBUTE_RT_SPECIAL_NAME, "rtspecialname " }, - { FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL, "hasfieldmarshal " }, + /*{ FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL, "hasfieldmarshal " },*/ { 0, NULL } }; @@ -1385,8 +1615,7 @@ field_flags (guint32 f) * Returns a stringifed representation of a MethodRefSig (22.2.2) */ char * -get_methodref_signature (MonoImage *m, guint32 blob_signature, const char *fancy_name, - MonoGenericContext *context) +get_methodref_signature (MonoImage *m, guint32 blob_signature, const char *fancy_name) { GString *res = g_string_new (""); const char *ptr = mono_metadata_blob_heap (m, blob_signature); @@ -1420,7 +1649,7 @@ get_methodref_signature (MonoImage *m, guint32 blob_signature, const char *fancy gen_count = mono_metadata_decode_value (ptr, &ptr); param_count = mono_metadata_decode_value (ptr, &ptr); if (cconv != 0xa) { - ptr = get_ret_type (m, ptr, &allocated_ret_type, context); + ptr = get_ret_type (m, ptr, &allocated_ret_type, NULL); g_string_append (res, allocated_ret_type); g_free (allocated_ret_type); } @@ -1451,7 +1680,7 @@ get_methodref_signature (MonoImage *m, guint32 blob_signature, const char *fancy ptr++; } - ptr = get_param (m, ptr, ¶m, context); + ptr = get_param (m, ptr, ¶m, NULL); g_string_append (res, param); if (i+1 != param_count) g_string_append (res, ", "); @@ -1471,10 +1700,10 @@ get_methodref_signature (MonoImage *m, guint32 blob_signature, const char *fancy * Returns a stringifed representation of a field ref */ char * -get_fieldref_signature (MonoImage *m, int idx, MonoGenericContext *context) +get_fieldref_signature (MonoImage *m, int idx, MonoGenericContainer *container) { guint32 cols [MONO_MEMBERREF_SIZE]; - MonoGenericContext *new_context; + MonoGenericContainer *new_container; char *type, *esname; char *sig; char *full_sig; @@ -1482,13 +1711,17 @@ get_fieldref_signature (MonoImage *m, int idx, MonoGenericContext *context) mono_metadata_decode_row (&m->tables [MONO_TABLE_MEMBERREF], idx - 1, cols, MONO_MEMBERREF_SIZE); - new_context = get_memberref_context (m, cols [MONO_MEMBERREF_CLASS], context); - sig = get_field_signature (m, cols [MONO_MEMBERREF_SIGNATURE], new_context); + new_container = get_memberref_container (m, cols [MONO_MEMBERREF_CLASS], container); + sig = get_field_signature (m, cols [MONO_MEMBERREF_SIGNATURE], new_container); - type = get_memberref_parent (m, cols [MONO_MEMBERREF_CLASS], context); + type = get_memberref_parent (m, cols [MONO_MEMBERREF_CLASS], container); esname = get_escaped_name (mono_metadata_string_heap (m, cols [MONO_MEMBERREF_NAME])); - full_sig = g_strdup_printf ("%s %s::%s", sig, type, esname); + full_sig = g_strdup_printf ("%s %s%s%s", + sig, + type ? type : "", + type ? "::" : "", + esname); g_free (sig); g_free (type); g_free (esname); @@ -1506,7 +1739,7 @@ get_fieldref_signature (MonoImage *m, int idx, MonoGenericContext *context) * the TypeDef table and locate the actual "owner" of the field */ char * -get_field (MonoImage *m, guint32 token, MonoGenericContext *context) +get_field (MonoImage *m, guint32 token, MonoGenericContainer *container) { int idx = mono_metadata_token_index (token); guint32 cols [MONO_FIELD_SIZE]; @@ -1518,12 +1751,12 @@ get_field (MonoImage *m, guint32 token, MonoGenericContext *context) * defined in another module/assembly, just like in get_method () */ if (mono_metadata_token_code (token) == MONO_TOKEN_MEMBER_REF) { - return get_fieldref_signature (m, idx, context); + return get_fieldref_signature (m, idx, container); } g_assert (mono_metadata_token_code (token) == MONO_TOKEN_FIELD_DEF); mono_metadata_decode_row (&m->tables [MONO_TABLE_FIELD], idx - 1, cols, MONO_FIELD_SIZE); - sig = get_field_signature (m, cols [MONO_FIELD_SIGNATURE], context); + sig = get_field_signature (m, cols [MONO_FIELD_SIGNATURE], container); /* * To locate the actual "container" for this field, we have to scan @@ -1534,8 +1767,11 @@ get_field (MonoImage *m, guint32 token, MonoGenericContext *context) 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", - sig, estype, esname); + res = g_strdup_printf ("%s %s%s%s", + sig, + estype ? estype : "", + estype ? "::" : "", + esname); g_free (type); g_free (sig); @@ -1545,8 +1781,8 @@ get_field (MonoImage *m, guint32 token, MonoGenericContext *context) return res; } -static MonoGenericContext * -get_memberref_context (MonoImage *m, guint32 mrp_token, MonoGenericContext *context) +static MonoGenericContainer * +get_memberref_container (MonoImage *m, guint32 mrp_token, MonoGenericContainer *container) { MonoClass *klass; @@ -1558,23 +1794,22 @@ get_memberref_context (MonoImage *m, guint32 mrp_token, MonoGenericContext *cont switch (table){ case 0: /* TypeDef */ - return (MonoGenericContext *) mono_metadata_load_generic_params ( - m, MONO_TOKEN_TYPE_DEF | idx, NULL); + return mono_metadata_load_generic_params (m, MONO_TOKEN_TYPE_DEF | idx, NULL); case 1: /* TypeRef */ return NULL; case 4: /* TypeSpec */ - klass = mono_class_get_full (m, MONO_TOKEN_TYPE_SPEC | idx, context); + klass = mono_class_get_full (m, MONO_TOKEN_TYPE_SPEC | idx, (MonoGenericContext *) container); g_assert (klass); - return klass->generic_class ? klass->generic_class->context : NULL; + return klass->generic_class ? klass->generic_class->container_class->generic_container : NULL; } g_assert_not_reached (); return NULL; } static char * -get_memberref_parent (MonoImage *m, guint32 mrp_token, MonoGenericContext *context) +get_memberref_parent (MonoImage *m, guint32 mrp_token, MonoGenericContainer *container) { /* * mrp_index is a MemberRefParent coded index @@ -1596,7 +1831,7 @@ get_memberref_parent (MonoImage *m, guint32 mrp_token, MonoGenericContext *conte return g_strdup ("TODO:MethodDef"); case 4: /* TypeSpec */ - return get_typespec (m, idx, FALSE, context); + return get_typespec (m, idx, FALSE, container); } g_assert_not_reached (); return NULL; @@ -1612,7 +1847,7 @@ get_memberref_parent (MonoImage *m, guint32 mrp_token, MonoGenericContext *conte * the TypeDef table and locate the actual "owner" of the field */ static char * -get_method_core (MonoImage *m, guint32 token, gboolean fullsig, MonoGenericContext *context) +get_method_core (MonoImage *m, guint32 token, gboolean fullsig, MonoGenericContainer *container) { int idx = mono_metadata_token_index (token); guint32 member_cols [MONO_MEMBERREF_SIZE], method_cols [MONO_METHOD_SIZE]; @@ -1620,17 +1855,18 @@ get_method_core (MonoImage *m, guint32 token, gboolean fullsig, MonoGenericConte char *name; MonoMethod *mh; + MonoGenericContainer *type_container = container; - mh = mono_get_method_full (m, token, NULL, context); + mh = mono_get_method_full (m, token, NULL, (MonoGenericContext *) container); if (mh) { if (mono_method_signature (mh)->is_inflated) - context = ((MonoMethodInflated *) mh)->context; + 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", sig, token, esname); + name = g_strdup_printf ("%s/*%08x*/%s%s", sig ? sig : "", token, sig ? "::" : "", esname); else - name = g_strdup_printf ("%s::%s", sig, esname); + name = g_strdup_printf ("%s%s%s", sig ? sig : "", sig ? "::" : "", esname); g_free (sig); g_free (esname); } else @@ -1641,25 +1877,45 @@ get_method_core (MonoImage *m, guint32 token, gboolean fullsig, MonoGenericConte mono_metadata_decode_row (&m->tables [MONO_TABLE_METHOD], idx - 1, method_cols, MONO_METHOD_SIZE); - sig = get_methodref_signature (m, method_cols [MONO_METHOD_SIGNATURE], name, context); + sig = get_methodref_signature (m, method_cols [MONO_METHOD_SIGNATURE], name); break; case MONO_TOKEN_MEMBER_REF: { mono_metadata_decode_row (&m->tables [MONO_TABLE_MEMBERREF], idx - 1, member_cols, MONO_MEMBERREF_SIZE); - if (!name) - name = g_strdup_printf ("%s::%s", - get_memberref_parent (m, member_cols [MONO_MEMBERREF_CLASS], context), + if (!name) { + char *parent = get_memberref_parent (m, member_cols [MONO_MEMBERREF_CLASS], container); + name = g_strdup_printf ("%s%s%s", + parent ? parent : "", + parent ? "::" : "", mono_metadata_string_heap (m, member_cols [MONO_MEMBERREF_NAME])); + g_free (parent); + } + if (mh) { + int arity = 0; + + if (mh->is_generic) + arity = mono_method_get_generic_container (mh)->type_argc; + else + if (mh->is_inflated && ((MonoMethodInflated *)mh)->declaring->is_generic) + arity = mono_method_get_generic_container (((MonoMethodInflated*) mh)->declaring)->type_argc; + + if (arity > 0) { + char *str = g_strdup_printf ("%s <[%d]>", name, arity); + g_free (name); + name = str; + } + } + sig = get_methodref_signature ( - m, member_cols [MONO_MEMBERREF_SIGNATURE], name, context); + m, member_cols [MONO_MEMBERREF_SIGNATURE], name); break; } case MONO_TOKEN_METHOD_SPEC: { mono_metadata_decode_row (&m->tables [MONO_TABLE_METHODSPEC], idx - 1, member_cols, MONO_METHODSPEC_SIZE); token = member_cols [MONO_METHODSPEC_METHOD]; - sig = get_methodspec (m, idx, token, name, context); + sig = get_methodspec (m, idx, token, name, type_container); break; } @@ -1683,9 +1939,9 @@ get_method_core (MonoImage *m, guint32 token, gboolean fullsig, MonoGenericConte } char * -get_method (MonoImage *m, guint32 token, MonoGenericContext *context) +get_method (MonoImage *m, guint32 token, MonoGenericContainer *container) { - return get_method_core (m, token, TRUE, context); + return get_method_core (m, token, TRUE, container); } /** @@ -1707,19 +1963,22 @@ get_methoddef (MonoImage *m, guint32 idx) mh = mono_get_method (m, MONO_TOKEN_METHOD_DEF | idx, NULL); if (mh) { sig = dis_stringify_type (m, &mh->klass->byval_arg, FALSE); - name = g_strdup_printf ("%s::%s", sig, mh->name); + name = g_strdup_printf ("%s%s%s", + sig ? sig : "", + 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, NULL); + sig = get_methodref_signature (m, cols [MONO_METHOD_SIGNATURE], name); return sig; } char * -get_method_type_param (MonoImage *m, guint32 blob_signature, MonoGenericContext *context) +get_method_type_param (MonoImage *m, guint32 blob_signature, MonoGenericContainer *container) { GString *res = g_string_new (""); const char *ptr = mono_metadata_blob_heap (m, blob_signature); @@ -1736,7 +1995,7 @@ get_method_type_param (MonoImage *m, guint32 blob_signature, MonoGenericContext for (i = 0; i < param_count; i++){ char *param = NULL; - ptr = get_param (m, ptr, ¶m, context); + ptr = get_param (m, ptr, ¶m, container); g_string_append (res, param); if (i+1 != param_count) g_string_append (res, ", "); @@ -1756,7 +2015,7 @@ get_method_type_param (MonoImage *m, guint32 blob_signature, MonoGenericContext */ char * -get_methodspec (MonoImage *m, int idx, guint32 token, const char *fancy_name, MonoGenericContext *context) +get_methodspec (MonoImage *m, int idx, guint32 token, const char *fancy_name, MonoGenericContainer *type_container) { GString *res = g_string_new (""); guint32 member_cols [MONO_MEMBERREF_SIZE], method_cols [MONO_METHOD_SIZE]; @@ -1764,6 +2023,8 @@ get_methodspec (MonoImage *m, int idx, guint32 token, const char *fancy_name, Mo const char *ptr; guint32 sig = 0; int param_count, cconv, i, gen_count = 0; + MonoGenericContainer *container; + MonoMethod *mh = NULL; switch (token & MONO_METHODDEFORREF_MASK) { case MONO_METHODDEFORREF_METHODDEF: @@ -1784,6 +2045,12 @@ 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); + container = mono_method_get_generic_container (mh); + if (!container) + container = type_container; if (*ptr & 0x20){ if (*ptr & 0x40) @@ -1801,7 +2068,7 @@ get_methodspec (MonoImage *m, int idx, guint32 token, const char *fancy_name, Mo param_count = mono_metadata_decode_value (ptr, &ptr); if (cconv != 0xa) { char *allocated_ret_type; - ptr = get_ret_type (m, ptr, &allocated_ret_type, context); + ptr = get_ret_type (m, ptr, &allocated_ret_type, container); g_string_append (res, allocated_ret_type); g_free (allocated_ret_type); } @@ -1814,7 +2081,7 @@ get_methodspec (MonoImage *m, int idx, guint32 token, const char *fancy_name, Mo mono_metadata_decode_row (&m->tables [MONO_TABLE_METHODSPEC], idx - 1, member_cols, MONO_METHODSPEC_SIZE); token = member_cols [MONO_METHODSPEC_SIGNATURE]; - type_param = get_method_type_param (m, token, context); + type_param = get_method_type_param (m, token, type_container); g_string_append (res, type_param); g_string_append (res, " ("); @@ -1825,7 +2092,7 @@ get_methodspec (MonoImage *m, int idx, guint32 token, const char *fancy_name, Mo for (i = 0; i < param_count; i++){ char *param = NULL; - ptr = get_param (m, ptr, ¶m, context); + ptr = get_param (m, ptr, ¶m, container); g_string_append (res, param); if (i+1 != param_count) g_string_append (res, ", "); @@ -1841,6 +2108,107 @@ get_methodspec (MonoImage *m, int idx, guint32 token, const char *fancy_name, Mo return s; } +/* + * get_encoded_user_string_bytearray: + * @ptr: pointer into the US heap + * @len: length of string in the heap. + * + * Strings on the US heap are encoded using UTF-16. Print a bytearray. + */ +static char* +get_encoded_user_string_bytearray (const unsigned char* ptr, int len) +{ + gchar *str; + int i, j, tspaces = (len % 16); + GString *res; + + if (len == 0) + return g_strdup_printf ("\"\""); + + res = g_string_new ("bytearray (\n\t"); + + for (i = 1; i <= len; ++i) { + g_string_append_printf (res, "%02x ", ptr [i-1]); + + if (i % 16 == 0) { + if (i == len) + g_string_append (res, ")// "); + else + g_string_append (res, " // "); + + for(j = i - 16; j < i; ++j) + g_string_append_printf (res, "%c", isprint (ptr [j]) ? ptr [j] : '.'); + g_string_append (res, "\n\t"); + } + } + + if (tspaces) { + g_string_append (res, ") "); + for (i = tspaces + 1; i < 16; ++i) + g_string_append_printf (res, " "); + + g_string_append (res, " // "); + for(i = len - tspaces; i < len; ++i) + g_string_append_printf (res, "%c", isprint (ptr [i]) ? ptr [i] : '.'); + g_string_append (res, "\n\t"); + } + + str = res->str; + g_string_free (res, FALSE); + return str; +} + +/* + * get_encoded_user_string_or_bytearray: + * @ptr: pointer into the US heap + * + * Strings on the US heap are encoded using UTF-16. Print as string + * if possible, else emit a bytearray. + */ +char* +get_encoded_user_string_or_bytearray (const unsigned char *ptr, int len) +{ + char *res, *eres, *result; + int i; + + res = g_malloc ((len >> 1) + 1); + + /* + * I should really use some kind of libunicode here + */ + for (i = 0; i + 1 < len; i += 2) { + if (ptr [i + 1] || + (!isprint (ptr [i]) && ptr [i] != '\\' && ptr [i] != '"' && + ptr [i] != '\r' && ptr [i] != '\n' && ptr [i] != '\t')) { + g_free (res); + return get_encoded_user_string_bytearray (ptr, len); + } + + res [i >> 1] = ptr [i]; + } + + res [len >> 1] = 0; + + eres = g_strescape (res, NULL); + result = g_strdup_printf ("\"%s\"", eres); + g_free (res); + g_free (eres); + + return result; +} + +char * +stringify_double (double r) +{ + char *ret, *ptr; + + ret = g_strdup_printf ("%.17g.", r); + ptr = ret + strlen (ret) - 1; + if (strpbrk (ret, ".eE") != ptr) + *ptr = '\0'; + + return ret; +} /** * get_constant: @@ -1853,10 +2221,10 @@ get_methodspec (MonoImage *m, int idx, guint32 token, const char *fancy_name, Mo char * get_constant (MonoImage *m, MonoTypeEnum t, guint32 blob_index) { - const unsigned char *ptr = mono_metadata_blob_heap (m, blob_index); + const char *ptr = mono_metadata_blob_heap (m, blob_index); int len; - len = mono_metadata_decode_value (ptr, (const char**)&ptr); + len = mono_metadata_decode_value (ptr, &ptr); switch (t){ case MONO_TYPE_BOOLEAN: @@ -1867,7 +2235,7 @@ get_constant (MonoImage *m, MonoTypeEnum t, guint32 blob_index) case MONO_TYPE_U1: case MONO_TYPE_I1: - return g_strdup_printf ("int8(0x%02x)", (int) (*ptr)); + return g_strdup_printf ("int8(0x%02x)", (int) ((*ptr) & 0xFF)); break; case MONO_TYPE_U2: @@ -1876,70 +2244,60 @@ get_constant (MonoImage *m, MonoTypeEnum t, guint32 blob_index) case MONO_TYPE_U4: case MONO_TYPE_I4: - return g_strdup_printf ("int32(%d)", read32 (ptr)); + return g_strdup_printf ("int32(0x%08x)", read32 (ptr)); + case MONO_TYPE_U8: case MONO_TYPE_I8: { guint32 low, high; low = read32 (ptr); high = read32 (ptr + 4); return g_strdup_printf ("int64(0x%08x%08x)", high, low); } - case MONO_TYPE_U8: { - guint32 low, high; - low = read32 (ptr); - high = read32 (ptr + 4); - return g_strdup_printf ("0x%08x%08x", high, low); - } case MONO_TYPE_R4: { + gboolean normal; float r; readr4 (ptr, &r); - return g_strdup_printf ("float32(%g)", (double) r); - } + + /* Crazy solaris systems doesn't have isnormal */ +#ifdef HAVE_FINITE + normal = finite (r); +#else + normal = isnormal (r); +#endif + if (!normal) { + return g_strdup_printf ("float32(0x%08x)", read32 (ptr)); + } else { + char *str = stringify_double ((double) r); + char *ret = g_strdup_printf ("float32(%s)", str); + g_free (str); + return ret; + } + } case MONO_TYPE_R8: { + gboolean normal; double r; readr8 (ptr, &r); - return g_strdup_printf ("float64(%g)", r); - } - case MONO_TYPE_STRING: { - gchar *str; - int i, j, tspaces = (len%16); - GString *res; - - if (len == 0) - return g_strdup_printf ("\"\""); - - res = g_string_new ("bytearray (\n\t"); - - for(i = 1; i <= len; ++i) { - g_string_append_printf(res, "%02x ", ptr[i-1]); - if(i%16 == 0) { - if(i == len) - g_string_append(res, ")// "); - else - g_string_append(res, " // "); - - for(j = i-16; j < i; ++j) - g_string_append_printf(res, "%c", isprint(ptr[j]) ? ptr[j] : '.'); - g_string_append(res, "\n\t"); - } + /* Crazy solaris systems doesn't have isnormal */ +#ifdef HAVE_FINITE + normal = finite (r); +#else + normal = isnormal (r); +#endif + if (!normal) { + guint32 low, high; + low = read32 (ptr); + high = read32 (ptr + 4); + return g_strdup_printf ("float64(0x%08x%08x)", high, low); + } else { + char *str = stringify_double (r); + char *ret = g_strdup_printf ("float64(%s)", str); + g_free (str); + return ret; } - - if(tspaces) { - g_string_append(res, ") "); - for(i = tspaces+1; i < 16; ++i) - g_string_append_printf(res, " "); - - g_string_append(res, " // "); - for(i = len-tspaces; i < len; ++i) - g_string_append_printf(res, "%c", isprint(ptr[i]) ? ptr[i] : '.'); - g_string_append(res, "\n\t"); - } - - str = res->str; - g_string_free(res, FALSE); - return str; } + case MONO_TYPE_STRING: + return get_encoded_user_string_or_bytearray ((const guchar*)ptr, len); case MONO_TYPE_CLASS: return g_strdup ("nullref"); @@ -1961,17 +2319,22 @@ get_constant (MonoImage *m, MonoTypeEnum t, guint32 blob_index) * constant. */ char * -get_token (MonoImage *m, guint32 token, MonoGenericContext *context) +get_token (MonoImage *m, guint32 token, MonoGenericContainer *container) { char *temp, *result; guint32 idx = mono_metadata_token_index (token); switch (mono_metadata_token_code (token)){ case MONO_TOKEN_FIELD_DEF: - temp = get_field (m, token, context); + temp = get_field (m, token, container); result = g_strdup_printf ("field %s", temp); g_free (temp); return result; + case MONO_TOKEN_METHOD_DEF: + temp = get_method (m, token, container); + result = g_strdup_printf ("method %s", temp); + g_free (temp); + return result; case MONO_TOKEN_TYPE_DEF: temp = get_typedef (m, idx); result = get_escaped_name (temp); @@ -1980,7 +2343,7 @@ get_token (MonoImage *m, guint32 token, MonoGenericContext *context) case MONO_TOKEN_TYPE_REF: return get_typeref (m, idx); case MONO_TOKEN_TYPE_SPEC: - return get_typespec (m, idx, TRUE, context); + return get_typespec (m, idx, TRUE, container); case MONO_TOKEN_MEMBER_REF: { guint32 cols [MONO_MEMBERREF_SIZE]; const char *sig; @@ -1988,13 +2351,15 @@ get_token (MonoImage *m, guint32 token, MonoGenericContext *context) sig = mono_metadata_blob_heap (m, cols [MONO_MEMBERREF_SIGNATURE]); mono_metadata_decode_blob_size (sig, &sig); if (*sig == 0x6) { /* it's a field */ - temp = get_field (m, token, context); + temp = get_field (m, token, container); result = g_strdup_printf ("field %s", temp); g_free (temp); return result; - } - else { - g_error ("Do not know how to decode tokens of type 0x%08x", token); + } else { + temp = get_method (m, token, container); + result = g_strdup_printf ("method %s", temp); + g_free (temp); + return result; } break; } @@ -2016,7 +2381,7 @@ get_token (MonoImage *m, guint32 token, MonoGenericContext *context) * at (token & 0xffffff) */ char * -get_token_type (MonoImage *m, guint32 token, MonoGenericContext *context) +get_token_type (MonoImage *m, guint32 token, MonoGenericContainer *container) { char *temp = NULL, *s = NULL; int idx; @@ -2035,7 +2400,7 @@ get_token_type (MonoImage *m, guint32 token, MonoGenericContext *context) break; case MONO_TOKEN_TYPE_SPEC: - s = get_typespec (m, idx, FALSE, context); + s = get_typespec (m, idx, FALSE, container); break; default: @@ -2055,7 +2420,7 @@ get_guid (MonoImage *m, guint32 guid_index) const unsigned char *guid; char *result; - guid = mono_metadata_guid_heap (m, guid_index); + guid = (const guchar*)mono_metadata_guid_heap (m, guid_index); result = g_strdup_printf ("{%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X}", guid [3], guid [2], guid [1], guid [0], guid [5], guid [4], guid [7], guid [6], @@ -2084,6 +2449,9 @@ dis_get_custom_attrs (MonoImage *m, guint32 token) case MONO_TABLE_ASSEMBLY: idx |= MONO_CUSTOM_ATTR_ASSEMBLY; break; + case MONO_TABLE_ASSEMBLYREF: + idx |= MONO_CUSTOM_ATTR_ASSEMBLYREF; + break; case MONO_TABLE_MODULE: idx |= MONO_CUSTOM_ATTR_MODULE; break; @@ -2102,6 +2470,9 @@ dis_get_custom_attrs (MonoImage *m, guint32 token) case MONO_TABLE_PARAM: idx |= MONO_CUSTOM_ATTR_PARAMDEF; break; + case MONO_TABLE_GENERICPARAM: + idx |= MONO_CUSTOM_ATTR_GENERICPAR; + break; default: g_print ("Missing custom attr get support for token 0x%08x\n", token); return NULL; @@ -2248,6 +2619,7 @@ init_key_table (void) g_hash_table_insert (key_table, (char *) "autochar", GINT_TO_POINTER (TRUE)); g_hash_table_insert (key_table, (char *) "auto", GINT_TO_POINTER (TRUE)); g_hash_table_insert (key_table, (char *) "beforefieldinit", GINT_TO_POINTER (TRUE)); + g_hash_table_insert (key_table, (char *) "bestfit", GINT_TO_POINTER (TRUE)); g_hash_table_insert (key_table, (char *) "beq", GINT_TO_POINTER (TRUE)); g_hash_table_insert (key_table, (char *) "beq.s", GINT_TO_POINTER (TRUE)); g_hash_table_insert (key_table, (char *) "bge", GINT_TO_POINTER (TRUE)); @@ -2289,6 +2661,7 @@ init_key_table (void) g_hash_table_insert (key_table, (char *) "bytearray", GINT_TO_POINTER (TRUE)); g_hash_table_insert (key_table, (char *) "byvalstr", GINT_TO_POINTER (TRUE)); g_hash_table_insert (key_table, (char *) "call", GINT_TO_POINTER (TRUE)); + g_hash_table_insert (key_table, (char *) "callconv", GINT_TO_POINTER (TRUE)); g_hash_table_insert (key_table, (char *) "calli", GINT_TO_POINTER (TRUE)); g_hash_table_insert (key_table, (char *) "callmostderived", GINT_TO_POINTER (TRUE)); g_hash_table_insert (key_table, (char *) "callvirt", GINT_TO_POINTER (TRUE)); @@ -2301,6 +2674,7 @@ init_key_table (void) g_hash_table_insert (key_table, (char *) "cgt", GINT_TO_POINTER (TRUE)); g_hash_table_insert (key_table, (char *) "cgt.un", GINT_TO_POINTER (TRUE)); g_hash_table_insert (key_table, (char *) "char", GINT_TO_POINTER (TRUE)); + g_hash_table_insert (key_table, (char *) "charmaperror", GINT_TO_POINTER (TRUE)); g_hash_table_insert (key_table, (char *) "cil", GINT_TO_POINTER (TRUE)); g_hash_table_insert (key_table, (char *) "ckfinite", GINT_TO_POINTER (TRUE)); g_hash_table_insert (key_table, (char *) "class", GINT_TO_POINTER (TRUE)); @@ -2375,6 +2749,7 @@ init_key_table (void) g_hash_table_insert (key_table, (char *) "final", GINT_TO_POINTER (TRUE)); g_hash_table_insert (key_table, (char *) "finally", GINT_TO_POINTER (TRUE)); g_hash_table_insert (key_table, (char *) "fixed", GINT_TO_POINTER (TRUE)); + g_hash_table_insert (key_table, (char *) "flags", GINT_TO_POINTER (TRUE)); g_hash_table_insert (key_table, (char *) "float32", GINT_TO_POINTER (TRUE)); g_hash_table_insert (key_table, (char *) "float64", GINT_TO_POINTER (TRUE)); g_hash_table_insert (key_table, (char *) "float", GINT_TO_POINTER (TRUE)); @@ -2433,6 +2808,7 @@ init_key_table (void) g_hash_table_insert (key_table, (char *) "ldc.i8", GINT_TO_POINTER (TRUE)); g_hash_table_insert (key_table, (char *) "ldc.r4", GINT_TO_POINTER (TRUE)); g_hash_table_insert (key_table, (char *) "ldc.r8", GINT_TO_POINTER (TRUE)); + g_hash_table_insert (key_table, (char *) "ldelem", GINT_TO_POINTER (TRUE)); g_hash_table_insert (key_table, (char *) "ldelema", GINT_TO_POINTER (TRUE)); g_hash_table_insert (key_table, (char *) "ldelem.i1", GINT_TO_POINTER (TRUE)); g_hash_table_insert (key_table, (char *) "ldelem.i2", GINT_TO_POINTER (TRUE)); @@ -2520,6 +2896,8 @@ init_key_table (void) g_hash_table_insert (key_table, (char *) "nullref", GINT_TO_POINTER (TRUE)); g_hash_table_insert (key_table, (char *) "object", GINT_TO_POINTER (TRUE)); g_hash_table_insert (key_table, (char *) "objectref", GINT_TO_POINTER (TRUE)); + g_hash_table_insert (key_table, (char *) "off", GINT_TO_POINTER (TRUE)); + g_hash_table_insert (key_table, (char *) "on", GINT_TO_POINTER (TRUE)); g_hash_table_insert (key_table, (char *) "opt", GINT_TO_POINTER (TRUE)); g_hash_table_insert (key_table, (char *) "optil", GINT_TO_POINTER (TRUE)); g_hash_table_insert (key_table, (char *) "or", GINT_TO_POINTER (TRUE)); @@ -2541,6 +2919,7 @@ init_key_table (void) g_hash_table_insert (key_table, (char *) "preservesig", GINT_TO_POINTER (TRUE)); g_hash_table_insert (key_table, (char *) "private", GINT_TO_POINTER (TRUE)); g_hash_table_insert (key_table, (char *) "privatescope", GINT_TO_POINTER (TRUE)); + g_hash_table_insert (key_table, (char *) "property", GINT_TO_POINTER (TRUE)); g_hash_table_insert (key_table, (char *) "protected", GINT_TO_POINTER (TRUE)); g_hash_table_insert (key_table, (char *) "public", GINT_TO_POINTER (TRUE)); g_hash_table_insert (key_table, (char *) "readonly", GINT_TO_POINTER (TRUE)); @@ -2574,6 +2953,7 @@ init_key_table (void) g_hash_table_insert (key_table, (char *) "starg.s", GINT_TO_POINTER (TRUE)); g_hash_table_insert (key_table, (char *) "static", GINT_TO_POINTER (TRUE)); g_hash_table_insert (key_table, (char *) "stdcall", GINT_TO_POINTER (TRUE)); + g_hash_table_insert (key_table, (char *) "stelem", GINT_TO_POINTER (TRUE)); g_hash_table_insert (key_table, (char *) "stelem.i1", GINT_TO_POINTER (TRUE)); g_hash_table_insert (key_table, (char *) "stelem.i2", GINT_TO_POINTER (TRUE)); g_hash_table_insert (key_table, (char *) "stelem.i4", GINT_TO_POINTER (TRUE)); @@ -2590,6 +2970,8 @@ init_key_table (void) g_hash_table_insert (key_table, (char *) "stind.i", GINT_TO_POINTER (TRUE)); g_hash_table_insert (key_table, (char *) "stind.r4", GINT_TO_POINTER (TRUE)); g_hash_table_insert (key_table, (char *) "stind.r8", GINT_TO_POINTER (TRUE)); + g_hash_table_insert (key_table, (char *) "stloc", GINT_TO_POINTER (TRUE)); + g_hash_table_insert (key_table, (char *) "stobj", GINT_TO_POINTER (TRUE)); g_hash_table_insert (key_table, (char *) "storage", GINT_TO_POINTER (TRUE)); g_hash_table_insert (key_table, (char *) "stored_object", GINT_TO_POINTER (TRUE)); g_hash_table_insert (key_table, (char *) "streamed_object", GINT_TO_POINTER (TRUE)); @@ -2597,6 +2979,11 @@ init_key_table (void) g_hash_table_insert (key_table, (char *) "strict", GINT_TO_POINTER (TRUE)); g_hash_table_insert (key_table, (char *) "string", GINT_TO_POINTER (TRUE)); g_hash_table_insert (key_table, (char *) "struct", GINT_TO_POINTER (TRUE)); + g_hash_table_insert (key_table, (char *) "stsfld", GINT_TO_POINTER (TRUE)); + g_hash_table_insert (key_table, (char *) "sub", GINT_TO_POINTER (TRUE)); + g_hash_table_insert (key_table, (char *) "sub.ovf", GINT_TO_POINTER (TRUE)); + g_hash_table_insert (key_table, (char *) "sub.ovf.un", GINT_TO_POINTER (TRUE)); + g_hash_table_insert (key_table, (char *) "switch", GINT_TO_POINTER (TRUE)); g_hash_table_insert (key_table, (char *) "synchronized", GINT_TO_POINTER (TRUE)); g_hash_table_insert (key_table, (char *) "syschar", GINT_TO_POINTER (TRUE)); g_hash_table_insert (key_table, (char *) "sysstring", GINT_TO_POINTER (TRUE)); @@ -2607,6 +2994,12 @@ init_key_table (void) g_hash_table_insert (key_table, (char *) "true", GINT_TO_POINTER (TRUE)); g_hash_table_insert (key_table, (char *) "type", GINT_TO_POINTER (TRUE)); g_hash_table_insert (key_table, (char *) "typedref", GINT_TO_POINTER (TRUE)); + g_hash_table_insert (key_table, (char *) "uint", GINT_TO_POINTER (TRUE)); + g_hash_table_insert (key_table, (char *) "uint8", GINT_TO_POINTER (TRUE)); + g_hash_table_insert (key_table, (char *) "uint16", GINT_TO_POINTER (TRUE)); + g_hash_table_insert (key_table, (char *) "uint32", GINT_TO_POINTER (TRUE)); + g_hash_table_insert (key_table, (char *) "uint64", GINT_TO_POINTER (TRUE)); + g_hash_table_insert (key_table, (char *) "unbox", GINT_TO_POINTER (TRUE)); g_hash_table_insert (key_table, (char *) "unicode", GINT_TO_POINTER (TRUE)); g_hash_table_insert (key_table, (char *) "unmanagedexp", GINT_TO_POINTER (TRUE)); g_hash_table_insert (key_table, (char *) "unmanaged", GINT_TO_POINTER (TRUE)); @@ -2622,6 +3015,7 @@ init_key_table (void) g_hash_table_insert (key_table, (char *) "wchar", GINT_TO_POINTER (TRUE)); g_hash_table_insert (key_table, (char *) "winapi", GINT_TO_POINTER (TRUE)); g_hash_table_insert (key_table, (char *) "with", GINT_TO_POINTER (TRUE)); + g_hash_table_insert (key_table, (char *) "xor", GINT_TO_POINTER (TRUE)); } guint32 @@ -2636,7 +3030,7 @@ method_dor_to_token (guint32 idx) { } char * -get_method_override (MonoImage *m, guint32 token, MonoGenericContext *context) +get_method_override (MonoImage *m, guint32 token, MonoGenericContainer *container) { MonoTableInfo *t = &m->tables [MONO_TABLE_METHODIMPL]; int i; @@ -2650,9 +3044,79 @@ get_method_override (MonoImage *m, guint32 token, MonoGenericContext *context) impl = method_dor_to_token (cols [MONO_METHODIMPL_BODY]); decl = method_dor_to_token (cols [MONO_METHODIMPL_DECLARATION]); - if (token == impl) - return get_method_core (m, decl, FALSE, context); + if (token == impl) { + MonoMethod *mh = NULL; + mh = mono_get_method_full (m, decl, NULL, (MonoGenericContext *) container); + + if (mh && (mh->klass && (mh->klass->generic_class || mh->klass->generic_container))) { + char *meth_str; + char *ret; + + meth_str = get_method_core (m, decl, TRUE, container); + ret = g_strdup_printf ("method %s", meth_str); + g_free (meth_str); + return ret; + } else { + return get_method_core (m, decl, FALSE, container); + } + } } return NULL; } + +static void +check_ambiguous_genparams (MonoGenericContainer *container) +{ + GSList *dup_list = NULL, *l; + GHashTable *table = NULL; + gpointer *p; + int i; + + if (!container) + return; + + if (generic_containers && g_hash_table_lookup (generic_containers, container)) + /* Already been checked for ambiguous gen params */ + return; + + table = g_hash_table_new (g_str_hash, g_str_equal); + for (i = 0; i < container->type_argc; i++) { + MonoGenericParam *param = &container->type_params [i]; + + if ((p = g_hash_table_lookup (table, param->name))) + dup_list = g_slist_prepend (g_slist_prepend (dup_list, GUINT_TO_POINTER (i + 1)), p); + else + g_hash_table_insert (table, (char*)param->name, GUINT_TO_POINTER (i + 1)); + } + + if (dup_list) { + if (!mono_generic_params_with_ambiguous_names) + mono_generic_params_with_ambiguous_names = g_hash_table_new (NULL, NULL); + for (l = dup_list; l; l = l->next) { + int param = GPOINTER_TO_UINT (l->data); + g_hash_table_insert (mono_generic_params_with_ambiguous_names, + &container->type_params [param-1], + &container->type_params [param-1]); + } + g_slist_free (dup_list); + } + + if (!generic_containers) + generic_containers = g_hash_table_new (NULL, NULL); + + g_hash_table_insert (generic_containers, container, container); + g_hash_table_destroy (table); +} + +static gboolean +cant_print_generic_param_name (MonoGenericParam *gparam) +{ + g_assert (gparam); + + check_ambiguous_genparams (gparam->owner); + return (!gparam->owner || (mono_generic_params_with_ambiguous_names && + g_hash_table_lookup (mono_generic_params_with_ambiguous_names, gparam))); +} + +