2009-03-11 Zoltan Varga <vargaz@gmail.com>
[mono-debugger.git] / mono / dis / declsec.c
blobff5ca5a59411fb90f57cb52f60f04ec5a59c66d6
1 /*
2 * declsec.h: Support for the new declarative security attribute
3 * metadata format (2.0)
5 * Author:
6 * Sebastien Pouliot <sebastien@ximian.com>
8 * Copyright (C) 2005 Novell, Inc (http://www.novell.com)
9 */
11 #include <glib.h>
12 #include <math.h>
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"
19 #include "declsec.h"
21 static char*
22 declsec_20_get_classname (const char* p, const char **rptr)
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);
31 c = (char *) p;
32 while ((*c++ != ',') && (cpos++ < len));
33 c++;
35 apos = cpos;
36 a = c;
37 while ((*a++ != ',') && (apos++ < len));
39 if (apos - cpos > 1) {
40 g_string_sprintfa (res, "[%.*s]%.*s", apos - cpos, c, cpos, p);
41 } else {
42 /* in-assembly type aren't fully qualified (no comma) */
43 g_string_sprintfa (res, "%.*s", cpos - 1, p);
46 p += len;
47 if (rptr)
48 *rptr = p;
50 result = res->str;
51 g_string_free (res, FALSE);
52 return result;
55 static gboolean
56 declsec_20_write_type (GString *str, char type)
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;
75 return TRUE;
78 static const char*
79 declsec_20_write_value (GString *str, char type, const char *value)
81 switch (type) {
82 case MONO_TYPE_U1:
83 g_string_sprintfa (str, "%d", (unsigned char)*value);
84 return value + 1;
85 case MONO_TYPE_I1:
86 g_string_sprintfa (str, "%d", *value);
87 return value + 1;
88 case MONO_TYPE_BOOLEAN:
89 g_string_sprintfa (str, "%s", *value ? "true" : "false");
90 return value + 1;
91 case MONO_TYPE_CHAR:
92 g_string_sprintfa (str, "0x%04X", read16 (value));
93 return value + 2;
94 case MONO_TYPE_U2:
95 g_string_sprintfa (str, "%d", read16 (value));
96 return value + 2;
97 case MONO_TYPE_I2:
98 g_string_sprintfa (str, "%d", (gint16)read16 (value));
99 return value + 2;
100 case MONO_TYPE_U4:
101 g_string_sprintfa (str, "%d", read32 (value));
102 return value + 4;
103 case MONO_TYPE_I4:
104 g_string_sprintfa (str, "%d", (gint32)read32 (value));
105 return value + 4;
106 case MONO_TYPE_U8:
107 g_string_sprintfa (str, "%lld", (long long)read64 (value));
108 return value + 8;
109 case MONO_TYPE_I8:
110 g_string_sprintfa (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_sprintfa (str, "0xFF800000"); /* negative infinity */
119 else if (inf == 1)
120 g_string_sprintfa (str, "0x7F800000"); /* positive infinity */
121 else if (isnan (val))
122 g_string_sprintfa (str, "0xFFC00000"); /* NaN */
123 else
124 g_string_sprintfa (str, "%.8g", val);
125 return value + 4;
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_sprintfa (str, "0xFFF00000000000000"); /* negative infinity */
134 else if (inf == 1)
135 g_string_sprintfa (str, "0x7FFF0000000000000"); /* positive infinity */
136 else if (isnan (val))
137 g_string_sprintfa (str, "0xFFF80000000000000"); /* NaN */
138 else
139 g_string_sprintfa (str, "%.17g", val);
140 return value + 8;
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_sprintfa (str, "'%.*s'", len, value);
149 return value + len;
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;
159 return 0;
162 char*
163 dump_declsec_entry20 (MonoImage *m, const char* p, const char *indent)
165 int i, num;
166 char *result;
167 GString *res = g_string_new ("");
169 if (*p++ != MONO_DECLSEC_FORMAT_20)
170 return NULL;
172 g_string_append (res, "{");
174 /* number of encoded permission attributes */
175 num = mono_metadata_decode_value (p, &p);
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_sprintfa (res, "%s = {", s);
182 g_free (s);
184 /* optional parameters length */
185 param_len = mono_metadata_decode_value (p, &p);
186 param_start = (char *) p;
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++;
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;
207 type = *p++;
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_sprintfa (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_sprintfa (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);
226 declsec_20_write_type (res, type);
228 len = mono_metadata_decode_value (p, &p);
229 g_string_sprintfa (res, " '%.*s' = ", len, p);
230 p += len;
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_sprintfa (res, "[%d]", elem);
238 } else {
239 declsec_20_write_type (res, type);
240 elem = 1;
242 g_string_append (res, "(");
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, " ");
252 if (j < pos - 1)
253 g_string_sprintfa (res, ")\n%s", indent);
254 else
255 g_string_append (res, ")");
260 if (i < num - 1)
261 g_string_sprintfa (res, "},\n%s", indent);
262 else
263 g_string_append (res, "}");
265 if (param_len > 0)
266 p = param_start + param_len;
268 g_string_append (res, "}");
270 result = res->str;
271 g_string_free (res, FALSE);
272 return result;