3 #include "mono/metadata/tokentype.h"
4 #include "mono/metadata/opcodes.h"
5 #include "mono/metadata/mono-endian.h"
6 #include "mono/metadata/debug-helpers.h"
8 struct MonoMethodDesc {
14 gboolean include_namespace;
17 static const char *wrapper_type_names [] = {
20 "delegate-begin-invoke",
21 "delegate-end-invoke",
26 "remoting-invoke-with-check",
34 append_class_name (GString *res, MonoClass *class, gboolean include_namespace)
37 g_string_append (res, "Unknown");
40 if (class->nested_in) {
41 append_class_name (res, class->nested_in, include_namespace);
42 g_string_append_c (res, '/');
44 if (include_namespace && *(class->name_space))
45 g_string_sprintfa (res, "%s.", class->name_space);
46 g_string_sprintfa (res, "%s", class->name);
50 mono_type_get_desc (GString *res, MonoType *type, gboolean include_namespace) {
53 g_string_append (res, "void"); break;
55 g_string_append (res, "char"); break;
56 case MONO_TYPE_BOOLEAN:
57 g_string_append (res, "bool"); break;
59 g_string_append (res, "byte"); break;
61 g_string_append (res, "sbyte"); break;
63 g_string_append (res, "uint16"); break;
65 g_string_append (res, "int16"); break;
67 g_string_append (res, "uint"); break;
69 g_string_append (res, "int"); break;
71 g_string_append (res, "ulong"); break;
73 g_string_append (res, "long"); break;
74 case MONO_TYPE_FNPTR: /* who cares for the exact signature? */
75 g_string_append (res, "*()"); break;
77 g_string_append (res, "uintptr"); break;
79 g_string_append (res, "intptr"); break;
81 g_string_append (res, "single"); break;
83 g_string_append (res, "double"); break;
84 case MONO_TYPE_STRING:
85 g_string_append (res, "string"); break;
86 case MONO_TYPE_OBJECT:
87 g_string_append (res, "object"); break;
89 mono_type_get_desc (res, type->data.type, include_namespace);
90 g_string_append_c (res, '*');
93 append_class_name (res, type->data.array->eklass, include_namespace);
94 g_string_sprintfa (res, "[%d]", type->data.array->rank);
96 case MONO_TYPE_SZARRAY:
97 mono_type_get_desc (res, &type->data.klass->byval_arg, include_namespace);
98 g_string_append (res, "[]");
100 case MONO_TYPE_CLASS:
101 case MONO_TYPE_VALUETYPE:
102 append_class_name (res, type->data.klass, include_namespace);
108 g_string_append_c (res, '&');
112 mono_type_full_name (MonoType *type)
117 str = g_string_new ("");
118 mono_type_get_desc (str, type, TRUE);
120 res = g_strdup (str->str);
121 g_string_free (str, TRUE);
126 mono_signature_get_desc (MonoMethodSignature *sig, gboolean include_namespace)
130 GString *res = g_string_new ("");
132 for (i = 0; i < sig->param_count; ++i) {
134 g_string_append_c (res, ',');
135 mono_type_get_desc (res, sig->params [i], include_namespace);
138 g_string_free (res, FALSE);
143 * The allowed format of a method description string is:
144 * [namespace.]classname:methodname[(args...)]
145 * TODO: describe instance methods.
148 mono_method_desc_new (const char *name, gboolean include_namespace)
150 MonoMethodDesc *result;
151 char *class_name, *class_nspace, *method_name, *use_args, *end;
154 class_nspace = g_strdup (name);
155 use_args = strchr (class_nspace, '(');
158 end = strchr (use_args, ')');
160 g_free (class_nspace);
165 method_name = strrchr (class_nspace, ':');
167 g_free (class_nspace);
171 /* allow two :: to separate the method name */
172 if (*method_name == ':')
174 class_name = strrchr (class_nspace, '.');
179 class_name = class_nspace;
182 result = g_new0 (MonoMethodDesc, 1);
183 result->include_namespace = include_namespace;
184 result->name = method_name;
185 result->klass = class_name;
186 result->namespace = use_namespace? class_nspace: NULL;
187 result->args = use_args? use_args: NULL;
191 result->num_args = 1;
203 mono_method_desc_from_method (MonoMethod *method)
205 MonoMethodDesc *result;
207 result = g_new0 (MonoMethodDesc, 1);
208 result->include_namespace = TRUE;
209 result->name = g_strdup (method->name);
210 result->klass = g_strdup (method->klass->name);
211 result->namespace = g_strdup (method->klass->name_space);
217 mono_method_desc_free (MonoMethodDesc *desc)
220 g_free (desc->namespace);
221 else if (desc->klass)
222 g_free (desc->klass);
227 * namespace and class are supposed to match already if this function is used.
230 mono_method_desc_match (MonoMethodDesc *desc, MonoMethod *method)
233 if (strcmp (desc->name, method->name))
237 if (desc->num_args != method->signature->param_count)
239 sig = mono_signature_get_desc (method->signature, desc->include_namespace);
240 if (strcmp (sig, desc->args)) {
249 mono_method_desc_full_match (MonoMethodDesc *desc, MonoMethod *method)
251 if (strcmp (desc->klass, method->klass->name))
253 if (desc->namespace && strcmp (desc->namespace, method->klass->name_space))
255 return mono_method_desc_match (desc, method);
259 mono_method_desc_search_in_class (MonoMethodDesc *desc, MonoClass *klass)
263 mono_class_init (klass);
264 for (i = 0; i < klass->method.count; ++i) {
265 if (mono_method_desc_match (desc, klass->methods [i]))
266 return klass->methods [i];
272 mono_method_desc_search_in_image (MonoMethodDesc *desc, MonoImage *image)
276 MonoTableInfo *methods;
280 if (desc->namespace && desc->klass) {
281 klass = mono_class_from_name (image, desc->namespace, desc->klass);
284 return mono_method_desc_search_in_class (desc, klass);
287 tdef = &image->tables [MONO_TABLE_TYPEDEF];
288 methods = &image->tables [MONO_TABLE_METHOD];
289 for (i = 0; i < methods->rows; ++i) {
290 guint32 token = mono_metadata_decode_row_col (methods, i, MONO_METHOD_NAME);
291 const char *n = mono_metadata_string_heap (image, token);
293 if (strcmp (n, desc->name))
295 method = mono_get_method (image, MONO_TOKEN_METHOD_DEF | (i + 1), NULL);
296 if (mono_method_desc_full_match (desc, method))
302 static const unsigned char*
303 dis_one (GString *str, MonoDisHelper *dh, MonoMethod *method, const unsigned char *ip)
305 MonoMethodHeader *header = ((MonoMethodNormal*)method)->header;
306 const MonoOpcode *opcode;
307 guint32 i, label, token;
311 label = ip - header->code;
313 tmp = dh->indenter (dh, method, label);
314 g_string_append (str, tmp);
317 if (dh->label_format)
318 g_string_sprintfa (str, dh->label_format, label);
320 i = mono_opcode_value (&ip);
322 opcode = &mono_opcodes [i];
323 g_string_sprintfa (str, "%-10s", mono_opcode_names [i]);
325 switch (opcode->argument) {
329 case MonoInlineField:
330 case MonoInlineMethod:
335 tmp = dh->tokener (dh, method, token);
336 g_string_append (str, tmp);
339 g_string_sprintfa (str, "0x%08x", token);
343 case MonoInlineString:
348 g_string_sprintfa (str, "%d", read16 (ip));
351 case MonoShortInlineVar:
352 g_string_sprintfa (str, "%d", (*ip));
355 case MonoInlineBrTarget:
358 if (dh->label_target)
359 g_string_sprintfa (str, dh->label_target, ip + sval - header->code);
361 g_string_sprintfa (str, "%d", sval);
363 case MonoShortInlineBrTarget:
364 sval = *(const signed char*)ip;
366 if (dh->label_target)
367 g_string_sprintfa (str, dh->label_target, ip + sval - header->code);
369 g_string_sprintfa (str, "%d", sval);
371 case MonoInlineSwitch: {
372 const unsigned char *end;
376 g_string_append_c (str, '(');
377 for (i = 0; i < sval; ++i) {
379 g_string_append (str, ", ");
381 if (dh->label_target)
382 g_string_sprintfa (str, dh->label_target, end + label - header->code);
384 g_string_sprintfa (str, "%d", label);
387 g_string_append_c (str, ')');
393 g_string_sprintfa (str, "%g", r);
397 case MonoShortInlineR: {
400 g_string_sprintfa (str, "%g", r);
405 g_string_sprintfa (str, "%d", (gint32)read32 (ip));
408 case MonoShortInlineI:
409 g_string_sprintfa (str, "%d", *(const signed char*)ip);
416 g_assert_not_reached ();
419 g_string_append (str, dh->newline);
427 "IL_%04x: ", /* label_format */
428 "IL_%04x", /* label_target */
435 mono_disasm_code_one (MonoDisHelper *dh, MonoMethod *method, const guchar *ip, const guchar **endp)
438 GString *res = g_string_new ("");
442 ip = dis_one (res, dh, method, ip);
447 g_string_free (res, FALSE);
452 mono_disasm_code (MonoDisHelper *dh, MonoMethod *method, const guchar *ip, const guchar* end)
455 GString *res = g_string_new ("");
460 ip = dis_one (res, dh, method, ip);
464 g_string_free (res, FALSE);
469 wrapper_type_to_str (guint32 wrapper_type)
471 g_assert (wrapper_type < sizeof (wrapper_type_names) / sizeof (char*));
473 return wrapper_type_names [wrapper_type];
477 mono_method_full_name (MonoMethod *method, gboolean signature)
483 char *tmpsig = mono_signature_get_desc (method->signature, TRUE);
485 if (method->wrapper_type != MONO_WRAPPER_NONE)
486 sprintf (wrapper, "(wrapper %s) ", wrapper_type_to_str (method->wrapper_type));
488 strcpy (wrapper, "");
489 res = g_strdup_printf ("%s%s.%s:%s (%s)", wrapper, method->klass->name_space,
490 method->klass->name, method->name, tmpsig);
494 res = g_strdup_printf ("%02d %s.%s:%s", method->wrapper_type, method->klass->name_space,
495 method->klass->name, method->name);