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/metadata/class-internals.h"
22 #include "mono/utils/mono-compiler.h"
34 klass
= fpclass (num
);
44 #error "Don't know how to implement isinf for this platform."
49 #define CODE_INDENT g_assert (indent_level < 512); \
50 indent[indent_level*2] = ' '; \
51 indent[indent_level*2+1] = ' '; \
53 indent[indent_level*2] = 0;
54 #define CODE_UNINDENT g_assert (indent_level); \
56 indent[indent_level*2] = 0;
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
;
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
;
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
);
82 if (mh
->num_clauses
) {
83 trys
= g_malloc0 (sizeof (gboolean
) * mh
->num_clauses
);
85 for (i
=1; i
< mh
->num_clauses
; ++i
) {
86 #define jcl mh->clauses [j]
87 #define cl mh->clauses [i]
89 for (j
= 0; j
< i
; j
++) {
90 if (cl
.try_offset
== jcl
.try_offset
&& cl
.try_len
== jcl
.try_len
) {
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
);
107 if (ptr
== start
+ mh
->clauses
[i
].handler_offset
) {
108 if (mh
->clauses
[i
].flags
== MONO_EXCEPTION_CLAUSE_FILTER
) {
110 fprintf (output
, "\t%s} { // %d\n", indent
, i
);
112 char * klass
= mh
->clauses
[i
].flags
? g_strdup ("") :
113 dis_stringify_object_with_class (m
, mh
->clauses
[i
].data
.catch_class
,
115 fprintf (output
, "\t%s%s %s { // %d\n", indent
,
116 clause_names
[mh
->clauses
[i
].flags
], klass
, i
);
120 if (mh
->clauses
[i
].flags
== MONO_EXCEPTION_CLAUSE_FAULT
)
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]);
128 fprintf (output
, "\t%sIL_%04x: ", indent
, (int) (ptr
- start
));
134 entry
= &mono_opcodes
[i
];
136 if (in_fault
&& entry
->opval
== 0xDC)
137 fprintf (output
, " %s", "endfault");
139 fprintf (output
, " %s ", mono_opcode_name (i
));
141 switch (entry
->argument
){
142 case MonoInlineBrTarget
: {
143 gint target
= read32 (ptr
);
144 fprintf (output
, "IL_%04x\n", ((int) (ptr
- start
)) + 4 + target
);
149 case MonoInlineField
: {
150 guint32 token
= read32 (ptr
);
153 s
= get_field (m
, token
, container
);
154 fprintf (output
, "%s", s
);
161 int value
= read32 (ptr
);
163 fprintf (output
, "%d", value
);
169 gint64 top
= read64 (ptr
);
171 fprintf (output
, "0x%llx", (long long) top
);
176 case MonoInlineMethod
: {
177 guint32 token
= read32 (ptr
);
180 s
= get_method (m
, token
, container
);
181 fprintf (output
, "%s", s
);
196 fprintf (output
, "(00 00 00 00 00 00 f0 ff)"); /* negative infinity */
198 fprintf (output
, "(00 00 00 00 00 00 f0 7f)"); /* positive infinity */
200 fprintf (output
, "(00 00 00 00 00 00 f8 ff)"); /* NaN */
202 char *str
= stringify_double (r
);
203 fprintf (output
, "%s", str
);
210 case MonoInlineSig
: {
211 guint32 token
= read32 (ptr
);
212 fprintf (output
, "signature-0x%08x", token
);
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
);
233 case MonoInlineSwitch
: {
234 guint32 count
= read32 (ptr
);
235 const unsigned char *endswitch
;
239 endswitch
= ptr
+ sizeof (guint32
) * count
;
240 fprintf (output
, count
> 0 ? "(\n" : "( )");
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");
252 case MonoInlineTok
: {
253 guint32 token
= read32 (ptr
);
256 s
= get_token (m
, token
, container
);
257 fprintf (output
, "%s", s
);
264 case MonoInlineType
: {
265 guint32 token
= read32 (ptr
);
266 char *s
= get_token_type (m
, token
, container
);
267 fprintf (output
, "%s", s
);
273 case MonoInlineVar
: {
274 guint16 var_idx
= read16 (ptr
);
276 fprintf (output
, "%d\n", var_idx
);
281 case MonoShortInlineBrTarget
: {
282 signed char x
= *ptr
;
284 fprintf (output
, "IL_%04x\n", (int)(ptr
- start
+ 1 + x
));
289 case MonoShortInlineI
: {
292 fprintf (output
, "0x%02x", x
);
297 case MonoShortInlineR
: {
305 fprintf (output
, "(00 00 80 ff)"); /* negative infinity */
307 fprintf (output
, "(00 00 80 7f)"); /* positive infinity */
309 fprintf (output
, "(00 00 c0 ff)"); /* NaN */
311 char *str
= stringify_double ((double) f
);
312 fprintf (output
, "%s", str
);
319 case MonoShortInlineVar
: {
320 unsigned char x
= *ptr
;
322 fprintf (output
, "%d", (int) x
);
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
]) {
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
) {
338 fprintf (output
, "\t%s} // end handler %d\n", indent
, i
);
339 if (mh
->clauses
[i
].flags
== MONO_EXCEPTION_CLAUSE_FAULT
)