2 * dis-cil.c: Disassembles CIL byte codes
5 * Miguel de Icaza (miguel@ximian.com)
7 * (C) 2001 Ximian, Inc.
20 #include "mono/metadata/opcodes.h"
21 #include "mono/utils/mono-compiler.h"
33 klass = fpclass (num);
43 #error "Don't know how to implement isinf for this platform."
48 #define CODE_INDENT g_assert (indent_level < 512); \
49 indent[indent_level*2] = ' '; \
50 indent[indent_level*2+1] = ' '; \
52 indent[indent_level*2] = 0;
53 #define CODE_UNINDENT g_assert (indent_level); \
55 indent[indent_level*2] = 0;
58 disassemble_cil (MonoImage *m, MonoMethodHeader *mh, MonoGenericContext *context)
60 const unsigned char *start = mh->code;
61 int size = mh->code_size;
62 const unsigned char *end = start + size;
63 const unsigned char *ptr = start;
64 const MonoOpcode *entry;
66 int i, j, indent_level = 0;
67 gboolean in_fault = 0;
68 const char *clause_names[] = {"catch", "filter", "finally", "", "fault"};
69 gboolean *trys = NULL;
73 for (i = 0; i < mh->num_clauses; ++i) {
74 #define clause mh->clauses [i]
75 g_print ("/* out clause %d: from %d len=%d, handler at %d, %d */\n",
76 clause.flags, clause.try_offset, clause.try_len, clause.handler_offset, clause.handler_len);
81 if (mh->num_clauses) {
82 trys = g_malloc0 (sizeof (gboolean) * mh->num_clauses);
84 for (i=1; i < mh->num_clauses; ++i) {
85 #define jcl mh->clauses [j]
86 #define cl mh->clauses [i]
88 for (j = 0; j < i; j++) {
89 if (cl.try_offset == jcl.try_offset && cl.try_len == jcl.try_len) {
100 for (i = mh->num_clauses - 1; i >= 0 ; --i) {
101 if (ptr == start + mh->clauses[i].try_offset && trys [i]) {
102 fprintf (output, "\t%s.try { // %d\n", indent, i);
106 if (ptr == start + mh->clauses[i].handler_offset) {
107 if (mh->clauses[i].flags == MONO_EXCEPTION_CLAUSE_FILTER) {
109 fprintf (output, "\t%s} { // %d\n", indent, i);
111 char * klass = mh->clauses[i].flags ? g_strdup ("") :
112 dis_stringify_object_with_class (m, mh->clauses[i].data.catch_class,
114 fprintf (output, "\t%s%s %s { // %d\n", indent,
115 clause_names [mh->clauses[i].flags], klass, i);
119 if (mh->clauses[i].flags == MONO_EXCEPTION_CLAUSE_FAULT)
122 if (mh->clauses[i].flags == MONO_EXCEPTION_CLAUSE_FILTER && ptr == start + mh->clauses[i].data.filter_offset) {
123 fprintf (output, "\t%s%s {\n", indent, clause_names[1]);
127 fprintf (output, "\t%sIL_%04x: ", indent, (int) (ptr - start));
133 entry = &mono_opcodes [i];
135 if (in_fault && entry->opval == 0xDC)
136 fprintf (output, " %s", "endfault");
138 fprintf (output, " %s ", mono_opcode_name (i));
140 switch (entry->argument){
141 case MonoInlineBrTarget: {
142 gint target = read32 (ptr);
143 fprintf (output, "IL_%04x\n", ((int) (ptr - start)) + 4 + target);
148 case MonoInlineField: {
149 guint32 token = read32 (ptr);
152 s = get_field (m, token, context);
153 fprintf (output, "%s", s);
160 int value = read32 (ptr);
162 fprintf (output, "%d", value);
168 gint64 top = read64 (ptr);
170 fprintf (output, "0x%llx", (long long) top);
175 case MonoInlineMethod: {
176 guint32 token = read32 (ptr);
179 s = get_method (m, token, context);
180 fprintf (output, "%s", s);
195 fprintf (output, "(00 00 00 00 00 00 f0 ff)"); /* negative infinity */
197 fprintf (output, "(00 00 00 00 00 00 f0 7f)"); /* positive infinity */
199 fprintf (output, "(00 00 00 00 00 00 f8 ff)"); /* NaN */
201 char *str = stringify_double (r);
202 fprintf (output, str);
209 case MonoInlineSig: {
210 guint32 token = read32 (ptr);
211 fprintf (output, "signature-0x%08x", token);
216 case MonoInlineString: {
217 guint32 token = read32 (ptr);
218 const char *us_ptr = mono_metadata_user_string (m, token & 0xffffff);
219 int len = mono_metadata_decode_blob_size (us_ptr, (const char**)&us_ptr);
221 char *s = get_encoded_user_string_or_bytearray (us_ptr, len);
224 * See section 23.1.4 on the encoding of the #US heap
226 fprintf (output, "%s", s);
232 case MonoInlineSwitch: {
233 guint32 count = read32 (ptr);
234 const unsigned char *endswitch;
238 endswitch = ptr + sizeof (guint32) * count;
239 fprintf (output, count > 0 ? "(\n" : "( )");
241 for (n = 0; n < count; n++){
242 fprintf (output, "\t%sIL_%04x%s", indent,
243 (int)(endswitch-start+read32 (ptr)),
244 n == count - 1 ? ")" : ",\n");
251 case MonoInlineTok: {
252 guint32 token = read32 (ptr);
255 s = get_token (m, token, context);
256 fprintf (output, "%s", s);
263 case MonoInlineType: {
264 guint32 token = read32 (ptr);
265 char *s = get_token_type (m, token, context);
266 fprintf (output, "%s", s);
272 case MonoInlineVar: {
273 guint16 var_idx = read16 (ptr);
275 fprintf (output, "%d\n", var_idx);
280 case MonoShortInlineBrTarget: {
281 signed char x = *ptr;
283 fprintf (output, "IL_%04x\n", (int)(ptr - start + 1 + x));
288 case MonoShortInlineI: {
291 fprintf (output, "0x%02x", x);
296 case MonoShortInlineR: {
304 fprintf (output, "(00 00 80 ff)"); /* negative infinity */
306 fprintf (output, "(00 00 80 7f)"); /* positive infinity */
308 fprintf (output, "(00 00 c0 ff)"); /* NaN */
310 char *str = stringify_double ((double) f);
311 fprintf (output, str);
318 case MonoShortInlineVar: {
319 unsigned char x = *ptr;
321 fprintf (output, "%d", (int) x);
329 fprintf (output, "\n");
330 for (i = 0; i < mh->num_clauses; ++i) {
331 if (ptr == start + mh->clauses[i].try_offset + mh->clauses[i].try_len && trys [i]) {
333 fprintf (output, "\t%s} // end .try %d\n", indent, i);
335 if (ptr == start + mh->clauses[i].handler_offset + mh->clauses[i].handler_len) {
337 fprintf (output, "\t%s} // end handler %d\n", indent, i);
338 if (mh->clauses[i].flags == MONO_EXCEPTION_CLAUSE_FAULT)