2 * dis-cil.c: Disassembles CIL byte codes
5 * Miguel de Icaza (miguel@ximian.com)
7 * (C) 2001 Ximian, Inc.
21 #include "mono/metadata/opcodes.h"
22 #include "mono/metadata/class-internals.h"
23 #include "mono/utils/mono-compiler.h"
25 #define CODE_INDENT g_assert (indent_level < 512); \
26 indent[indent_level*2] = ' '; \
27 indent[indent_level*2+1] = ' '; \
29 indent[indent_level*2] = 0;
30 #define CODE_UNINDENT g_assert (indent_level); \
32 indent[indent_level*2] = 0;
35 disassemble_cil (MonoImage
*m
, MonoMethodHeader
*mh
, MonoGenericContainer
*container
)
37 const unsigned char *start
= mh
->code
;
38 int size
= mh
->code_size
;
39 const unsigned char *end
= start
+ size
;
40 const unsigned char *ptr
= start
;
41 const MonoOpcode
*entry
;
43 int i
, j
, indent_level
= 0;
44 gboolean in_fault
= 0;
45 const char *clause_names
[] = {"catch", "filter", "finally", "", "fault"};
46 gboolean
*trys
= NULL
;
50 for (i
= 0; i
< mh
->num_clauses
; ++i
) {
51 #define clause mh->clauses [i]
52 g_print ("/* out clause %d: from %d len=%d, handler at %d, %d */\n",
53 clause
.flags
, clause
.try_offset
, clause
.try_len
, clause
.handler_offset
, clause
.handler_len
);
58 if (mh
->num_clauses
) {
59 trys
= (gboolean
*)g_malloc0 (sizeof (gboolean
) * mh
->num_clauses
);
61 for (i
=1; i
< mh
->num_clauses
; ++i
) {
62 #define jcl mh->clauses [j]
63 #define cl mh->clauses [i]
65 for (j
= 0; j
< i
; j
++) {
66 if (cl
.try_offset
== jcl
.try_offset
&& cl
.try_len
== jcl
.try_len
) {
77 for (i
= mh
->num_clauses
- 1; i
>= 0 ; --i
) {
78 if (ptr
== start
+ mh
->clauses
[i
].try_offset
&& trys
[i
]) {
79 fprintf (output
, "\t%s.try { // %d\n", indent
, i
);
83 if (ptr
== start
+ mh
->clauses
[i
].handler_offset
) {
84 if (mh
->clauses
[i
].flags
== MONO_EXCEPTION_CLAUSE_FILTER
) {
86 fprintf (output
, "\t%s} { // %d\n", indent
, i
);
88 char * klass
= mh
->clauses
[i
].flags
? g_strdup ("") :
89 dis_stringify_object_with_class (m
, mh
->clauses
[i
].data
.catch_class
,
91 fprintf (output
, "\t%s%s %s { // %d\n", indent
,
92 clause_names
[mh
->clauses
[i
].flags
], klass
, i
);
96 if (mh
->clauses
[i
].flags
== MONO_EXCEPTION_CLAUSE_FAULT
)
99 if (mh
->clauses
[i
].flags
== MONO_EXCEPTION_CLAUSE_FILTER
&& ptr
== start
+ mh
->clauses
[i
].data
.filter_offset
) {
100 fprintf (output
, "\t%s%s {\n", indent
, clause_names
[1]);
104 fprintf (output
, "\t%sIL_%04x: ", indent
, (int) (ptr
- start
));
110 entry
= &mono_opcodes
[i
];
112 if (in_fault
&& entry
->opval
== 0xDC)
113 fprintf (output
, " %s", "endfault");
115 fprintf (output
, " %s ", mono_opcode_name (i
));
117 switch (entry
->argument
){
118 case MonoInlineBrTarget
: {
119 gint target
= read32 (ptr
);
120 fprintf (output
, "IL_%04x\n", ((int) (ptr
- start
)) + 4 + target
);
125 case MonoInlineField
: {
126 guint32 token
= read32 (ptr
);
129 s
= get_field (m
, token
, container
);
130 fprintf (output
, "%s", s
);
137 int value
= read32 (ptr
);
139 fprintf (output
, "%d", value
);
145 gint64 top
= read64 (ptr
);
147 fprintf (output
, "0x%llx", (long long) top
);
152 case MonoInlineMethod
: {
153 guint32 token
= read32 (ptr
);
156 s
= get_method (m
, token
, container
);
157 fprintf (output
, "%s", s
);
172 fprintf (output
, "(00 00 00 00 00 00 f0 ff)"); /* negative infinity */
174 fprintf (output
, "(00 00 00 00 00 00 f0 7f)"); /* positive infinity */
175 else if (dis_isnan (r
))
176 fprintf (output
, "(00 00 00 00 00 00 f8 ff)"); /* NaN */
178 char *str
= stringify_double (r
);
179 fprintf (output
, "%s", str
);
186 case MonoInlineSig
: {
187 guint32 token
= read32 (ptr
);
188 fprintf (output
, "signature-0x%08x", token
);
193 case MonoInlineString
: {
194 guint32 token
= read32 (ptr
);
195 const char *us_ptr
= mono_metadata_user_string (m
, token
& 0xffffff);
196 int len
= mono_metadata_decode_blob_size (us_ptr
, (const char**)&us_ptr
);
198 char *s
= get_encoded_user_string_or_bytearray ((const guchar
*)us_ptr
, len
);
201 * See section 23.1.4 on the encoding of the #US heap
203 fprintf (output
, "%s", s
);
209 case MonoInlineSwitch
: {
210 guint32 count
= read32 (ptr
);
211 const unsigned char *endswitch
;
215 endswitch
= ptr
+ sizeof (guint32
) * count
;
216 fprintf (output
, count
> 0 ? "(\n" : "( )");
218 for (n
= 0; n
< count
; n
++){
219 fprintf (output
, "\t%sIL_%04x%s", indent
,
220 (int)(endswitch
-start
+read32 (ptr
)),
221 n
== count
- 1 ? ")" : ",\n");
228 case MonoInlineTok
: {
229 guint32 token
= read32 (ptr
);
232 s
= get_token (m
, token
, container
);
233 fprintf (output
, "%s", s
);
240 case MonoInlineType
: {
241 guint32 token
= read32 (ptr
);
242 char *s
= get_token_type (m
, token
, container
);
243 fprintf (output
, "%s", s
);
249 case MonoInlineVar
: {
250 guint16 var_idx
= read16 (ptr
);
252 fprintf (output
, "%d\n", var_idx
);
257 case MonoShortInlineBrTarget
: {
258 signed char x
= *ptr
;
260 fprintf (output
, "IL_%04x\n", (int)(ptr
- start
+ 1 + x
));
265 case MonoShortInlineI
: {
268 fprintf (output
, "0x%02x", x
);
273 case MonoShortInlineR
: {
281 fprintf (output
, "(00 00 80 ff)"); /* negative infinity */
283 fprintf (output
, "(00 00 80 7f)"); /* positive infinity */
284 else if (dis_isnan (f
))
285 fprintf (output
, "(00 00 c0 ff)"); /* NaN */
287 char *str
= stringify_double ((double) f
);
288 fprintf (output
, "%s", str
);
295 case MonoShortInlineVar
: {
296 unsigned char x
= *ptr
;
298 fprintf (output
, "%d", (int) x
);
306 fprintf (output
, "\n");
307 for (i
= 0; i
< mh
->num_clauses
; ++i
) {
308 if (ptr
== start
+ mh
->clauses
[i
].try_offset
+ mh
->clauses
[i
].try_len
&& trys
[i
]) {
310 fprintf (output
, "\t%s} // end .try %d\n", indent
, i
);
312 if (ptr
== start
+ mh
->clauses
[i
].handler_offset
+ mh
->clauses
[i
].handler_len
) {
314 fprintf (output
, "\t%s} // end handler %d\n", indent
, i
);
315 if (mh
->clauses
[i
].flags
== MONO_EXCEPTION_CLAUSE_FAULT
)