#include <string.h>
#include <ctype.h>
#include <glib.h>
+#include <math.h>
#include "meta.h"
#include "util.h"
#include "get.h"
+#include <mono/utils/mono-compiler.h>
#include <mono/metadata/class.h>
#include <mono/metadata/marshal.h>
static char *
get_memberref_parent (MonoImage *m, guint32 mrp_token, MonoGenericContext *context);
+
+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;
char *tstring, *result;
guint32 token;
+ if (idx == 1)
+ /* <Module> */
+ 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]);
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);
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 *
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 *
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);
}
/*
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;
}
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);
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, context);
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, context ? context->container : NULL, 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, context);
g_string_append (res, s);
g_free (s);
g_string_append_c (res, ' ');
g_string_append (res, s);
g_free (s);
break;
-
+
case MONO_TYPE_SZARRAY:
ptr = get_custom_mod (m, ptr, &s);
if (s){
g_string_append_c (res, ' ');
g_free (s);
}
- ptr = get_type (m, ptr, &s, context);
+ ptr = get_type (m, ptr, &s, is_def, context);
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, context);
g_string_append (res, s);
g_free (s);
break;
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;
{ 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" },
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*
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, ' ');
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);
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;
+ }
+ 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;
+ }
+ }
+}
+
/**
* get_generic_param
* @m: metadata context
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++) {
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);
}
char*
dis_stringify_method_signature (MonoImage *m, MonoMethodSignature *method, int methoddef_row,
MonoGenericContext *context, gboolean fully_qualified)
+{
+ return dis_stringify_method_signature_full (m, method, methoddef_row, context, 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,
+ MonoGenericContext *context, 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, *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);
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);
- if (container)
+ if (container) {
+ mono_metadata_load_generic_param_constraints (
+ m, MONO_TOKEN_METHOD_DEF | methoddef_row, container);
context = (MonoGenericContext *) 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);
+
+ 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);
+
+ 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 (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);
+
+ if (i)
+ marshal_info = dis_stringify_marshal_spec (spec);
+ else
+ ret_marshal_info = dis_stringify_marshal_spec (spec);
+ }
+ param_index ++;
+ } else {
+ if (i)
+ /* A_[0-9]* does not require escaping */
+ esname = g_strdup_printf ("A_%i", i - start);
+ }
+
+ if (!i)
+ continue;
+
+ if (i > 1)
+ g_string_append (result, ", ");
+
+ 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, "instance ");
- g_string_append (result, map (method->call_convention, call_conv_type_map));
- g_string_sprintfa (result, " %s ", retval);
+ 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, "%s::", estype);
+ g_string_sprintfa (result_ret, "%s::", estype);
g_free (estype);
+ g_free (type);
}
- esname = get_escaped_name (name);
- g_string_append (result, esname);
+ esname = get_escaped_name (method_name);
+ g_string_append (result_ret, 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) {
- 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++;
- } else {
- name = "";
- }
- if (i)
- g_string_append (result, ", ");
- retval = dis_stringify_param (m, method->params [i]);
- esname = get_escaped_name (name);
- g_string_append_printf (result, "%s %s", retval, esname);
- g_free (retval);
- g_free (esname);
+ if (gen_param) {
+ g_string_append (result_ret, gen_param);
+ g_free (gen_param);
}
- g_string_append (result, ") ");
+ 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 */ ",
{
char *result, *esname;
+ if (c->type_token == mono_metadata_make_token (MONO_TABLE_TYPEDEF, 1))
+ /* <Module> */
+ return NULL;
+
+ if (c->rank || c->byval_arg.type == MONO_TYPE_PTR)
+ g_assert (0);
+
esname = get_escaped_name (c->name);
if (c->nested_in){
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 (c->type_token == mono_metadata_make_token (MONO_TABLE_TYPEDEF, 1))
+ /* <Module> */
+ return NULL;
+
if (m != c->image) {
if (c->image->assembly_name) {
/* we cheat */
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: {
if (type->byref)
byref = "&";
+
+ if (!bare)
+ /* bare is NULL, for <Module> */
+ return bare;
- result = g_strconcat (mods ? mods : "", bare, byref, pinned, NULL);
+ result = g_strconcat (bare, byref, pinned, mods ? mods : "", NULL);
g_free (bare);
* 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, MonoGenericContext *context)
{
const char *start = ptr;
guint32 type;
int count, i;
char *temp;
- ptr = get_type (m, ptr, &temp, context);
+ ptr = get_type (m, ptr, &temp, is_def, context);
g_string_append (str, temp);
g_free (temp);
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, context);
g_string_append (str, temp);
}
}
default:
- t = mono_metadata_parse_type_full (m, context, MONO_PARSE_TYPE, 0, start, &ptr);
- *result = dis_stringify_type (m, t, FALSE);
+ t = mono_metadata_parse_type_full (m, context ? context->container : NULL, MONO_PARSE_TYPE, 0, start, &ptr);
+ *result = dis_stringify_type (m, t, is_def);
mono_metadata_free_type (t);
break;
}
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, context);
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);
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, context);
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);
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;
ptr++;
by_ref = 1;
}
- ptr = get_type (m, ptr, &allocated_type_string, context);
+ ptr = get_type (m, ptr, &allocated_type_string, FALSE, context);
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
*
get_escaped_name (const char *name)
{
const char *s;
+ char *ret, *esc;
+
+ if (!name)
+ return NULL;
g_assert (key_table);
for (s = name; *s; s++) {
if (isalnum (*s) || *s == '_' || *s == '$' || *s == '@' ||
- *s == '?' || *s == '.' || *s == 0 || *s == '!')
+ *s == '?' || *s == '.' || *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 [] = {
{ 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 }
};
* 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);
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);
}
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, ", ");
type = get_memberref_parent (m, cols [MONO_MEMBERREF_CLASS], context);
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);
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);
* 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);
char *name;
MonoMethod *mh;
+ MonoGenericContext *gc = context;
mh = mono_get_method_full (m, token, NULL, context);
if (mh) {
- if (mh->signature->is_inflated)
+ mh = mono_get_inflated_method (mh);
+ 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);
+ 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
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], context),
+ 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->generic_container)
+ arity = mh->generic_container->type_argc;
+ else
+ if (mh->is_inflated && ((MonoMethodInflated *)mh)->declaring->generic_container)
+ arity = ((MonoMethodInflated*) mh)->declaring->generic_container->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, gc);
break;
}
mh = mono_get_method (m, MONO_TOKEN_METHOD_DEF | idx, NULL);
if (mh) {
- sig = dis_stringify_object_with_class (m, mh->klass, TRUE, FALSE);
- name = g_strdup_printf ("%s::%s", sig, mh->name);
+ sig = dis_stringify_type (m, &mh->klass->byval_arg, FALSE);
+ 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;
}
const char *ptr;
guint32 sig = 0;
int param_count, cconv, i, gen_count = 0;
+ MonoGenericContainer *container = NULL;
+ MonoGenericContext *parent_context = context;
+ MonoMethod *mh = NULL;
switch (token & MONO_METHODDEFORREF_MASK) {
case MONO_METHODDEFORREF_METHODDEF:
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, parent_context);
+ g_assert (mh);
+ if ((container = mh->generic_container))
+ context = (MonoGenericContext*) container;
if (*ptr & 0x20){
if (*ptr & 0x40)
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, parent_context);
g_string_append (res, type_param);
g_string_append (res, " (");
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)
+{
+ unsigned 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:
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 = 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 (ptr, len);
case MONO_TYPE_CLASS:
return g_strdup ("nullref");
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;
}
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;
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;
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));
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));
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));
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));
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));
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));
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));
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));
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));
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));
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));
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
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, context);
+ mh = mono_get_inflated_method (mh);
+
+ 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, context);
+ ret = g_strdup_printf ("method %s", meth_str);
+ g_free (meth_str);
+ return ret;
+ } else {
+ return get_method_core (m, decl, FALSE, context);
+ }
+ }
}
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)));
+}
+
+