3d6cd252366431fc9f6cb255f0aba34499c556c0
[mono.git] / mono / dis / declsec.c
1 /*
2  * declsec.h:  Support for the new declarative security attribute
3  *      metadata format (2.0)
4  *
5  * Author:
6  *      Sebastien Pouliot  <sebastien@ximian.com>
7  *
8  * Copyright (C) 2005 Novell, Inc (http://www.novell.com)
9  */
10
11 #include <glib.h>
12 #include <math.h>
13
14 #include "mono/metadata/blob.h"
15 #include "mono/metadata/metadata.h"
16 #include "mono/metadata/mono-endian.h"
17 #include "mono/utils/mono-compiler.h"
18
19 #include "declsec.h"
20 #include "util.h"
21
22 static char*
23 declsec_20_get_classname (const char* p, const char **rptr)
24 {
25         int apos, cpos = 0;
26         char *c;
27         char *a;
28         char *result;
29         GString *res = g_string_new ("");
30         int len = mono_metadata_decode_value (p, &p);
31
32         c = (char *) p;
33         while ((*c++ != ',') && (cpos++ < len));
34         c++;
35
36         apos = cpos;
37         a = c;
38         while ((*a++ != ',') && (apos++ < len));
39
40         if (apos - cpos > 1) {
41                 g_string_append_printf (res, "[%.*s]%.*s", apos - cpos, c, cpos, p);
42         } else {
43                 /* in-assembly type aren't fully qualified (no comma) */
44                 g_string_append_printf (res, "%.*s", cpos - 1, p);
45         }
46
47         p += len;
48         if (rptr)
49                 *rptr = p;
50
51         result = res->str;
52         g_string_free (res, FALSE);
53         return result;
54 }
55
56 static gboolean
57 declsec_20_write_type (GString *str, char type)
58 {
59         switch (type) {
60         case MONO_TYPE_BOOLEAN:
61                 g_string_append (str, "bool");
62                 break;
63         case MONO_TYPE_SZARRAY:
64                 g_string_append (str, "[]");
65                 break;
66         case MONO_TYPE_SYSTEM_TYPE:
67                 g_string_append (str, "type");
68                 break;
69         case MONO_TYPE_STRING:
70                 g_string_append (str, "string");
71                 break;
72         default:
73                 g_warning ("TODO type %d - please fill a bug report on this!", type);
74                 return FALSE;
75         }
76         return TRUE;
77 }
78
79 static const char*
80 declsec_20_write_value (GString *str, char type, const char *value)
81 {
82         switch (type) {
83         case MONO_TYPE_U1:
84                 g_string_append_printf (str, "%d", (unsigned char)*value);
85                 return value + 1;
86         case MONO_TYPE_I1:
87                 g_string_append_printf (str, "%d", *value);
88                 return value + 1;
89         case MONO_TYPE_BOOLEAN:
90                 g_string_append_printf (str, "%s", *value ? "true" : "false");
91                 return value + 1;
92         case MONO_TYPE_CHAR:
93                 g_string_append_printf (str, "0x%04X", read16 (value));
94                 return value + 2;
95         case MONO_TYPE_U2:
96                 g_string_append_printf (str, "%d", read16 (value));
97                 return value + 2;
98         case MONO_TYPE_I2:
99                 g_string_append_printf (str, "%d", (gint16)read16 (value));
100                 return value + 2;
101         case MONO_TYPE_U4:
102                 g_string_append_printf (str, "%d", read32 (value));
103                 return value + 4;
104         case MONO_TYPE_I4:
105                 g_string_append_printf (str, "%d", (gint32)read32 (value));
106                 return value + 4;
107         case MONO_TYPE_U8:
108                 g_string_append_printf (str, "%lld", (long long)read64 (value));
109                 return value + 8;
110         case MONO_TYPE_I8:
111                 g_string_append_printf (str, "%lld", (long long)read64 (value));
112                 return value + 8;
113         case MONO_TYPE_R4: {
114                 float val;
115                 int inf;
116                 readr4 (value, &val);
117                 inf = dis_isinf (val);
118                 if (inf == -1) 
119                         g_string_append_printf (str, "0xFF800000"); /* negative infinity */
120                 else if (inf == 1)
121                         g_string_append_printf (str, "0x7F800000"); /* positive infinity */
122                 else if (dis_isnan (val))
123                         g_string_append_printf (str, "0xFFC00000"); /* NaN */
124                 else
125                         g_string_append_printf (str, "%.8g", val);
126                 return value + 4;
127         }
128         case MONO_TYPE_R8: {
129                 double val;
130                 int inf;
131                 readr8 (value, &val);
132                 inf = dis_isinf (val);
133                 if (inf == -1) 
134                         g_string_append_printf (str, "0xFFF00000000000000"); /* negative infinity */
135                 else if (inf == 1)
136                         g_string_append_printf (str, "0x7FFF0000000000000"); /* positive infinity */
137                 else if (isnan (val))
138                         g_string_append_printf (str, "0xFFF80000000000000"); /* NaN */
139                 else
140                         g_string_append_printf (str, "%.17g", val);
141                 return value + 8;
142         }
143         case MONO_TYPE_STRING:
144                 if (*value == (char)0xff) {
145                         g_string_append (str, "nullref");
146                         return value + 1;
147                 } else {
148                         int len = mono_metadata_decode_value (value, &value);
149                         g_string_append_printf (str, "'%.*s'", len, value);
150                         return value + len;
151                 }
152         case MONO_TYPE_SYSTEM_TYPE: {
153                 char *cname = declsec_20_get_classname (value, NULL);
154                 int len = mono_metadata_decode_value (value, &value);
155                 g_string_append (str, cname);
156                 g_free (cname);
157                 return value + len;
158         }
159         }
160         return 0;
161 }
162
163 char*
164 dump_declsec_entry20 (MonoImage *m, const char* p, const char *indent)
165 {
166         int i, num;
167         char *result;
168         GString *res = g_string_new ("");
169
170         if (*p++ != MONO_DECLSEC_FORMAT_20)
171                 return NULL;
172
173         g_string_append (res, "{");
174
175         /* number of encoded permission attributes */
176         num = mono_metadata_decode_value (p, &p);
177
178         for (i = 0; i < num; i++) {
179                 int len, j, pos = 0, param_len;
180                 char *param_start;
181                 char *s = declsec_20_get_classname (p, &p);
182                 g_string_append_printf (res, "%s = {", s);
183                 g_free (s);
184
185                 /* optional parameters length */
186                 param_len = mono_metadata_decode_value (p, &p);
187                 param_start = (char *) p;
188
189                 /* number of parameters */
190                 pos = mono_metadata_decode_value (p, &p);
191                 for (j = 0; j < pos; j++) {
192                         int k, elem;
193                         int type = *p++;
194
195                         switch (type) {
196                         case MONO_DECLSEC_FIELD:
197                                 /* not sure if/how we can get this in a declarative security attribute... */
198                                 g_string_append (res, "field ");
199                                 break;
200                         case MONO_DECLSEC_PROPERTY:
201                                 g_string_append (res, "property ");
202                                 break;
203                         default:
204                                 g_warning ("TODO %d - please fill a bug report on this!", type);
205                                 break;
206                         }
207
208                         type = *p++;
209
210                         if (type == MONO_DECLSEC_ENUM) {
211                                 s = declsec_20_get_classname (p, &p);
212                                 len = mono_metadata_decode_value (p, &p);
213                                 g_string_append_printf (res, "enum %s '%.*s' = ", s, len, p);
214                                 g_free (s);
215                                 p += len;
216                                 /* TODO: we must detect the size of the enum element (from the type ? length ?)
217                                  * note: ildasm v2 has some problem decoding them too and doesn't
218                                  * seems to rely on the type (as the other assembly isn't loaded) */
219                                 g_string_append_printf (res, "int32(%d)", read32 (p));
220                                 p += 4;
221                         } else {
222                                 int arraytype = 0;
223                                 if (type == MONO_TYPE_SZARRAY) {
224                                         arraytype = *p++;
225                                         declsec_20_write_type (res, arraytype);
226                                 }
227                                 declsec_20_write_type (res, type);
228
229                                 len = mono_metadata_decode_value (p, &p);
230                                 g_string_append_printf (res, " '%.*s' = ", len, p);
231                                 p += len;
232
233                                 if (type == MONO_TYPE_SZARRAY) {
234                                         type = arraytype;
235                                         declsec_20_write_type (res, type);
236                                         elem = read32 (p);
237                                         p += 4;
238                                         g_string_append_printf (res, "[%d]", elem);
239                                 } else {
240                                         declsec_20_write_type (res, type);
241                                         elem = 1;
242                                 }
243                                 g_string_append (res, "(");
244
245                                 /* write value - or each element in the array */
246                                 for (k = 0; k < elem; k++) {
247                                         p = declsec_20_write_value (res, type, p);
248                                         /* separate array elements */
249                                         if (k < elem - 1)
250                                                 g_string_append (res, " ");
251                                 }
252                                 
253                                 if (j < pos - 1)
254                                         g_string_append_printf (res, ")\n%s", indent);
255                                 else
256                                         g_string_append (res, ")");
257                         }
258
259                 }
260
261                 if (i < num - 1)
262                         g_string_append_printf (res, "},\n%s", indent);
263                 else
264                         g_string_append (res, "}");
265
266                 if (param_len > 0)
267                         p = param_start + param_len;
268         }
269         g_string_append (res, "}");
270
271         result = res->str;
272         g_string_free (res, FALSE);
273         return result;
274 }