Wed Jul 11 18:52:15 CEST 2001 Paolo Molaro <lupus@ximian.com>
[mono.git] / mono / dis / dis-cil.c
1 /*
2  * dis-cil.c: Disassembles CIL byte codes
3  *
4  * Author:
5  *   Miguel de Icaza (miguel@ximian.com)
6  *
7  * (C) 2001 Ximian, Inc.
8  */
9 #include <config.h>
10 #include <glib.h>
11 #include <stdio.h>
12 #include <wchar.h>
13 #include "meta.h"
14 #include "get.h"
15 #include "dump.h"
16 #include "dis-cil.h"
17
18 enum {
19         InlineBrTarget,
20         InlineField,
21         InlineI,
22         InlineI8,
23         InlineMethod,
24         InlineNone,
25         InlineR,
26         InlineSig,
27         InlineString,
28         InlineSwitch,
29         InlineTok,
30         InlineType,
31         InlineVar,
32         ShortInlineBrTarget,
33         ShortInlineI,
34         ShortInlineR,
35         ShortInlineVar
36 };
37
38 #define OPDEF(a,b,c,d,e,f,g,h,i,j) \
39         { b, e, g, h, i },
40
41 typedef struct {
42         char *name;
43         int   argument;
44
45         /*
46          * we are not really using any of the following:
47          */
48         int   bytes;
49         unsigned char  o1, o2;
50 } opcode_t;
51
52 static opcode_t opcodes [300] = {
53 #include "mono/cil/opcode.def"
54 };
55
56 /*
57  * Strings on the US heap are encoded using UTF-16.  Poor man's
58  * UTF-16 to UTF-8.  I know its broken, use libunicode later.
59  */
60 static char *
61 get_encoded_user_string (const char *ptr)
62 {
63         char *res;
64         int len, i, j;
65
66         ptr = get_blob_encoded_size (ptr, &len);
67         res = g_malloc (len + 1);
68
69         /*
70          * I should really use some kind of libunicode here
71          */
72         for (i = 0, j = 0; i < len; j++, i += 2)
73                 res [j] = ptr [i];
74
75         res [j] = 0;
76                 
77         return res;
78 }
79
80 void
81 dissasemble_cil (metadata_t *m, const unsigned char *start, int size) 
82 {
83         const unsigned char *end = start + size;
84         const unsigned char *ptr = start;
85         opcode_t *entry;
86
87         while (ptr < end){
88                 if (*ptr == 0xfe){
89                         ptr++;
90                         entry = &opcodes [*ptr + 256];
91                 } else 
92                         entry = &opcodes [*ptr];
93
94                 fprintf (output, "\tIL_%04x: %s ", (int) (ptr - start), entry->name);
95                 ptr++;
96                 switch (entry->argument){
97                 case InlineBrTarget: {
98                         gint target = *(gint32 *) ptr;
99                         fprintf (output, "IL_%04x", ((int) (ptr - start)) + 4 + target);
100                         ptr += 4;
101                         break;
102                 }
103                         
104                 case InlineField: {
105                         guint32 token = *(guint32 *) ptr;
106                         fprintf (output, "fieldref-0x%08x", token);
107                         ptr += 4;
108                         break;
109                 }
110                 
111                 case InlineI: {
112                         int value = *(int *) ptr;
113
114                         fprintf (output, "%d", value);
115                         ptr += 4;
116                         break;
117                 }
118                 
119                 case InlineI8: {
120                         gint64 top = *(guint64 *) ptr;
121
122                         fprintf (output, "%lld", (long long) top);
123                         ptr += 8;
124                         break;
125                 }
126                 
127                 case InlineMethod: {
128                         guint32 token = *(guint32 *) ptr;
129                         fprintf (output, "method-0x%08x", token);
130                         ptr += 4;
131                         break;
132                 }
133                 
134                 case InlineNone:
135                         break;
136                         
137                 case InlineR: {
138                         double r = *(double *) ptr;
139                         fprintf (output, "%g", r);
140                         ptr += 8;
141                         break;
142                 }
143                 
144                 case InlineSig: {
145                         guint32 token = *(guint32 *) ptr;
146                         fprintf (output, "signature-0x%08x", token);
147                         ptr += 4;
148                         break;
149                 }
150                 
151                 case InlineString: {
152                         guint32 token = *(guint32 *) ptr;
153                         
154                         char *s = get_encoded_user_string (
155                                 mono_metadata_user_string (m, token & 0xffffff));
156                         
157                         /*
158                          * See section 23.1.4 on the encoding of the #US heap
159                          */
160                         fprintf (output, "\"%s\"", s);
161                         g_free (s);
162                         ptr += 4;
163                         break;
164                 }
165
166                 case InlineSwitch: {
167                         guint32 count = *(guint32 *) ptr;
168                         guint32 i;
169                         
170                         ptr += 4;
171                         fprintf (output, "(\n\t\t\t");
172                         for (i = 0; i < count; i++){
173                                 fprintf (output, "IL_%x", *(guint32 *) ptr);
174                                 ptr += 4;
175                         }
176                         fprintf (output, "\t\t\t)");
177                         break;
178                 }
179
180                 case InlineTok: {
181                         guint32 token = *(guint32 *) ptr;
182
183                         fprintf (output, "TOKEN_%08x", token);
184                         ptr += 4;
185                         break;
186                 }
187                 
188                 case InlineType: {
189                         guint32 token = *(guint32 *) ptr;
190
191                         fprintf (output, "Type-%08x", token);
192                         ptr += 4;
193                         break;
194                 }
195
196                 case InlineVar: {
197                         gint16 var_idx = *(gint16 *) ptr;
198
199                         fprintf (output, "variable-%d\n", var_idx);
200                         ptr += 2;
201                         break;
202                 }
203
204                 case ShortInlineBrTarget: {
205                         signed char x = *ptr;
206                         
207                         fprintf (output, "IL_%04x", ptr - start + 1 + x);
208                         ptr++;
209                         break;
210                 }
211
212                 case ShortInlineI: {
213                         char x = *ptr;
214
215                         fprintf (output, "0x%02x", x);
216                         ptr++;
217                         break;
218                 }
219
220                 case ShortInlineR: {
221                         float f = *(float *) ptr;
222
223                         fprintf (output, "%g", (double) f);
224                         ptr += 4;
225                         break;
226                 }
227
228                 case ShortInlineVar: {
229                         signed char x = *ptr;
230
231                         fprintf (output, "V_%d", (int) x);
232                         ptr++;
233                         break;
234                 }
235
236                 }
237
238                 fprintf (output, "\n");
239         }
240 }