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 class_name = strrchr (class_nspace, '.');
138 class_name = class_nspace;
141 result = g_new0 (MonoMethodDesc, 1);
142 result->include_namespace = include_namespace;
143 result->name = method_name;
144 result->klass = class_name;
145 result->namespace = use_namespace? class_nspace: NULL;
146 result->args = use_args? use_args: NULL;
150 result->num_args = 1;
161 mono_method_desc_free (MonoMethodDesc *desc)
164 g_free (desc->namespace);
165 else if (desc->klass)
166 g_free (desc->klass);
171 * namespace and class are supposed to match already if this function is used.
174 mono_method_desc_match (MonoMethodDesc *desc, MonoMethod *method)
177 if (strcmp (desc->name, method->name))
181 if (desc->num_args != method->signature->param_count)
183 sig = mono_signature_get_desc (method->signature, desc->include_namespace);
184 if (strcmp (sig, desc->args)) {
193 mono_method_desc_full_match (MonoMethodDesc *desc, MonoMethod *method)
195 if (strcmp (desc->klass, method->klass->name))
197 if (desc->namespace && strcmp (desc->namespace, method->klass->name_space))
199 return mono_method_desc_match (desc, method);
203 mono_method_desc_search_in_class (MonoMethodDesc *desc, MonoClass *klass)
207 mono_class_init (klass);
208 for (i = 0; i < klass->method.count; ++i) {
209 if (mono_method_desc_match (desc, klass->methods [i]))
210 return klass->methods [i];
216 mono_method_desc_search_in_image (MonoMethodDesc *desc, MonoImage *image)
220 MonoTableInfo *methods;
224 if (desc->namespace && desc->klass) {
225 klass = mono_class_from_name (image, desc->namespace, desc->klass);
228 return mono_method_desc_search_in_class (desc, klass);
231 tdef = &image->tables [MONO_TABLE_TYPEDEF];
232 methods = &image->tables [MONO_TABLE_METHOD];
233 for (i = 0; i < methods->rows; ++i) {
234 guint32 index = mono_metadata_decode_row_col (methods, i, MONO_METHOD_NAME);
235 const char *n = mono_metadata_string_heap (image, index);
237 if (strcmp (n, desc->name))
239 method = mono_get_method (image, MONO_TOKEN_METHOD_DEF | (i + 1), NULL);
240 if (mono_method_desc_full_match (desc, method))
246 static const unsigned char*
247 dis_one (GString *str, MonoDisHelper *dh, MonoMethod *method, const unsigned char *ip)
249 MonoMethodHeader *header = ((MonoMethodNormal*)method)->header;
250 const MonoOpcode *opcode;
251 guint32 i, label, token;
255 label = ip - header->code;
257 tmp = dh->indenter (dh, method, label);
258 g_string_append (str, tmp);
261 if (dh->label_format)
262 g_string_sprintfa (str, dh->label_format, label);
270 opcode = &mono_opcodes [i];
271 g_string_sprintfa (str, "%-10s", mono_opcode_names [i]);
273 switch (opcode->argument) {
277 case MonoInlineField:
278 case MonoInlineMethod:
283 tmp = dh->tokener (dh, method, token);
284 g_string_append (str, tmp);
287 g_string_sprintfa (str, "0x%08x", token);
291 case MonoInlineString:
296 g_string_sprintfa (str, "%d", read16 (ip));
299 case MonoShortInlineVar:
300 g_string_sprintfa (str, "%d", (*ip));
303 case MonoInlineBrTarget:
306 if (dh->label_target)
307 g_string_sprintfa (str, dh->label_target, ip + sval - header->code);
309 g_string_sprintfa (str, "%d", sval);
311 case MonoShortInlineBrTarget:
312 sval = *(signed char*)ip;
314 if (dh->label_target)
315 g_string_sprintfa (str, dh->label_target, ip + sval - header->code);
317 g_string_sprintfa (str, "%d", sval);
319 case MonoInlineSwitch: {
320 const unsigned char *end;
324 g_string_append_c (str, '(');
325 for (i = 0; i < sval; ++i) {
327 g_string_append (str, ", ");
329 if (dh->label_target)
330 g_string_sprintfa (str, dh->label_target, end + label - header->code);
332 g_string_sprintfa (str, "%d", label);
335 g_string_append_c (str, ')');
341 g_string_sprintfa (str, "%g", r);
345 case MonoShortInlineR: {
348 g_string_sprintfa (str, "%g", r);
353 g_string_sprintfa (str, "%d", (gint32)read32 (ip));
356 case MonoShortInlineI:
357 g_string_sprintfa (str, "%d", *(signed char*)ip);
364 g_assert_not_reached ();
367 g_string_append (str, dh->newline);
375 "IL_%04x: ", /* label_format */
376 "IL_%04x", /* label_target */
383 mono_disasm_code_one (MonoDisHelper *dh, MonoMethod *method, const guchar *ip)
386 GString *res = g_string_new ("");
390 dis_one (res, dh, method, ip);
393 g_string_free (res, FALSE);
398 mono_disasm_code (MonoDisHelper *dh, MonoMethod *method, const guchar *ip, const guchar* end)
401 GString *res = g_string_new ("");
406 ip = dis_one (res, dh, method, ip);
410 g_string_free (res, FALSE);