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;
164 mono_method_desc_free (MonoMethodDesc *desc)
167 g_free (desc->namespace);
168 else if (desc->klass)
169 g_free (desc->klass);
174 * namespace and class are supposed to match already if this function is used.
177 mono_method_desc_match (MonoMethodDesc *desc, MonoMethod *method)
180 if (strcmp (desc->name, method->name))
184 if (desc->num_args != method->signature->param_count)
186 sig = mono_signature_get_desc (method->signature, desc->include_namespace);
187 if (strcmp (sig, desc->args)) {
196 mono_method_desc_full_match (MonoMethodDesc *desc, MonoMethod *method)
198 if (strcmp (desc->klass, method->klass->name))
200 if (desc->namespace && strcmp (desc->namespace, method->klass->name_space))
202 return mono_method_desc_match (desc, method);
206 mono_method_desc_search_in_class (MonoMethodDesc *desc, MonoClass *klass)
210 mono_class_init (klass);
211 for (i = 0; i < klass->method.count; ++i) {
212 if (mono_method_desc_match (desc, klass->methods [i]))
213 return klass->methods [i];
219 mono_method_desc_search_in_image (MonoMethodDesc *desc, MonoImage *image)
223 MonoTableInfo *methods;
227 if (desc->namespace && desc->klass) {
228 klass = mono_class_from_name (image, desc->namespace, desc->klass);
231 return mono_method_desc_search_in_class (desc, klass);
234 tdef = &image->tables [MONO_TABLE_TYPEDEF];
235 methods = &image->tables [MONO_TABLE_METHOD];
236 for (i = 0; i < methods->rows; ++i) {
237 guint32 token = mono_metadata_decode_row_col (methods, i, MONO_METHOD_NAME);
238 const char *n = mono_metadata_string_heap (image, token);
240 if (strcmp (n, desc->name))
242 method = mono_get_method (image, MONO_TOKEN_METHOD_DEF | (i + 1), NULL);
243 if (mono_method_desc_full_match (desc, method))
249 static const unsigned char*
250 dis_one (GString *str, MonoDisHelper *dh, MonoMethod *method, const unsigned char *ip)
252 MonoMethodHeader *header = ((MonoMethodNormal*)method)->header;
253 const MonoOpcode *opcode;
254 guint32 i, label, token;
258 label = ip - header->code;
260 tmp = dh->indenter (dh, method, label);
261 g_string_append (str, tmp);
264 if (dh->label_format)
265 g_string_sprintfa (str, dh->label_format, label);
267 i = mono_opcode_value (&ip);
269 opcode = &mono_opcodes [i];
270 g_string_sprintfa (str, "%-10s", mono_opcode_names [i]);
272 switch (opcode->argument) {
276 case MonoInlineField:
277 case MonoInlineMethod:
282 tmp = dh->tokener (dh, method, token);
283 g_string_append (str, tmp);
286 g_string_sprintfa (str, "0x%08x", token);
290 case MonoInlineString:
295 g_string_sprintfa (str, "%d", read16 (ip));
298 case MonoShortInlineVar:
299 g_string_sprintfa (str, "%d", (*ip));
302 case MonoInlineBrTarget:
305 if (dh->label_target)
306 g_string_sprintfa (str, dh->label_target, ip + sval - header->code);
308 g_string_sprintfa (str, "%d", sval);
310 case MonoShortInlineBrTarget:
311 sval = *(const signed char*)ip;
313 if (dh->label_target)
314 g_string_sprintfa (str, dh->label_target, ip + sval - header->code);
316 g_string_sprintfa (str, "%d", sval);
318 case MonoInlineSwitch: {
319 const unsigned char *end;
323 g_string_append_c (str, '(');
324 for (i = 0; i < sval; ++i) {
326 g_string_append (str, ", ");
328 if (dh->label_target)
329 g_string_sprintfa (str, dh->label_target, end + label - header->code);
331 g_string_sprintfa (str, "%d", label);
334 g_string_append_c (str, ')');
340 g_string_sprintfa (str, "%g", r);
344 case MonoShortInlineR: {
347 g_string_sprintfa (str, "%g", r);
352 g_string_sprintfa (str, "%d", (gint32)read32 (ip));
355 case MonoShortInlineI:
356 g_string_sprintfa (str, "%d", *(const signed char*)ip);
363 g_assert_not_reached ();
366 g_string_append (str, dh->newline);
374 "IL_%04x: ", /* label_format */
375 "IL_%04x", /* label_target */
382 mono_disasm_code_one (MonoDisHelper *dh, MonoMethod *method, const guchar *ip)
385 GString *res = g_string_new ("");
389 dis_one (res, dh, method, ip);
392 g_string_free (res, FALSE);
397 mono_disasm_code (MonoDisHelper *dh, MonoMethod *method, const guchar *ip, const guchar* end)
400 GString *res = g_string_new ("");
405 ip = dis_one (res, dh, method, ip);
409 g_string_free (res, FALSE);
414 mono_method_full_name (MonoMethod *method, gboolean signature)
419 char *tmpsig = mono_signature_get_desc (method->signature, TRUE);
421 res = g_strdup_printf ("%02d %s.%s:%s (%s)", method->wrapper_type, method->klass->name_space,
422 method->klass->name, method->name, tmpsig);
426 res = g_strdup_printf ("%02d %s.%s:%s", method->wrapper_type, method->klass->name_space,
427 method->klass->name, method->name);