2005-08-13 Jb Evain <jbevain@gmail.com>
[mono.git] / mono / dis / get.c
index 2ab9a9aa9a48d06c695eb7aa2f9595ff2ec701fd..f76a8b1b326bce19b90e3bf9a3cefb7548f4bdbb 100644 (file)
@@ -12,6 +12,7 @@
 #include <string.h>
 #include <ctype.h>
 #include <glib.h>
+#include <math.h>
 #include "meta.h"
 #include "util.h"
 #include "get.h"
@@ -51,7 +52,7 @@ get_typedef (MonoImage *m, int idx)
                 
                 outer = get_typedef (m, mono_metadata_token_index (token));
                 result = g_strdup_printf (
-                        "%s%s%s/%s%s", ns, *ns?".":"", outer,
+                        "%s/%s%s", outer,
                         mono_metadata_string_heap (m, cols [MONO_TYPEDEF_NAME]),
                        tstring ? tstring : "");
                g_free (outer);
@@ -169,7 +170,7 @@ 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, MonoGenericContext *context)
+get_typespec (MonoImage *m, guint32 idx, gboolean is_def, MonoGenericContext *context)
 {
        guint32 cols [MONO_TYPESPEC_SIZE];
        const char *ptr;
@@ -234,15 +235,8 @@ get_typespec (MonoImage *m, guint32 idx, MonoGenericContext *context)
                g_free (s);
                break;
 
-       case MONO_TYPE_VAR:
-       case MONO_TYPE_MVAR:
-               ptr = get_type (m, ptr-1, &s, context);
-               g_string_append (res, s);
-               g_free (s);
-               break;
-               
        default:
-               s = dis_stringify_type (m, type, FALSE);
+               s = dis_stringify_type (m, type, is_def);
                g_string_append (res, s);
                g_free (s);
                break;
@@ -351,7 +345,7 @@ get_typedef_or_ref (MonoImage *m, guint32 dor_token, MonoGenericContext *context
                break;
                
        case 2: /* TypeSpec */
-               s = get_typespec (m, idx, context);
+               s = get_typespec (m, idx, FALSE, context);
                break;
 
        default:
@@ -452,7 +446,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" },
@@ -476,7 +470,7 @@ dis_stringify_token (MonoImage *m, guint32 token)
        switch (token >> 24) {
        case MONO_TABLE_TYPEDEF: return get_typedef (m, idx);
        case MONO_TABLE_TYPEREF: return get_typeref (m, idx);
-       case MONO_TABLE_TYPESPEC: return get_typespec (m, idx, NULL);
+       case MONO_TABLE_TYPESPEC: return get_typespec (m, idx, FALSE, NULL);
        default:
                 break;
        }
@@ -535,9 +529,10 @@ dis_stringify_param (MonoImage *m, MonoType *param)
        char *t;
        char *result;
        char *attribs;
+       const char *in = param->attrs & PARAM_ATTRIBUTE_IN ? "[in]" : "";
        const char *out = param->attrs & PARAM_ATTRIBUTE_OUT ? "[out]": "";
        const char *opt = param->attrs & PARAM_ATTRIBUTE_OPTIONAL ? "[opt]": "";
-       attribs = g_strconcat(out, opt, NULL);
+       attribs = g_strconcat(in, out, opt, NULL);
        t = dis_stringify_type (m, param, TRUE);
        result = g_strjoin(attribs[0] ? " ":"", attribs, t, NULL);
        g_free (t);
@@ -545,6 +540,229 @@ 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: <v_type> vector */
+               return g_strdup ("vector");
+       case MONO_VARIANT_ARRAY:
+               /* FIXME: output: <v_type> [ ] */
+               return g_strdup ("[]");
+       case MONO_VARIANT_BYREF:
+               /* FIXME: output: <v_type> & */
+               return g_strdup ("&");
+       default:
+               return g_strdup ("unknown");
+       }
+}
+
+static char*
+dis_stringify_native_type (MonoMarshalNative native)
+{
+       switch (native) {
+       case MONO_NATIVE_BOOLEAN:
+               return g_strdup ("bool");
+       case MONO_NATIVE_I1:
+               return g_strdup ("int8");
+       case MONO_NATIVE_U1:
+               return g_strdup ("unsigned int8");
+       case MONO_NATIVE_I2:
+               return g_strdup ("int16");
+       case MONO_NATIVE_U2:
+               return g_strdup ("unsigned int16");
+       case MONO_NATIVE_I4:
+               return g_strdup ("int32");
+       case MONO_NATIVE_U4:
+               return g_strdup ("unsigned int32");
+       case MONO_NATIVE_I8:
+               return g_strdup ("int64");
+       case MONO_NATIVE_U8:
+               return g_strdup ("unsigned int64");
+       case MONO_NATIVE_R4:
+               return g_strdup ("float32");
+       case MONO_NATIVE_R8:
+               return g_strdup ("float64");
+       case MONO_NATIVE_CURRENCY:
+               return g_strdup ("currency");
+       case MONO_NATIVE_BSTR:
+               return g_strdup ("bstr");
+       case MONO_NATIVE_LPSTR:
+               return g_strdup ("lpstr");
+       case MONO_NATIVE_LPWSTR:
+               return g_strdup ("lpwstr");
+       case MONO_NATIVE_LPTSTR:
+               return g_strdup ("lptstr");
+       case MONO_NATIVE_IUNKNOWN:
+               return g_strdup ("iunknown");
+       case MONO_NATIVE_IDISPATCH:
+               return g_strdup ("idispatch");
+       case MONO_NATIVE_STRUCT:
+               return g_strdup ("struct");
+       case MONO_NATIVE_INTERFACE:
+               return g_strdup ("interface");
+       case MONO_NATIVE_SAFEARRAY:
+               return g_strdup ("safearray");
+       case MONO_NATIVE_INT:
+               return g_strdup ("int");
+       case MONO_NATIVE_UINT:
+               return g_strdup ("unsigned int");
+       case MONO_NATIVE_VBBYREFSTR:
+               return g_strdup ("vbbyrefstr");
+       case MONO_NATIVE_ANSIBSTR:
+               return g_strdup ("ansi bstr");
+       case MONO_NATIVE_TBSTR:
+               return g_strdup ("tbstr");
+       case MONO_NATIVE_VARIANTBOOL:
+               return g_strdup ("variant bool");
+       case MONO_NATIVE_FUNC:
+               return g_strdup ("method");
+       case MONO_NATIVE_ASANY:
+               return g_strdup ("as any");
+       case MONO_NATIVE_LPSTRUCT:
+               return g_strdup ("lpstruct");
+       case MONO_NATIVE_CUSTOM:
+               return g_strdup ("custom");
+       case MONO_NATIVE_ERROR:
+               return g_strdup ("error");
+       case MONO_NATIVE_MAX:
+               return g_strdup ("");
+       default:
+               return g_strdup ("unknown");
+       }
+}
+
+char*
+dis_stringify_marshal_spec (MonoMarshalSpec *spec)
+{
+       switch (spec->native) {
+       case MONO_NATIVE_BYVALTSTR:
+               return g_strdup_printf (" marshal (fixed sysstring [%d])", spec->data.array_data.num_elem);
+       case MONO_NATIVE_BYVALARRAY:
+               return g_strdup_printf (" marshal (fixed array [%d])", spec->data.array_data.num_elem);
+       case MONO_NATIVE_LPARRAY: {
+               char *elem_type, *elems, *ret;
+               guint32 num_elem = spec->data.array_data.num_elem;
+               guint32 param_num = spec->data.array_data.param_num;
+
+               elem_type = dis_stringify_native_type (spec->data.array_data.elem_type);
+               if (num_elem == -1 && param_num == -1)
+                       elems = g_strdup ("");
+               else if ((param_num == -1) || (spec->data.array_data.elem_mult == 0))
+                       elems = g_strdup_printf ("%d", num_elem);
+               else if ((num_elem == -1) || (num_elem == 0))
+                       elems = g_strdup_printf ("+ %d", param_num);
+               else
+                       elems = g_strdup_printf ("%d + %d", num_elem, param_num);
+                       
+               ret = g_strdup_printf (" marshal (%s[%s])", elem_type, elems);
+               g_free (elem_type);
+               g_free (elems);
+               return ret;
+       }
+       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;
+       }
+       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;
+       }       
+       }
+}
+
 /**
  * get_generic_param
  * @m: metadata context 
@@ -592,7 +810,7 @@ get_generic_param (MonoImage *m, MonoGenericContainer *container)
                                first = 0;
                        } else
                                g_string_append (result, ", ");
-                       sig = dis_stringify_object_with_class (m, *constr, TRUE, TRUE);
+                       sig = dis_stringify_type (m, &((*constr)->byval_arg), TRUE);
                        g_string_append (result, sig);
                        g_free (sig);
                 }
@@ -618,15 +836,18 @@ dis_stringify_method_signature (MonoImage *m, MonoMethodSignature *method, int m
 {
        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 *name = "", *method_name = "";
        int free_method = 0;
        char *retval, *esname;
        char *type = NULL;
+       char *marshal_info = NULL, *ret_marshal_info = NULL;
        char *gen_param = NULL;
        GString *result = g_string_new ("");
+       GString *result_ret = g_string_new ("");
        MonoGenericContainer *container = NULL;
-       int i;
+       int i, start;
         
        g_assert (method || methoddef_row);
 
@@ -634,7 +855,7 @@ 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]);
@@ -652,46 +873,91 @@ dis_stringify_method_signature (MonoImage *m, MonoMethodSignature *method, int m
 
                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;
+               name = "";
+               has_param_row = param_index && param_index < next_param_index;
+
+               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];
-                       param_index++;
+               
+               if (has_param_row && i == pcols [MONO_PARAM_SEQUENCE]) {
+                       if (i)
+                               name = mono_metadata_string_heap (m, pcols [MONO_PARAM_NAME]);
+
+                       if (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);
+
+                               if (i)
+                                       marshal_info = dis_stringify_marshal_spec (spec);
+                               else
+                                       ret_marshal_info = dis_stringify_marshal_spec (spec);
+                       }
+                       param_index ++;
                } else {
-                       name = "";
+                       if (i)
+                               name = 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]);
+
+               retval = dis_stringify_param (m, method->params [i - 1]);
+
                esname = get_escaped_name (name);
-               g_string_append_printf (result, "%s %s", retval, esname);
+               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);
+       }
+       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);
@@ -740,6 +1006,9 @@ get_escaped_class_name (MonoClass *c)
 {
        char *result, *esname;
 
+       if (c->rank || c->byval_arg.type == MONO_TYPE_PTR) 
+               g_assert (0);
+
        esname = get_escaped_name (c->name);
 
        if (c->nested_in){
@@ -760,7 +1029,8 @@ char *
 dis_stringify_object_with_class (MonoImage *m, MonoClass *c, gboolean prefix, gboolean is_def)
 {
        /* FIXME: handle MONO_TYPE_OBJECT ... */
-       const char *otype = c->byval_arg.type == MONO_TYPE_VALUETYPE ? "valuetype " : "class " ;
+       MonoType *type = &c->byval_arg;
+       const char *otype = type->type == MONO_TYPE_VALUETYPE ? "valuetype " : "class " ;
        char *assemblyref = NULL, *result, *esname, *generic = NULL;
        
        if (m != c->image) {
@@ -897,7 +1167,8 @@ dis_stringify_type (MonoImage *m, MonoType *type, gboolean is_def)
        case MONO_TYPE_GENERICINST: {
                GString *str = g_string_new ("");
                int i;
-               char *generic_type = dis_stringify_type (m, type->data.generic_class->generic_type, is_def);
+               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);
@@ -1097,7 +1368,7 @@ get_ret_type (MonoImage *m, const char *ptr, char **ret_type, MonoGenericContext
        }
 
        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");
@@ -1143,7 +1414,7 @@ get_param (MonoImage *m, const char *ptr, char **retval, MonoGenericContext *con
        }
        
        if (*ptr == MONO_TYPE_TYPEDBYREF){
-               g_string_append (str, " typedbyref ");
+               g_string_append (str, " typedref ");
                ptr++;
        } else {
                gboolean by_ref = 0;
@@ -1174,6 +1445,7 @@ char*
 get_escaped_name (const char *name)
 {
        const char *s;
+       char *tmp, *tmp2;
 
        g_assert (key_table);
 
@@ -1194,7 +1466,8 @@ get_escaped_name (const char *name)
        }
 
        for (s = name; *s; s++) {
-               if (isalnum (*s) || *s == '_' || *s == '$' || *s == '@' || *s == '?' || *s == '.' || *s == 0)
+               if (isalnum (*s) || *s == '_' || *s == '$' || *s == '@' ||
+                   *s == '?' || *s == '.' || *s == 0 || *s == '!')
                        continue;
 
                return g_strdup_printf ("'%s'", name);
@@ -1240,7 +1513,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 }
 };
 
@@ -1477,7 +1750,7 @@ get_memberref_parent (MonoImage *m, guint32 mrp_token, MonoGenericContext *conte
                return g_strdup ("TODO:MethodDef");
                
        case 4: /* TypeSpec */
-               return get_typespec (m, idx, context);
+               return get_typespec (m, idx, FALSE, context);
        }
        g_assert_not_reached ();
        return NULL;
@@ -1492,7 +1765,7 @@ get_memberref_parent (MonoImage *m, guint32 mrp_token, MonoGenericContext *conte
  * Since there is no backpointer in the Field table, we have to scan
  * the TypeDef table and locate the actual "owner" of the field
  */
-char *
+static char *
 get_method_core (MonoImage *m, guint32 token, gboolean fullsig, MonoGenericContext *context)
 {
        int idx = mono_metadata_token_index (token);
@@ -1504,10 +1777,10 @@ get_method_core (MonoImage *m, guint32 token, gboolean fullsig, MonoGenericConte
 
        mh = mono_get_method_full (m, token, NULL, context);
        if (mh) {
-               if (mh->signature->is_inflated)
+               if (mono_method_signature (mh)->is_inflated)
                        context = ((MonoMethodInflated *) mh)->context;
                esname = get_escaped_name (mh->name);
-               sig = dis_stringify_object_with_class (m, mh->klass, TRUE, TRUE);
+               sig = dis_stringify_type (m, &mh->klass->byval_arg, TRUE);
                if (show_tokens)
                        name = g_strdup_printf ("%s/*%08x*/::%s", sig, token, esname);
                else
@@ -1587,7 +1860,7 @@ get_methoddef (MonoImage *m, guint32 idx)
 
        mh = mono_get_method (m, MONO_TOKEN_METHOD_DEF | idx, NULL);
        if (mh) {
-               sig = dis_stringify_object_with_class (m, mh->klass, TRUE, FALSE);
+               sig = dis_stringify_type (m, &mh->klass->byval_arg, FALSE);
                name = g_strdup_printf ("%s::%s", sig, mh->name);
                g_free (sig);
        } else
@@ -1757,34 +2030,44 @@ 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: {
                float r;
                readr4 (ptr, &r);
-               return g_strdup_printf ("float32(%g)", (double) r);
-       }
+               if (! isnormal (r))
+                       return g_strdup_printf ("float32(0x%08x)", read32 (ptr));
+               else
+                       return g_strdup_printf ("float32(%g)", r);
+       }       
        case MONO_TYPE_R8: {
                double r;
                readr8 (ptr, &r);
-               return g_strdup_printf ("float64(%g)", r);
+               if (! isnormal (r)) {
+                       guint32 low, high;
+                       low = read32 (ptr);
+                       high = read32 (ptr + 4);
+                       return g_strdup_printf ("float64(0x%08x%08x)", high, low);
+               } else {
+                       return g_strdup_printf ("float64(%g)", r);
+               }
        }
        case MONO_TYPE_STRING: {
                gchar *str;
                int i, j, tspaces = (len%16);
-               GString *res = g_string_new ("bytearray (\n\t");
+               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]);
@@ -1854,15 +2137,9 @@ get_token (MonoImage *m, guint32 token, MonoGenericContext *context)
                g_free (temp);
                return result;
        case MONO_TOKEN_TYPE_REF:
-               temp = get_typeref (m, idx);
-               result = get_escaped_name (temp);
-               g_free (temp);
-               return result;
+               return get_typeref (m, idx);
        case MONO_TOKEN_TYPE_SPEC:
-               temp = get_typespec (m, idx, context);
-               result = get_escaped_name (temp);
-               g_free (temp);
-               return result;
+               return get_typespec (m, idx, TRUE, context);
        case MONO_TOKEN_MEMBER_REF: {
                guint32 cols [MONO_MEMBERREF_SIZE];
                const char *sig;
@@ -1874,9 +2151,11 @@ get_token (MonoImage *m, guint32 token, MonoGenericContext *context)
                        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, context);
+                       result = g_strdup_printf ("method %s", temp);
+                       g_free (temp);
+                       return result;
                }
                break;
        }
@@ -1917,7 +2196,7 @@ get_token_type (MonoImage *m, guint32 token, MonoGenericContext *context)
                break;
                
        case MONO_TOKEN_TYPE_SPEC:
-               s = get_typespec (m, idx, context);
+               s = get_typespec (m, idx, FALSE, context);
                break;
 
        default:
@@ -2476,6 +2755,7 @@ init_key_table (void)
        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));
        g_hash_table_insert (key_table, (char *) "stream", GINT_TO_POINTER (TRUE));
+       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 *) "synchronized", GINT_TO_POINTER (TRUE));
@@ -2503,6 +2783,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