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"
31 klass = fpclass (num);
42 #error "Don't know how to implement isinf for this platform."
46 * Strings on the US heap are encoded using UTF-16. Poor man's
47 * UTF-16 to UTF-8. I know its broken, use libunicode later.
50 get_encoded_user_string (const char *ptr)
55 len = mono_metadata_decode_blob_size (ptr, &ptr);
56 res = g_malloc (len + 1);
59 * I should really use some kind of libunicode here
61 for (i = 0, j = 0; i < len; j++, i += 2)
66 result = g_strescape (res, NULL);
72 #define CODE_INDENT g_assert (indent_level < 512); \
73 indent[indent_level*2] = ' '; \
74 indent[indent_level*2+1] = ' '; \
76 indent[indent_level*2] = 0;
77 #define CODE_UNINDENT g_assert (indent_level); \
79 indent[indent_level*2] = 0;
82 dissasemble_cil (MonoImage *m, MonoMethodHeader *mh, MonoGenericContext *context)
84 const unsigned char *start = mh->code;
85 int size = mh->code_size;
86 const unsigned char *end = start + size;
87 const unsigned char *ptr = start;
88 const MonoOpcode *entry;
90 int i, indent_level = 0;
91 gboolean in_fault = 0;
92 const char *clause_names[] = {"catch", "filter", "finally", "", "fault"};
93 gboolean *trys = NULL;
97 for (i = 0; i < mh->num_clauses; ++i) {
98 #define clause mh->clauses [i]
99 g_print ("/* out clause %d: from %d len=%d, handler at %d, %d */\n",
100 clause.flags, clause.try_offset, clause.try_len, clause.handler_offset, clause.handler_len);
105 if (mh->num_clauses) {
106 trys = g_malloc0 (sizeof (gboolean) * mh->num_clauses);
108 for (i=1; i < mh->num_clauses; ++i) {
109 #define pcl mh->clauses [i-1]
110 #define cl mh->clauses [i]
111 if (pcl.try_offset != cl.try_offset || pcl.try_len != cl.try_len)
119 for (i = mh->num_clauses - 1; i >= 0 ; --i) {
120 if (ptr == start + mh->clauses[i].try_offset && trys [i]) {
121 fprintf (output, "\t%s.try { // %d\n", indent, i);
125 if (ptr == start + mh->clauses[i].handler_offset) {
126 if (mh->clauses[i].flags == MONO_EXCEPTION_CLAUSE_FILTER) {
128 fprintf (output, "\t%s} { // %d\n", indent, i);
130 char * klass = mh->clauses[i].flags ? g_strdup ("") :
131 dis_stringify_object_with_class (m, mh->clauses[i].data.catch_class,
133 fprintf (output, "\t%s%s %s { // %d\n", indent,
134 clause_names [mh->clauses[i].flags], klass, i);
138 if (mh->clauses[i].flags == MONO_EXCEPTION_CLAUSE_FAULT)
141 if (mh->clauses[i].flags == MONO_EXCEPTION_CLAUSE_FILTER && ptr == start + mh->clauses[i].data.filter_offset) {
142 fprintf (output, "\t%s%s {\n", indent, clause_names[1]);
146 fprintf (output, "\t%sIL_%04x: ", indent, (int) (ptr - start));
152 entry = &mono_opcodes [i];
154 if (in_fault && entry->opval == 0xDC)
155 fprintf (output, " %s", "endfault");
157 fprintf (output, " %s ", mono_opcode_name (i));
159 switch (entry->argument){
160 case MonoInlineBrTarget: {
161 gint target = read32 (ptr);
162 fprintf (output, "IL_%04x\n", ((int) (ptr - start)) + 4 + target);
167 case MonoInlineField: {
168 guint32 token = read32 (ptr);
171 s = get_field (m, token, context);
172 fprintf (output, "%s", s);
179 int value = read32 (ptr);
181 fprintf (output, "%d", value);
187 gint64 top = read64 (ptr);
189 fprintf (output, "0x%llx", (long long) top);
194 case MonoInlineMethod: {
195 guint32 token = read32 (ptr);
198 s = get_method (m, token, context);
199 fprintf (output, "%s", s);
214 fprintf (output, "(00 00 00 00 00 00 f0 ff)"); /* negative infinity */
216 fprintf (output, "(00 00 00 00 00 00 f0 7f)"); /* positive infinity */
218 fprintf (output, "(00 00 00 00 00 00 f8 ff)"); /* NaN */
220 fprintf (output, "%g", r);
225 case MonoInlineSig: {
226 guint32 token = read32 (ptr);
227 fprintf (output, "signature-0x%08x", token);
232 case MonoInlineString: {
233 guint32 token = read32 (ptr);
235 char *s = get_encoded_user_string (
236 mono_metadata_user_string (m, token & 0xffffff));
239 * See section 23.1.4 on the encoding of the #US heap
241 fprintf (output, "\"%s\"", s);
247 case MonoInlineSwitch: {
248 guint32 count = read32 (ptr);
249 const unsigned char *endswitch;
253 endswitch = ptr + sizeof (guint32) * count;
254 fprintf (output, count > 0 ? "(\n" : "( )");
256 for (n = 0; n < count; n++){
257 fprintf (output, "\t%sIL_%04x%s", indent,
258 (int)(endswitch-start+read32 (ptr)),
259 n == count - 1 ? ")" : ",\n");
266 case MonoInlineTok: {
267 guint32 token = read32 (ptr);
270 s = get_token (m, token, context);
271 fprintf (output, "%s", s);
278 case MonoInlineType: {
279 guint32 token = read32 (ptr);
280 char *s = get_token_type (m, token, context);
281 fprintf (output, "%s", s);
287 case MonoInlineVar: {
288 guint16 var_idx = read16 (ptr);
290 fprintf (output, "%d\n", var_idx);
295 case MonoShortInlineBrTarget: {
296 signed char x = *ptr;
298 fprintf (output, "IL_%04x\n", (int)(ptr - start + 1 + x));
303 case MonoShortInlineI: {
306 fprintf (output, "0x%02x", x);
311 case MonoShortInlineR: {
319 fprintf (output, "(00 00 80 ff)"); /* negative infinity */
321 fprintf (output, "(00 00 80 7f)"); /* positive infinity */
323 fprintf (output, "(00 00 c0 ff)"); /* NaN */
325 fprintf (output, "%g", (double) f);
330 case MonoShortInlineVar: {
331 unsigned char x = *ptr;
333 fprintf (output, "%d", (int) x);
341 fprintf (output, "\n");
342 for (i = 0; i < mh->num_clauses; ++i) {
343 if (ptr == start + mh->clauses[i].try_offset + mh->clauses[i].try_len && trys [i]) {
345 fprintf (output, "\t%s} // end .try %d\n", indent, i);
347 if (ptr == start + mh->clauses[i].handler_offset + mh->clauses[i].handler_len) {
349 fprintf (output, "\t%s} // end handler %d\n", indent, i);
350 if (mh->clauses[i].flags == MONO_EXCEPTION_CLAUSE_FAULT)