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, "int"); break;
37 g_string_append (res, "uint"); 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, "intptr"); break;
47 g_string_append (res, "uintptr"); 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 index = mono_metadata_decode_row_col (methods, i, MONO_METHOD_NAME);
238 const char *n = mono_metadata_string_heap (image, index);
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);
273 opcode = &mono_opcodes [i];
274 g_string_sprintfa (str, "%-10s", mono_opcode_names [i]);
276 switch (opcode->argument) {
280 case MonoInlineField:
281 case MonoInlineMethod:
286 tmp = dh->tokener (dh, method, token);
287 g_string_append (str, tmp);
290 g_string_sprintfa (str, "0x%08x", token);
294 case MonoInlineString:
299 g_string_sprintfa (str, "%d", read16 (ip));
302 case MonoShortInlineVar:
303 g_string_sprintfa (str, "%d", (*ip));
306 case MonoInlineBrTarget:
309 if (dh->label_target)
310 g_string_sprintfa (str, dh->label_target, ip + sval - header->code);
312 g_string_sprintfa (str, "%d", sval);
314 case MonoShortInlineBrTarget:
315 sval = *(signed char*)ip;
317 if (dh->label_target)
318 g_string_sprintfa (str, dh->label_target, ip + sval - header->code);
320 g_string_sprintfa (str, "%d", sval);
322 case MonoInlineSwitch: {
323 const unsigned char *end;
327 g_string_append_c (str, '(');
328 for (i = 0; i < sval; ++i) {
330 g_string_append (str, ", ");
332 if (dh->label_target)
333 g_string_sprintfa (str, dh->label_target, end + label - header->code);
335 g_string_sprintfa (str, "%d", label);
338 g_string_append_c (str, ')');
344 g_string_sprintfa (str, "%g", r);
348 case MonoShortInlineR: {
351 g_string_sprintfa (str, "%g", r);
356 g_string_sprintfa (str, "%d", (gint32)read32 (ip));
359 case MonoShortInlineI:
360 g_string_sprintfa (str, "%d", *(signed char*)ip);
367 g_assert_not_reached ();
370 g_string_append (str, dh->newline);
378 "IL_%04x: ", /* label_format */
379 "IL_%04x", /* label_target */
386 mono_disasm_code_one (MonoDisHelper *dh, MonoMethod *method, const guchar *ip)
389 GString *res = g_string_new ("");
393 dis_one (res, dh, method, ip);
396 g_string_free (res, FALSE);
401 mono_disasm_code (MonoDisHelper *dh, MonoMethod *method, const guchar *ip, const guchar* end)
404 GString *res = g_string_new ("");
409 ip = dis_one (res, dh, method, ip);
413 g_string_free (res, FALSE);