*
* (C) 2001 Ximian, Inc.
* Copyright 2012 Xamarin Inc
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
*/
#include <config.h>
#include <stdio.h>
#include <mono/utils/mono-compiler.h>
#include <mono/metadata/class.h>
#include <mono/metadata/marshal.h>
+#include <mono/metadata/metadata-internals.h>
extern gboolean substitute_with_mscorlib_p;
+static char *
+get_token_comment (const char *prefix, guint32 token);
+
static MonoGenericContainer *
get_memberref_container (MonoImage *m, guint32 mrp_token, MonoGenericContainer *container);
/* Check if this is a nested type */
token = MONO_TOKEN_TYPE_DEF | (idx);
token = mono_metadata_nested_in_typedef (m, token);
- tstring = show_tokens ? g_strdup_printf ("/*%08x*/", token) : NULL;
+ tstring = get_token_comment (NULL, token);
if (token) {
char *outer;
if (show_tokens) {
int token = mono_metadata_make_token (MONO_TABLE_TYPESPEC, idx);
- result = g_strdup_printf ("%s/*%08x*/", res->str, token);
- } else
+ result = get_token_comment (res->str, token);
+ g_string_free (res, TRUE);
+ } else {
result = res->str;
-
- g_string_free (res, FALSE);
+ g_string_free (res, FALSE);
+ }
return result;
}
if (show_tokens) {
int token = mono_metadata_make_token (MONO_TABLE_TYPEREF, idx);
- char *temp = g_strdup_printf ("%s/*%08x*/", ret, token);
+ char *temp = get_token_comment (ret, token);
g_free (ret);
ret = temp;
}
esname = get_escaped_class_name (c);
- if (c->generic_class) {
- MonoGenericClass *gclass = c->generic_class;
+ if (mono_class_is_ginst (c)) {
+ MonoGenericClass *gclass = mono_class_get_generic_class (c);
MonoGenericInst *inst = gclass->context.class_inst;
GString *str = g_string_new ("");
int i;
const char *
get_type (MonoImage *m, const char *ptr, char **result, gboolean is_def, MonoGenericContainer *container)
{
+ MonoError error;
const char *start = ptr;
guint32 type;
MonoType *t;
case MONO_TYPE_VALUETYPE:
case MONO_TYPE_CLASS: {
guint32 token = mono_metadata_parse_typedef_or_ref (m, ptr, &ptr);
- MonoClass *klass = mono_class_get (m, token);
+ MonoClass *klass = mono_class_get_checked (m, token, &error);
char *temp;
- if (klass)
+ if (klass) {
temp = dis_stringify_object_with_class (m, klass, TRUE, FALSE);
- else
- temp = g_strdup_printf ("<BROKEN CLASS token_%8x>", token);
+ } else {
+ temp = g_strdup_printf ("<BROKEN CLASS token_%8x due to %s>", token, mono_error_get_message (&error));
+ mono_error_cleanup (&error);
+ }
if (show_tokens) {
- *result = g_strdup_printf ("%s/*%08x*/", temp, token);
+ *result = get_token_comment (temp, token);
g_free (temp);
} else
*result = temp;
}
default:
- t = mono_metadata_parse_type_full (m, container, 0, start, &ptr);
+ t = mono_metadata_parse_type_checked (m, container, 0, FALSE, start, &ptr, &error);
if (t) {
*result = dis_stringify_type (m, t, is_def);
} else {
- GString *err = g_string_new ("@!#$<InvalidType>$#!@");
- if (container)
- t = mono_metadata_parse_type_full (m, NULL, 0, start, &ptr);
- if (t) {
- char *name = dis_stringify_type (m, t, is_def);
- g_warning ("Encountered a generic type inappropriate for its context");
- g_string_append (err, " // ");
- g_string_append (err, name);
- g_free (name);
- } else {
- g_warning ("Encountered an invalid type");
- }
- *result = g_string_free (err, FALSE);
+ *result = g_strdup_printf ("Invalid type due to %s", mono_error_get_message (&error));
+ mono_error_cleanup (&error);
}
break;
return full_sig;
}
+/**
+ * get_token_comment:
+ *
+ * If show_tokens is TRUE, return "prefix""token(table)".
+ * If show_tokens is FALSE, return "prefix" or NULL if prefix is NULL.
+ * Caller is responsible for freeing.
+ */
+char *
+get_token_comment (const char *prefix, guint32 token)
+{
+ if (!show_tokens)
+ return prefix ? g_strdup_printf ("%s", prefix) : NULL;
+ gint32 tableidx = mono_metadata_token_table (token);
+ if ((tableidx < 0) || (tableidx > MONO_TABLE_LAST))
+ return g_strdup_printf ("%s/*%08x*/", prefix ? prefix : "", token);
+ else
+ return g_strdup_printf ("%s/*%08x(%s)*/", prefix ? prefix : "", token, mono_meta_table_name (tableidx));
+}
+
/**
* get_field:
* @m: metadata context
{
int idx = mono_metadata_token_index (token);
guint32 cols [MONO_FIELD_SIZE];
- char *sig, *res, *type, *estype, *esname;
+ char *sig, *res, *type, *estype, *esname, *token_comment;
guint32 type_idx;
/*
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%s",
+ token_comment = get_token_comment (NULL, token);
+ res = g_strdup_printf ("%s %s%s%s%s",
sig,
estype ? estype : "",
estype ? "::" : "",
- esname);
+ esname,
+ token_comment ? token_comment : ""
+ );
g_free (type);
g_free (sig);
g_free (estype);
g_free (esname);
+ g_free (token_comment);
return res;
}
case 4: /* TypeSpec */
klass = mono_class_get_full (m, MONO_TOKEN_TYPE_SPEC | idx, (MonoGenericContext *) container);
g_assert (klass);
- return klass->generic_class ? klass->generic_class->container_class->generic_container : NULL;
+ return mono_class_is_ginst (klass) ? mono_class_get_generic_container (mono_class_get_generic_class (klass)->container_class) : NULL;
}
g_assert_not_reached ();
return NULL;
static char *
get_method_core (MonoImage *m, guint32 token, gboolean fullsig, MonoGenericContainer *container)
{
+ MonoError error;
int idx = mono_metadata_token_index (token);
guint32 member_cols [MONO_MEMBERREF_SIZE], method_cols [MONO_METHOD_SIZE];
char *sig = NULL, *esname;
MonoMethod *mh;
MonoGenericContainer *type_container = container;
- mh = mono_get_method_full (m, token, NULL, (MonoGenericContext *) container);
+ mh = mono_get_method_checked (m, token, NULL, (MonoGenericContext *) container, &error);
if (mh) {
if (mono_method_signature (mh)->is_inflated)
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%s", sig ? sig : "", token, sig ? "::" : "", esname);
- else
- name = g_strdup_printf ("%s%s%s", sig ? sig : "", sig ? "::" : "", esname);
+ char *token_comment = get_token_comment (NULL, token);
+ name = g_strdup_printf ("%s%s%s%s", sig ? sig : "", token_comment ? token_comment : "", sig ? "::" : "", esname);
g_free (sig);
g_free (esname);
- } else
+ g_free (token_comment);
+ } else {
name = NULL;
+ mono_error_cleanup (&error);
+ }
switch (mono_metadata_token_code (token)){
case MONO_TOKEN_METHOD_DEF:
}
if (show_tokens) {
- char *retval = g_strdup_printf ("%s /* %08x */", sig, token);
+ char *retval = get_token_comment (sig, token);
g_free (sig);
return retval;
} else
char *
get_methoddef (MonoImage *m, guint32 idx)
{
- guint32 cols [MONO_METHOD_SIZE];
+ MonoError error;
+ guint32 cols [MONO_METHOD_SIZE];
char *sig;
const char *name;
MonoMethod *mh;
- mh = mono_get_method (m, MONO_TOKEN_METHOD_DEF | idx, NULL);
+ mh = mono_get_method_checked (m, MONO_TOKEN_METHOD_DEF | idx, NULL, NULL, &error);
if (mh) {
sig = dis_stringify_type (m, &mh->klass->byval_arg, FALSE);
name = g_strdup_printf ("%s%s%s",
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);
+ } else {
+ name = g_strdup_printf ("!bad-method-name!");
+ mono_error_cleanup (&error);
+ }
+ 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);
- return sig;
+ return sig;
}
char *
char *
get_methodspec (MonoImage *m, int idx, guint32 token, const char *fancy_name, MonoGenericContainer *type_container)
{
- GString *res = g_string_new ("");
+ MonoError error;
+ GString *res = g_string_new ("");
guint32 member_cols [MONO_MEMBERREF_SIZE], method_cols [MONO_METHOD_SIZE];
char *s, *type_param;
const char *ptr;
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);
+ mh = mono_get_method_checked (m, method_dor_to_token (token), NULL, (MonoGenericContext *) type_container, &error);
+ if (!mh) {
+ g_string_append_printf (res, "Could not decode method token 0x%x due to %s", token, mono_error_get_message (&error));
+ mono_error_cleanup (&error);
+ return g_string_free (res, FALSE);
+ }
+
container = mono_method_get_generic_container (mh);
if (!container)
container = type_container;
decl = method_dor_to_token (cols [MONO_METHODIMPL_DECLARATION]);
if (token == impl) {
+ MonoError error;
MonoMethod *mh = NULL;
- mh = mono_get_method_full (m, decl, NULL, (MonoGenericContext *) container);
+ mh = mono_get_method_checked (m, decl, NULL, (MonoGenericContext *) container, &error);
- if (mh && (mh->klass && (mh->klass->generic_class || mh->klass->generic_container))) {
+ if (mh && (mh->klass && (mono_class_is_ginst (mh->klass) || mono_class_is_gtd (mh->klass)))) {
char *meth_str;
char *ret;
g_free (meth_str);
return ret;
} else {
- return get_method_core (m, decl, FALSE, container);
+ if (!mono_error_ok (&error)) {
+ char *meth_str = get_method_core (m, decl, FALSE, container);
+ char *ret = g_strdup_printf ("Could not decode method override %s due to %s", meth_str, mono_error_get_message (&error));
+
+ mono_error_cleanup (&error);
+ g_free (meth_str);
+ return ret;
+ } else {
+ return get_method_core (m, decl, FALSE, container);
+ }
}
}
}
container = mono_generic_param_owner (gparam);
check_ambiguous_genparams (container);
return (!container || (mono_generic_params_with_ambiguous_names &&
- g_hash_table_lookup (mono_generic_params_with_ambiguous_names, gparam)));
+ g_hash_table_lookup (mono_generic_params_with_ambiguous_names, gparam)) || !mono_generic_param_info (gparam));
}