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;
18 mono_type_get_desc (GString *res, MonoType *type, gboolean include_namespace) {
21 g_string_append (res, "void"); break;
23 g_string_append (res, "char"); break;
24 case MONO_TYPE_BOOLEAN:
25 g_string_append (res, "bool"); break;
27 g_string_append (res, "byte"); break;
29 g_string_append (res, "sbyte"); break;
31 g_string_append (res, "uint16"); break;
33 g_string_append (res, "int16"); break;
35 g_string_append (res, "uint"); break;
37 g_string_append (res, "int"); break;
39 g_string_append (res, "ulong"); break;
41 g_string_append (res, "long"); break;
42 case MONO_TYPE_FNPTR: /* who cares for the exact signature? */
43 g_string_append (res, "*()"); break;
45 g_string_append (res, "uintptr"); break;
47 g_string_append (res, "intptr"); break;
49 g_string_append (res, "single"); break;
51 g_string_append (res, "double"); break;
52 case MONO_TYPE_STRING:
53 g_string_append (res, "string"); break;
54 case MONO_TYPE_OBJECT:
55 g_string_append (res, "object"); break;
57 mono_type_get_desc (res, type->data.type, include_namespace);
58 g_string_append_c (res, '*');
61 mono_type_get_desc (res, type->data.array->type, include_namespace);
62 g_string_sprintfa (res, "[%d]", type->data.array->rank);
64 case MONO_TYPE_SZARRAY:
65 mono_type_get_desc (res, type->data.type, include_namespace);
66 g_string_append (res, "[]");
69 case MONO_TYPE_VALUETYPE: {
70 MonoClass *class = type->data.klass;
72 g_string_append (res, "Unknown");
75 if (include_namespace && *(class->name_space))
76 g_string_sprintfa (res, "%s.", class->name_space);
77 g_string_sprintfa (res, "%s", class->name);
84 g_string_append_c (res, '&');
88 mono_signature_get_desc (MonoMethodSignature *sig, gboolean include_namespace)
92 GString *res = g_string_new ("");
94 for (i = 0; i < sig->param_count; ++i) {
96 g_string_append_c (res, ',');
97 mono_type_get_desc (res, sig->params [i], include_namespace);
100 g_string_free (res, FALSE);
105 * The allowed format of a method description string is:
106 * [namespace.]classname:methodname[(args...)]
107 * TODO: describe instance methods.
110 mono_method_desc_new (const char *name, gboolean include_namespace)
112 MonoMethodDesc *result;
113 char *class_name, *class_nspace, *method_name, *use_args, *end;
116 class_nspace = g_strdup (name);
117 use_args = strchr (class_nspace, '(');
120 end = strchr (use_args, ')');
122 g_free (class_nspace);
127 method_name = strrchr (class_nspace, ':');
129 g_free (class_nspace);
133 /* allow two :: to separate the method name */
134 if (*method_name == ':')
136 class_name = strrchr (class_nspace, '.');
141 class_name = class_nspace;
144 result = g_new0 (MonoMethodDesc, 1);
145 result->include_namespace = include_namespace;
146 result->name = method_name;
147 result->klass = class_name;
148 result->namespace = use_namespace? class_nspace: NULL;
149 result->args = use_args? use_args: NULL;
153 result->num_args = 1;
165 mono_method_desc_from_method (MonoMethod *method)
167 MonoMethodDesc *result;
169 result = g_new0 (MonoMethodDesc, 1);
170 result->include_namespace = TRUE;
171 result->name = g_strdup (method->name);
172 result->klass = g_strdup (method->klass->name);
173 result->namespace = g_strdup (method->klass->name_space);
179 mono_method_desc_free (MonoMethodDesc *desc)
182 g_free (desc->namespace);
183 else if (desc->klass)
184 g_free (desc->klass);
189 * namespace and class are supposed to match already if this function is used.
192 mono_method_desc_match (MonoMethodDesc *desc, MonoMethod *method)
195 if (strcmp (desc->name, method->name))
199 if (desc->num_args != method->signature->param_count)
201 sig = mono_signature_get_desc (method->signature, desc->include_namespace);
202 if (strcmp (sig, desc->args)) {
211 mono_method_desc_full_match (MonoMethodDesc *desc, MonoMethod *method)
213 if (strcmp (desc->klass, method->klass->name))
215 if (desc->namespace && strcmp (desc->namespace, method->klass->name_space))
217 return mono_method_desc_match (desc, method);
221 mono_method_desc_search_in_class (MonoMethodDesc *desc, MonoClass *klass)
225 mono_class_init (klass);
226 for (i = 0; i < klass->method.count; ++i) {
227 if (mono_method_desc_match (desc, klass->methods [i]))
228 return klass->methods [i];
234 mono_method_desc_search_in_image (MonoMethodDesc *desc, MonoImage *image)
238 MonoTableInfo *methods;
242 if (desc->namespace && desc->klass) {
243 klass = mono_class_from_name (image, desc->namespace, desc->klass);
246 return mono_method_desc_search_in_class (desc, klass);
249 tdef = &image->tables [MONO_TABLE_TYPEDEF];
250 methods = &image->tables [MONO_TABLE_METHOD];
251 for (i = 0; i < methods->rows; ++i) {
252 guint32 token = mono_metadata_decode_row_col (methods, i, MONO_METHOD_NAME);
253 const char *n = mono_metadata_string_heap (image, token);
255 if (strcmp (n, desc->name))
257 method = mono_get_method (image, MONO_TOKEN_METHOD_DEF | (i + 1), NULL);
258 if (mono_method_desc_full_match (desc, method))
264 static const unsigned char*
265 dis_one (GString *str, MonoDisHelper *dh, MonoMethod *method, const unsigned char *ip)
267 MonoMethodHeader *header = ((MonoMethodNormal*)method)->header;
268 const MonoOpcode *opcode;
269 guint32 i, label, token;
273 label = ip - header->code;
275 tmp = dh->indenter (dh, method, label);
276 g_string_append (str, tmp);
279 if (dh->label_format)
280 g_string_sprintfa (str, dh->label_format, label);
282 i = mono_opcode_value (&ip);
284 opcode = &mono_opcodes [i];
285 g_string_sprintfa (str, "%-10s", mono_opcode_names [i]);
287 switch (opcode->argument) {
291 case MonoInlineField:
292 case MonoInlineMethod:
297 tmp = dh->tokener (dh, method, token);
298 g_string_append (str, tmp);
301 g_string_sprintfa (str, "0x%08x", token);
305 case MonoInlineString:
310 g_string_sprintfa (str, "%d", read16 (ip));
313 case MonoShortInlineVar:
314 g_string_sprintfa (str, "%d", (*ip));
317 case MonoInlineBrTarget:
320 if (dh->label_target)
321 g_string_sprintfa (str, dh->label_target, ip + sval - header->code);
323 g_string_sprintfa (str, "%d", sval);
325 case MonoShortInlineBrTarget:
326 sval = *(const signed char*)ip;
328 if (dh->label_target)
329 g_string_sprintfa (str, dh->label_target, ip + sval - header->code);
331 g_string_sprintfa (str, "%d", sval);
333 case MonoInlineSwitch: {
334 const unsigned char *end;
338 g_string_append_c (str, '(');
339 for (i = 0; i < sval; ++i) {
341 g_string_append (str, ", ");
343 if (dh->label_target)
344 g_string_sprintfa (str, dh->label_target, end + label - header->code);
346 g_string_sprintfa (str, "%d", label);
349 g_string_append_c (str, ')');
355 g_string_sprintfa (str, "%g", r);
359 case MonoShortInlineR: {
362 g_string_sprintfa (str, "%g", r);
367 g_string_sprintfa (str, "%d", (gint32)read32 (ip));
370 case MonoShortInlineI:
371 g_string_sprintfa (str, "%d", *(const signed char*)ip);
378 g_assert_not_reached ();
381 g_string_append (str, dh->newline);
389 "IL_%04x: ", /* label_format */
390 "IL_%04x", /* label_target */
397 mono_disasm_code_one (MonoDisHelper *dh, MonoMethod *method, const guchar *ip, const guchar **endp)
400 GString *res = g_string_new ("");
404 ip = dis_one (res, dh, method, ip);
409 g_string_free (res, FALSE);
414 mono_disasm_code (MonoDisHelper *dh, MonoMethod *method, const guchar *ip, const guchar* end)
417 GString *res = g_string_new ("");
422 ip = dis_one (res, dh, method, ip);
426 g_string_free (res, FALSE);
431 mono_method_full_name (MonoMethod *method, gboolean signature)
436 char *tmpsig = mono_signature_get_desc (method->signature, TRUE);
438 res = g_strdup_printf ("%02d %s.%s:%s (%s)", method->wrapper_type, method->klass->name_space,
439 method->klass->name, method->name, tmpsig);
443 res = g_strdup_printf ("%02d %s.%s:%s", method->wrapper_type, method->klass->name_space,
444 method->klass->name, method->name);