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