2 * dis-cil.c: Disassembles CIL byte codes
5 * Miguel de Icaza (miguel@ximian.com)
7 * (C) 2001 Ximian, Inc.
17 #include "mono/metadata/opcodes.h"
20 * Strings on the US heap are encoded using UTF-16. Poor man's
21 * UTF-16 to UTF-8. I know its broken, use libunicode later.
24 get_encoded_user_string (const char *ptr)
29 len = mono_metadata_decode_blob_size (ptr, &ptr);
30 res = g_malloc (len + 1);
33 * I should really use some kind of libunicode here
35 for (i = 0, j = 0; i < len; j++, i += 2)
43 #define CODE_INDENT g_assert (indent_level < 512); \
44 indent[indent_level*2] = ' '; \
45 indent[indent_level*2+1] = ' '; \
47 indent[indent_level*2] = 0;
48 #define CODE_UNINDENT g_assert (indent_level); \
50 indent[indent_level*2] = 0;
53 dissasemble_cil (MonoImage *m, MonoMethodHeader *mh)
55 const unsigned char *start = mh->code;
56 int size = mh->code_size;
57 const unsigned char *end = start + size;
58 const unsigned char *ptr = start;
59 const MonoOpcode *entry;
61 int i, indent_level = 0;
62 const char *clause_names[] = {"catch", "filter", "finally", "fault"};
67 for (i = 0; i < mh->num_clauses; ++i) {
68 #define clause mh->clauses [i]
69 g_print ("out clause %d: from %d len=%d, handler at %d, %d\n",
70 clause.flags, clause.try_offset, clause.try_len, clause.handler_offset, clause.handler_len);
75 for (i = mh->num_clauses - 1; i >= 0 ; --i) {
76 if ((mh->clauses[i].flags == 0 || mh->clauses[i].flags == 2) && ptr == start + mh->clauses[i].try_offset) {
77 fprintf (output, "\t%s.try { // %d\n", indent, i);
80 if (ptr == start + mh->clauses[i].handler_offset) {
81 char * klass = mh->clauses[i].flags ? g_strdup ("") : dis_stringify_token (m, mh->clauses[i].token_or_filter);
82 fprintf (output, "\t%s%s %s { // %d\n", indent, clause_names [mh->clauses[i].flags], klass, i);
87 fprintf (output, "\t%sIL_%04x: ", indent, (int) (ptr - start));
93 entry = &mono_opcodes [i];
95 fprintf (output, "%s ", mono_opcode_names [i]);
97 switch (entry->argument){
98 case MonoInlineBrTarget: {
99 gint target = read32 (ptr);
100 fprintf (output, "IL_%04x\n", ((int) (ptr - start)) + 4 + target);
105 case MonoInlineField: {
106 guint32 token = read32 (ptr);
109 s = get_field (m, token);
110 fprintf (output, "%s", s);
117 int value = read32 (ptr);
119 fprintf (output, "%d", value);
125 gint64 top = read64 (ptr);
127 fprintf (output, "0x%llx", (long long) top);
132 case MonoInlineMethod: {
133 guint32 token = read32 (ptr);
136 s = get_method (m, token);
137 fprintf (output, "%s", s);
149 fprintf (output, "%g", r);
154 case MonoInlineSig: {
155 guint32 token = read32 (ptr);
156 fprintf (output, "signature-0x%08x", token);
161 case MonoInlineString: {
162 guint32 token = read32 (ptr);
164 char *s = get_encoded_user_string (
165 mono_metadata_user_string (m, token & 0xffffff));
168 * See section 23.1.4 on the encoding of the #US heap
170 fprintf (output, "\"%s\"", s);
176 case MonoInlineSwitch: {
177 guint32 count = read32 (ptr);
178 const unsigned char *endswitch;
182 endswitch = ptr + sizeof (guint32) * count;
183 fprintf (output, "(\n");
185 for (n = 0; n < count; n++){
186 fprintf (output, "\t%sIL_%04x%s", indent,
187 endswitch-start+read32 (ptr),
188 n == count - 1 ? ")" : ",\n");
195 case MonoInlineTok: {
196 guint32 token = read32 (ptr);
199 s = get_token (m, token);
200 fprintf (output, "%s", s);
207 case MonoInlineType: {
208 guint32 token = read32 (ptr);
209 char *s = get_token_type (m, token);
210 fprintf (output, "%s", s);
216 case MonoInlineVar: {
217 guint16 var_idx = read16 (ptr);
219 fprintf (output, "%d\n", var_idx);
224 case MonoShortInlineBrTarget: {
225 signed char x = *ptr;
227 fprintf (output, "IL_%04x\n", ptr - start + 1 + x);
232 case MonoShortInlineI: {
235 fprintf (output, "0x%02x", x);
240 case MonoShortInlineR: {
244 fprintf (output, "%g", (double) f);
249 case MonoShortInlineVar: {
250 unsigned char x = *ptr;
252 fprintf (output, "%d", (int) x);
260 fprintf (output, "\n");
261 for (i = 0; i < mh->num_clauses; ++i) {
262 if ((mh->clauses[i].flags == 0 || mh->clauses[i].flags == 2) && ptr == start + mh->clauses[i].try_offset + mh->clauses[i].try_len) {
264 fprintf (output, "\t%s} // end .try %d\n", indent, i);
266 if (ptr == start + mh->clauses[i].handler_offset + mh->clauses[i].handler_len) {
268 fprintf (output, "\t%s} // end handler %d\n", indent, i);