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