3 #include "mono/metadata/tokentype.h"
4 #include "mono/metadata/opcodes.h"
5 #include "mono/metadata/class-internals.h"
6 #include "mono/metadata/mono-endian.h"
7 #include "mono/metadata/debug-helpers.h"
9 struct MonoMethodDesc
{
15 gboolean include_namespace
;
18 static const char *wrapper_type_names
[] = {
21 "delegate-begin-invoke",
22 "delegate-end-invoke",
27 "remoting-invoke-with-check",
40 append_class_name (GString
*res
, MonoClass
*class, gboolean include_namespace
)
43 g_string_append (res
, "Unknown");
46 if (class->nested_in
) {
47 append_class_name (res
, class->nested_in
, include_namespace
);
48 g_string_append_c (res
, '/');
50 if (include_namespace
&& *(class->name_space
))
51 g_string_sprintfa (res
, "%s.", class->name_space
);
52 g_string_sprintfa (res
, "%s", class->name
);
56 mono_type_get_desc (GString
*res
, MonoType
*type
, gboolean include_namespace
) {
59 g_string_append (res
, "void"); break;
61 g_string_append (res
, "char"); break;
62 case MONO_TYPE_BOOLEAN
:
63 g_string_append (res
, "bool"); break;
65 g_string_append (res
, "byte"); break;
67 g_string_append (res
, "sbyte"); break;
69 g_string_append (res
, "uint16"); break;
71 g_string_append (res
, "int16"); break;
73 g_string_append (res
, "uint"); break;
75 g_string_append (res
, "int"); break;
77 g_string_append (res
, "ulong"); break;
79 g_string_append (res
, "long"); break;
80 case MONO_TYPE_FNPTR
: /* who cares for the exact signature? */
81 g_string_append (res
, "*()"); break;
83 g_string_append (res
, "uintptr"); break;
85 g_string_append (res
, "intptr"); break;
87 g_string_append (res
, "single"); break;
89 g_string_append (res
, "double"); break;
90 case MONO_TYPE_STRING
:
91 g_string_append (res
, "string"); break;
92 case MONO_TYPE_OBJECT
:
93 g_string_append (res
, "object"); break;
95 mono_type_get_desc (res
, type
->data
.type
, include_namespace
);
96 g_string_append_c (res
, '*');
99 append_class_name (res
, type
->data
.array
->eklass
, include_namespace
);
100 g_string_sprintfa (res
, "[%d]", type
->data
.array
->rank
);
102 case MONO_TYPE_SZARRAY
:
103 mono_type_get_desc (res
, &type
->data
.klass
->byval_arg
, include_namespace
);
104 g_string_append (res
, "[]");
106 case MONO_TYPE_CLASS
:
107 case MONO_TYPE_VALUETYPE
:
108 append_class_name (res
, type
->data
.klass
, include_namespace
);
110 case MONO_TYPE_GENERICINST
:
111 mono_type_get_desc (res
, type
->data
.generic_inst
->generic_type
, include_namespace
);
117 g_string_append_c (res
, '&');
121 mono_type_full_name (MonoType
*type
)
126 str
= g_string_new ("");
127 mono_type_get_desc (str
, type
, TRUE
);
129 res
= g_strdup (str
->str
);
130 g_string_free (str
, TRUE
);
135 mono_signature_get_desc (MonoMethodSignature
*sig
, gboolean include_namespace
)
139 GString
*res
= g_string_new ("");
141 for (i
= 0; i
< sig
->param_count
; ++i
) {
143 g_string_append_c (res
, ',');
144 mono_type_get_desc (res
, sig
->params
[i
], include_namespace
);
147 g_string_free (res
, FALSE
);
152 * mono_method_desc_new:
154 * Creates a method description for `name', which conforms to the following
157 * [namespace.]classname:methodname[(args...)]
159 * in all the loaded assemblies.
161 * Returns a parsed representation of the method description.
164 mono_method_desc_new (const char *name
, gboolean include_namespace
)
166 MonoMethodDesc
*result
;
167 char *class_name
, *class_nspace
, *method_name
, *use_args
, *end
;
170 class_nspace
= g_strdup (name
);
171 use_args
= strchr (class_nspace
, '(');
174 end
= strchr (use_args
, ')');
176 g_free (class_nspace
);
181 method_name
= strrchr (class_nspace
, ':');
183 g_free (class_nspace
);
187 /* allow two :: to separate the method name */
188 if (*method_name
== ':')
190 class_name
= strrchr (class_nspace
, '.');
195 class_name
= class_nspace
;
198 result
= g_new0 (MonoMethodDesc
, 1);
199 result
->include_namespace
= include_namespace
;
200 result
->name
= method_name
;
201 result
->klass
= class_name
;
202 result
->namespace = use_namespace
? class_nspace
: NULL
;
203 result
->args
= use_args
? use_args
: NULL
;
207 result
->num_args
= 1;
219 mono_method_desc_from_method (MonoMethod
*method
)
221 MonoMethodDesc
*result
;
223 result
= g_new0 (MonoMethodDesc
, 1);
224 result
->include_namespace
= TRUE
;
225 result
->name
= g_strdup (method
->name
);
226 result
->klass
= g_strdup (method
->klass
->name
);
227 result
->namespace = g_strdup (method
->klass
->name_space
);
233 * mono_method_desc_free:
235 * Releases the MonoMethodDesc object `desc'.
238 mono_method_desc_free (MonoMethodDesc
*desc
)
241 g_free (desc
->namespace);
242 else if (desc
->klass
)
243 g_free (desc
->klass
);
248 * namespace and class are supposed to match already if this function is used.
251 mono_method_desc_match (MonoMethodDesc
*desc
, MonoMethod
*method
)
254 if (strcmp (desc
->name
, method
->name
))
258 if (desc
->num_args
!= method
->signature
->param_count
)
260 sig
= mono_signature_get_desc (method
->signature
, desc
->include_namespace
);
261 if (strcmp (sig
, desc
->args
)) {
270 mono_method_desc_full_match (MonoMethodDesc
*desc
, MonoMethod
*method
)
272 if (strcmp (desc
->klass
, method
->klass
->name
))
274 if (desc
->namespace && strcmp (desc
->namespace, method
->klass
->name_space
))
276 return mono_method_desc_match (desc
, method
);
280 mono_method_desc_search_in_class (MonoMethodDesc
*desc
, MonoClass
*klass
)
284 mono_class_init (klass
);
285 for (i
= 0; i
< klass
->method
.count
; ++i
) {
286 if (mono_method_desc_match (desc
, klass
->methods
[i
]))
287 return klass
->methods
[i
];
293 mono_method_desc_search_in_image (MonoMethodDesc
*desc
, MonoImage
*image
)
296 const MonoTableInfo
*tdef
;
297 const MonoTableInfo
*methods
;
301 if (desc
->namespace && desc
->klass
) {
302 klass
= mono_class_from_name (image
, desc
->namespace, desc
->klass
);
305 return mono_method_desc_search_in_class (desc
, klass
);
308 tdef
= mono_image_get_table_info (image
, MONO_TABLE_TYPEDEF
);
309 methods
= mono_image_get_table_info (image
, MONO_TABLE_METHOD
);
310 for (i
= 0; i
< mono_table_info_get_rows (methods
); ++i
) {
311 guint32 token
= mono_metadata_decode_row_col (methods
, i
, MONO_METHOD_NAME
);
312 const char *n
= mono_metadata_string_heap (image
, token
);
314 if (strcmp (n
, desc
->name
))
316 method
= mono_get_method (image
, MONO_TOKEN_METHOD_DEF
| (i
+ 1), NULL
);
317 if (mono_method_desc_full_match (desc
, method
))
323 static const unsigned char*
324 dis_one (GString
*str
, MonoDisHelper
*dh
, MonoMethod
*method
, const unsigned char *ip
, const unsigned char *end
)
326 MonoMethodHeader
*header
= ((MonoMethodNormal
*)method
)->header
;
327 const MonoOpcode
*opcode
;
328 guint32 i
, label
, token
;
332 label
= ip
- header
->code
;
334 tmp
= dh
->indenter (dh
, method
, label
);
335 g_string_append (str
, tmp
);
338 if (dh
->label_format
)
339 g_string_sprintfa (str
, dh
->label_format
, label
);
341 i
= mono_opcode_value (&ip
, end
);
343 opcode
= &mono_opcodes
[i
];
344 g_string_sprintfa (str
, "%-10s", mono_opcode_name (i
));
346 switch (opcode
->argument
) {
350 case MonoInlineField
:
351 case MonoInlineMethod
:
356 tmp
= dh
->tokener (dh
, method
, token
);
357 g_string_append (str
, tmp
);
360 g_string_sprintfa (str
, "0x%08x", token
);
364 case MonoInlineString
:
369 g_string_sprintfa (str
, "%d", read16 (ip
));
372 case MonoShortInlineVar
:
373 g_string_sprintfa (str
, "%d", (*ip
));
376 case MonoInlineBrTarget
:
379 if (dh
->label_target
)
380 g_string_sprintfa (str
, dh
->label_target
, ip
+ sval
- header
->code
);
382 g_string_sprintfa (str
, "%d", sval
);
384 case MonoShortInlineBrTarget
:
385 sval
= *(const signed char*)ip
;
387 if (dh
->label_target
)
388 g_string_sprintfa (str
, dh
->label_target
, ip
+ sval
- header
->code
);
390 g_string_sprintfa (str
, "%d", sval
);
392 case MonoInlineSwitch
: {
393 const unsigned char *end
;
397 g_string_append_c (str
, '(');
398 for (i
= 0; i
< sval
; ++i
) {
400 g_string_append (str
, ", ");
402 if (dh
->label_target
)
403 g_string_sprintfa (str
, dh
->label_target
, end
+ label
- header
->code
);
405 g_string_sprintfa (str
, "%d", label
);
408 g_string_append_c (str
, ')');
414 g_string_sprintfa (str
, "%g", r
);
418 case MonoShortInlineR
: {
421 g_string_sprintfa (str
, "%g", r
);
426 g_string_sprintfa (str
, "%d", (gint32
)read32 (ip
));
429 case MonoShortInlineI
:
430 g_string_sprintfa (str
, "%d", *(const signed char*)ip
);
437 g_assert_not_reached ();
440 g_string_append (str
, dh
->newline
);
448 "IL_%04x: ", /* label_format */
449 "IL_%04x", /* label_target */
456 mono_disasm_code_one (MonoDisHelper
*dh
, MonoMethod
*method
, const guchar
*ip
, const guchar
**endp
)
459 GString
*res
= g_string_new ("");
463 /* set ip + 2 as the end: this is just a debugging method */
464 ip
= dis_one (res
, dh
, method
, ip
, ip
+ 2);
469 g_string_free (res
, FALSE
);
474 mono_disasm_code (MonoDisHelper
*dh
, MonoMethod
*method
, const guchar
*ip
, const guchar
* end
)
477 GString
*res
= g_string_new ("");
482 ip
= dis_one (res
, dh
, method
, ip
, end
);
486 g_string_free (res
, FALSE
);
491 wrapper_type_to_str (guint32 wrapper_type
)
493 g_assert (wrapper_type
< sizeof (wrapper_type_names
) / sizeof (char*));
495 return wrapper_type_names
[wrapper_type
];
499 mono_method_full_name (MonoMethod
*method
, gboolean signature
)
503 const char *nspace
= method
->klass
->name_space
;
506 char *tmpsig
= mono_signature_get_desc (method
->signature
, TRUE
);
508 if (method
->wrapper_type
!= MONO_WRAPPER_NONE
)
509 sprintf (wrapper
, "(wrapper %s) ", wrapper_type_to_str (method
->wrapper_type
));
511 strcpy (wrapper
, "");
512 res
= g_strdup_printf ("%s%s%s%s:%s (%s)", wrapper
,
513 nspace
, *nspace
? "." : "",
514 method
->klass
->name
, method
->name
, tmpsig
);
518 res
= g_strdup_printf ("%02d %s%s%s:%s", method
->wrapper_type
,
519 nspace
, *nspace
? "." : "",
520 method
->klass
->name
, method
->name
);
527 mono_find_method_by_name (MonoClass
*klass
, const char *name
, int param_count
)
529 MonoMethod
*res
= NULL
;
532 mono_class_init (klass
);
534 for (i
= 0; i
< klass
->method
.count
; ++i
) {
535 if (klass
->methods
[i
]->name
[0] == name
[0] &&
536 !strcmp (name
, klass
->methods
[i
]->name
) &&
537 klass
->methods
[i
]->signature
->param_count
== param_count
) {
538 res
= klass
->methods
[i
];