Add System.Net.Http to build
[mono-project.git] / mono / dis / dis-cil.c
blob52af86c5b5d4a3e8801caea8bd749d647ab3ccd0
1 /*
2 * dis-cil.c: Disassembles CIL byte codes
4 * Author:
5 * Miguel de Icaza (miguel@ximian.com)
7 * (C) 2001 Ximian, Inc.
8 */
9 #include <config.h>
10 #include <glib.h>
11 #include <stdio.h>
12 #include <math.h>
13 #ifdef HAVE_WCHAR_H
14 #include <wchar.h>
15 #endif
16 #include "meta.h"
17 #include "get.h"
18 #include "dump.h"
19 #include "dis-cil.h"
20 #include "mono/metadata/opcodes.h"
21 #include "mono/metadata/class-internals.h"
22 #include "mono/utils/mono-compiler.h"
24 #ifndef HAVE_ISINF
26 #ifdef HAVE_IEEEFP_H
27 #include <ieeefp.h>
28 int isinf (double);
29 int
30 isinf (double num)
32 fpclass_t klass;
34 klass = fpclass (num);
35 if (klass == FP_NINF)
36 return -1;
38 if (klass == FP_PINF)
39 return 1;
41 return 0;
43 #else
44 #error "Don't know how to implement isinf for this platform."
45 #endif
47 #endif
49 #define CODE_INDENT g_assert (indent_level < 512); \
50 indent[indent_level*2] = ' '; \
51 indent[indent_level*2+1] = ' '; \
52 ++indent_level; \
53 indent[indent_level*2] = 0;
54 #define CODE_UNINDENT g_assert (indent_level); \
55 --indent_level; \
56 indent[indent_level*2] = 0;
58 void
59 disassemble_cil (MonoImage *m, MonoMethodHeader *mh, MonoGenericContainer *container)
61 const unsigned char *start = mh->code;
62 int size = mh->code_size;
63 const unsigned char *end = start + size;
64 const unsigned char *ptr = start;
65 const MonoOpcode *entry;
66 char indent[1024];
67 int i, j, indent_level = 0;
68 gboolean in_fault = 0;
69 const char *clause_names[] = {"catch", "filter", "finally", "", "fault"};
70 gboolean *trys = NULL;
71 indent [0] = 0;
73 #ifdef DEBUG
74 for (i = 0; i < mh->num_clauses; ++i) {
75 #define clause mh->clauses [i]
76 g_print ("/* out clause %d: from %d len=%d, handler at %d, %d */\n",
77 clause.flags, clause.try_offset, clause.try_len, clause.handler_offset, clause.handler_len);
78 #undef clause
80 #endif
82 if (mh->num_clauses) {
83 trys = g_malloc0 (sizeof (gboolean) * mh->num_clauses);
84 trys [0] = 1;
85 for (i=1; i < mh->num_clauses; ++i) {
86 #define jcl mh->clauses [j]
87 #define cl mh->clauses [i]
88 trys [i] = 1;
89 for (j = 0; j < i; j++) {
90 if (cl.try_offset == jcl.try_offset && cl.try_len == jcl.try_len) {
91 trys [i] = 0;
92 break;
95 #undef jcl
96 #undef cl
100 while (ptr < end){
101 for (i = mh->num_clauses - 1; i >= 0 ; --i) {
102 if (ptr == start + mh->clauses[i].try_offset && trys [i]) {
103 fprintf (output, "\t%s.try { // %d\n", indent, i);
104 CODE_INDENT;
107 if (ptr == start + mh->clauses[i].handler_offset) {
108 if (mh->clauses[i].flags == MONO_EXCEPTION_CLAUSE_FILTER) {
109 CODE_UNINDENT;
110 fprintf (output, "\t%s} { // %d\n", indent, i);
111 } else {
112 char * klass = mh->clauses[i].flags ? g_strdup ("") :
113 dis_stringify_object_with_class (m, mh->clauses[i].data.catch_class,
114 TRUE, FALSE);
115 fprintf (output, "\t%s%s %s { // %d\n", indent,
116 clause_names [mh->clauses[i].flags], klass, i);
117 g_free (klass);
119 CODE_INDENT;
120 if (mh->clauses[i].flags == MONO_EXCEPTION_CLAUSE_FAULT)
121 in_fault = 1;
123 if (mh->clauses[i].flags == MONO_EXCEPTION_CLAUSE_FILTER && ptr == start + mh->clauses[i].data.filter_offset) {
124 fprintf (output, "\t%s%s {\n", indent, clause_names[1]);
125 CODE_INDENT;
128 fprintf (output, "\t%sIL_%04x: ", indent, (int) (ptr - start));
129 i = *ptr;
130 if (*ptr == 0xfe){
131 ptr++;
132 i = *ptr + 256;
134 entry = &mono_opcodes [i];
136 if (in_fault && entry->opval == 0xDC)
137 fprintf (output, " %s", "endfault");
138 else
139 fprintf (output, " %s ", mono_opcode_name (i));
140 ptr++;
141 switch (entry->argument){
142 case MonoInlineBrTarget: {
143 gint target = read32 (ptr);
144 fprintf (output, "IL_%04x\n", ((int) (ptr - start)) + 4 + target);
145 ptr += 4;
146 break;
149 case MonoInlineField: {
150 guint32 token = read32 (ptr);
151 char *s;
153 s = get_field (m, token, container);
154 fprintf (output, "%s", s);
155 g_free (s);
156 ptr += 4;
157 break;
160 case MonoInlineI: {
161 int value = read32 (ptr);
163 fprintf (output, "%d", value);
164 ptr += 4;
165 break;
168 case MonoInlineI8: {
169 gint64 top = read64 (ptr);
171 fprintf (output, "0x%llx", (long long) top);
172 ptr += 8;
173 break;
176 case MonoInlineMethod: {
177 guint32 token = read32 (ptr);
178 char *s;
180 s = get_method (m, token, container);
181 fprintf (output, "%s", s);
182 g_free (s);
183 ptr += 4;
184 break;
187 case MonoInlineNone:
188 break;
190 case MonoInlineR: {
191 double r;
192 int inf;
193 readr8 (ptr, &r);
194 inf = isinf (r);
195 if (inf == -1)
196 fprintf (output, "(00 00 00 00 00 00 f0 ff)"); /* negative infinity */
197 else if (inf == 1)
198 fprintf (output, "(00 00 00 00 00 00 f0 7f)"); /* positive infinity */
199 else if (isnan (r))
200 fprintf (output, "(00 00 00 00 00 00 f8 ff)"); /* NaN */
201 else {
202 char *str = stringify_double (r);
203 fprintf (output, "%s", str);
204 g_free (str);
206 ptr += 8;
207 break;
210 case MonoInlineSig: {
211 guint32 token = read32 (ptr);
212 fprintf (output, "signature-0x%08x", token);
213 ptr += 4;
214 break;
217 case MonoInlineString: {
218 guint32 token = read32 (ptr);
219 const char *us_ptr = mono_metadata_user_string (m, token & 0xffffff);
220 int len = mono_metadata_decode_blob_size (us_ptr, (const char**)&us_ptr);
222 char *s = get_encoded_user_string_or_bytearray ((const guchar*)us_ptr, len);
225 * See section 23.1.4 on the encoding of the #US heap
227 fprintf (output, "%s", s);
228 g_free (s);
229 ptr += 4;
230 break;
233 case MonoInlineSwitch: {
234 guint32 count = read32 (ptr);
235 const unsigned char *endswitch;
236 guint32 n;
238 ptr += 4;
239 endswitch = ptr + sizeof (guint32) * count;
240 fprintf (output, count > 0 ? "(\n" : "( )");
241 CODE_INDENT;
242 for (n = 0; n < count; n++){
243 fprintf (output, "\t%sIL_%04x%s", indent,
244 (int)(endswitch-start+read32 (ptr)),
245 n == count - 1 ? ")" : ",\n");
246 ptr += 4;
248 CODE_UNINDENT;
249 break;
252 case MonoInlineTok: {
253 guint32 token = read32 (ptr);
254 char *s;
256 s = get_token (m, token, container);
257 fprintf (output, "%s", s);
258 g_free (s);
260 ptr += 4;
261 break;
264 case MonoInlineType: {
265 guint32 token = read32 (ptr);
266 char *s = get_token_type (m, token, container);
267 fprintf (output, "%s", s);
268 g_free (s);
269 ptr += 4;
270 break;
273 case MonoInlineVar: {
274 guint16 var_idx = read16 (ptr);
276 fprintf (output, "%d\n", var_idx);
277 ptr += 2;
278 break;
281 case MonoShortInlineBrTarget: {
282 signed char x = *ptr;
284 fprintf (output, "IL_%04x\n", (int)(ptr - start + 1 + x));
285 ptr++;
286 break;
289 case MonoShortInlineI: {
290 char x = *ptr;
292 fprintf (output, "0x%02x", x);
293 ptr++;
294 break;
297 case MonoShortInlineR: {
298 float f;
299 int inf;
301 readr4 (ptr, &f);
303 inf = isinf (f);
304 if (inf == -1)
305 fprintf (output, "(00 00 80 ff)"); /* negative infinity */
306 else if (inf == 1)
307 fprintf (output, "(00 00 80 7f)"); /* positive infinity */
308 else if (isnan (f))
309 fprintf (output, "(00 00 c0 ff)"); /* NaN */
310 else {
311 char *str = stringify_double ((double) f);
312 fprintf (output, "%s", str);
313 g_free (str);
315 ptr += 4;
316 break;
319 case MonoShortInlineVar: {
320 unsigned char x = *ptr;
322 fprintf (output, "%d", (int) x);
323 ptr++;
324 break;
326 default:
327 break;
330 fprintf (output, "\n");
331 for (i = 0; i < mh->num_clauses; ++i) {
332 if (ptr == start + mh->clauses[i].try_offset + mh->clauses[i].try_len && trys [i]) {
333 CODE_UNINDENT;
334 fprintf (output, "\t%s} // end .try %d\n", indent, i);
336 if (ptr == start + mh->clauses[i].handler_offset + mh->clauses[i].handler_len) {
337 CODE_UNINDENT;
338 fprintf (output, "\t%s} // end handler %d\n", indent, i);
339 if (mh->clauses[i].flags == MONO_EXCEPTION_CLAUSE_FAULT)
340 in_fault = 0;
344 if (trys)
345 g_free (trys);