1 /**
2  * \file
3  * Copyright 2016 Microsoft
4  * Licensed under the MIT license. See LICENSE file in the project root for full license information.
5  */
6 #include <config.h>
7 #include <mono/metadata/class-internals.h>
8 #include <mono/metadata/tabledefs.h>
9 
10 
11 typedef enum {
12 	PROP_MARSHAL_INFO = 1, /* MonoMarshalType */
13 	PROP_REF_INFO_HANDLE = 2, /* gchandle */
14 	PROP_EXCEPTION_DATA = 3, /* MonoErrorBoxed* */
15 	PROP_NESTED_CLASSES = 4, /* GList* */
16 	PROP_PROPERTY_INFO = 5, /* MonoClassPropertyInfo* */
17 	PROP_EVENT_INFO = 6, /* MonoClassEventInfo* */
18 	PROP_FIELD_DEF_VALUES = 7, /* MonoFieldDefaultValue* */
19 	PROP_DECLSEC_FLAGS = 8, /* guint32 */
20 	PROP_WEAK_BITMAP = 9
21 }  InfrequentDataKind;
22 
23 /* Accessors based on class kind*/
24 
25 /*
26 * mono_class_get_generic_class:
27 *
28 *   Return the MonoGenericClass of @klass, which MUST be a generic instance.
29 */
30 MonoGenericClass*
mono_class_get_generic_class(MonoClass * klass)31 mono_class_get_generic_class (MonoClass *klass)
32 {
33 	g_assert (mono_class_is_ginst (klass));
34 	return ((MonoClassGenericInst*)klass)->generic_class;
35 }
36 
37 /*
38 * mono_class_try_get_generic_class:
39 *
40 *   Return the MonoGenericClass if @klass is a ginst, NULL otherwise
41 */
42 MonoGenericClass*
mono_class_try_get_generic_class(MonoClass * klass)43 mono_class_try_get_generic_class (MonoClass *klass)
44 {
45 	if (mono_class_is_ginst (klass))
46 		return ((MonoClassGenericInst*)klass)->generic_class;
47 	return NULL;
48 }
49 
50 /**
51  * mono_class_get_flags:
52  * \param klass the MonoClass to act on
53  * \returns the \c TypeAttributes flags of \p klass.
54  * See the \c TYPE_ATTRIBUTE_* definitions in \c tabledefs.h for the different values.
55  */
56 guint32
mono_class_get_flags(MonoClass * klass)57 mono_class_get_flags (MonoClass *klass)
58 {
59 	switch (klass->class_kind) {
60 	case MONO_CLASS_DEF:
61 	case MONO_CLASS_GTD:
62 		return ((MonoClassDef*)klass)->flags;
63 	case MONO_CLASS_GINST:
64 		return mono_class_get_flags (((MonoClassGenericInst*)klass)->generic_class->container_class);
65 	case MONO_CLASS_GPARAM:
66 		return TYPE_ATTRIBUTE_PUBLIC;
67 	case MONO_CLASS_ARRAY:
68 		/* all arrays are marked serializable and sealed, bug #42779 */
69 		return TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | TYPE_ATTRIBUTE_PUBLIC;
70 	case MONO_CLASS_POINTER:
71 		return TYPE_ATTRIBUTE_CLASS | (mono_class_get_flags (klass->element_class) & TYPE_ATTRIBUTE_VISIBILITY_MASK);
72 	}
73 	g_assert_not_reached ();
74 }
75 
76 void
mono_class_set_flags(MonoClass * klass,guint32 flags)77 mono_class_set_flags (MonoClass *klass, guint32 flags)
78 {
79 	g_assert (klass->class_kind == MONO_CLASS_DEF || klass->class_kind == MONO_CLASS_GTD);
80 	((MonoClassDef*)klass)->flags = flags;
81 }
82 
83 /*
84  * mono_class_get_generic_container:
85  *
86  *   Return the generic container of KLASS which should be a generic type definition.
87  */
88 MonoGenericContainer*
mono_class_get_generic_container(MonoClass * klass)89 mono_class_get_generic_container (MonoClass *klass)
90 {
91 	g_assert (mono_class_is_gtd (klass));
92 
93 	return ((MonoClassGtd*)klass)->generic_container;
94 }
95 
96 MonoGenericContainer*
mono_class_try_get_generic_container(MonoClass * klass)97 mono_class_try_get_generic_container (MonoClass *klass)
98 {
99 	if (mono_class_is_gtd (klass))
100 		return ((MonoClassGtd*)klass)->generic_container;
101 	return NULL;
102 }
103 
104 
105 void
mono_class_set_generic_container(MonoClass * klass,MonoGenericContainer * container)106 mono_class_set_generic_container (MonoClass *klass, MonoGenericContainer *container)
107 {
108 	g_assert (mono_class_is_gtd (klass));
109 
110 	((MonoClassGtd*)klass)->generic_container = container;
111 }
112 
113 /*
114  * mono_class_get_first_method_idx:
115  *
116  *   Return the table index of the first method for metadata classes.
117  */
118 guint32
mono_class_get_first_method_idx(MonoClass * klass)119 mono_class_get_first_method_idx (MonoClass *klass)
120 {
121 	g_assert (mono_class_has_static_metadata (klass));
122 
123 	return ((MonoClassDef*)klass)->first_method_idx;
124 }
125 
126 void
mono_class_set_first_method_idx(MonoClass * klass,guint32 idx)127 mono_class_set_first_method_idx (MonoClass *klass, guint32 idx)
128 {
129 	g_assert (mono_class_has_static_metadata (klass));
130 
131 	((MonoClassDef*)klass)->first_method_idx = idx;
132 }
133 
134 guint32
mono_class_get_first_field_idx(MonoClass * klass)135 mono_class_get_first_field_idx (MonoClass *klass)
136 {
137 	if (mono_class_is_ginst (klass))
138 		return mono_class_get_first_field_idx (mono_class_get_generic_class (klass)->container_class);
139 
140 	g_assert (mono_class_has_static_metadata (klass));
141 
142 	return ((MonoClassDef*)klass)->first_field_idx;
143 }
144 
145 void
mono_class_set_first_field_idx(MonoClass * klass,guint32 idx)146 mono_class_set_first_field_idx (MonoClass *klass, guint32 idx)
147 {
148 	g_assert (mono_class_has_static_metadata (klass));
149 
150 	((MonoClassDef*)klass)->first_field_idx = idx;
151 }
152 
153 guint32
mono_class_get_method_count(MonoClass * klass)154 mono_class_get_method_count (MonoClass *klass)
155 {
156 	switch (klass->class_kind) {
157 	case MONO_CLASS_DEF:
158 	case MONO_CLASS_GTD:
159 		return ((MonoClassDef*)klass)->method_count;
160 	case MONO_CLASS_GINST:
161 		return mono_class_get_method_count (((MonoClassGenericInst*)klass)->generic_class->container_class);
162 	case MONO_CLASS_GPARAM:
163 		return 0;
164 	case MONO_CLASS_ARRAY:
165 		return ((MonoClassArray*)klass)->method_count;
166 	case MONO_CLASS_POINTER:
167 		return 0;
168 	default:
169 		g_assert_not_reached ();
170 		return 0;
171 	}
172 }
173 
174 void
mono_class_set_method_count(MonoClass * klass,guint32 count)175 mono_class_set_method_count (MonoClass *klass, guint32 count)
176 {
177 	switch (klass->class_kind) {
178 	case MONO_CLASS_DEF:
179 	case MONO_CLASS_GTD:
180 		((MonoClassDef*)klass)->method_count = count;
181 		break;
182 	case MONO_CLASS_GINST:
183 		break;
184 	case MONO_CLASS_GPARAM:
185 	case MONO_CLASS_POINTER:
186 		g_assert (count == 0);
187 		break;
188 	case MONO_CLASS_ARRAY:
189 		((MonoClassArray*)klass)->method_count = count;
190 		break;
191 	default:
192 		g_assert_not_reached ();
193 		break;
194 	}
195 }
196 
197 guint32
mono_class_get_field_count(MonoClass * klass)198 mono_class_get_field_count (MonoClass *klass)
199 {
200 	switch (klass->class_kind) {
201 	case MONO_CLASS_DEF:
202 	case MONO_CLASS_GTD:
203 		return ((MonoClassDef*)klass)->field_count;
204 	case MONO_CLASS_GINST:
205 		return mono_class_get_field_count (((MonoClassGenericInst*)klass)->generic_class->container_class);
206 	case MONO_CLASS_GPARAM:
207 	case MONO_CLASS_ARRAY:
208 	case MONO_CLASS_POINTER:
209 		return 0;
210 	default:
211 		g_assert_not_reached ();
212 		return 0;
213 	}
214 }
215 
216 void
mono_class_set_field_count(MonoClass * klass,guint32 count)217 mono_class_set_field_count (MonoClass *klass, guint32 count)
218 {
219 	switch (klass->class_kind) {
220 	case MONO_CLASS_DEF:
221 	case MONO_CLASS_GTD:
222 		((MonoClassDef*)klass)->field_count = count;
223 		break;
224 	case MONO_CLASS_GINST:
225 		break;
226 	case MONO_CLASS_GPARAM:
227 	case MONO_CLASS_ARRAY:
228 	case MONO_CLASS_POINTER:
229 		g_assert (count == 0);
230 		break;
231 	default:
232 		g_assert_not_reached ();
233 		break;
234 	}
235 }
236 
237 MonoMarshalType*
mono_class_get_marshal_info(MonoClass * klass)238 mono_class_get_marshal_info (MonoClass *klass)
239 {
240 	return mono_property_bag_get (&klass->infrequent_data, PROP_MARSHAL_INFO);
241 }
242 
243 void
mono_class_set_marshal_info(MonoClass * klass,MonoMarshalType * marshal_info)244 mono_class_set_marshal_info (MonoClass *klass, MonoMarshalType *marshal_info)
245 {
246 	marshal_info->head.tag = PROP_MARSHAL_INFO;
247 	mono_property_bag_add (&klass->infrequent_data, marshal_info);
248 }
249 
250 typedef struct {
251 	MonoPropertyBagItem head;
252 	guint32 value;
253 } Uint32Property;
254 
255 guint32
mono_class_get_ref_info_handle(MonoClass * klass)256 mono_class_get_ref_info_handle (MonoClass *klass)
257 {
258 	Uint32Property *prop = mono_property_bag_get (&klass->infrequent_data, PROP_REF_INFO_HANDLE);
259 	return prop ? prop->value : 0;
260 }
261 
262 guint32
mono_class_set_ref_info_handle(MonoClass * klass,guint32 value)263 mono_class_set_ref_info_handle (MonoClass *klass, guint32 value)
264 {
265 	if (!value) {
266 		Uint32Property *prop = mono_property_bag_get (&klass->infrequent_data, PROP_REF_INFO_HANDLE);
267 		if (prop)
268 			prop->value = 0;
269 		return 0;
270 	}
271 
272 	Uint32Property *prop = mono_class_alloc (klass, sizeof (Uint32Property));
273 	prop->head.tag = PROP_REF_INFO_HANDLE;
274 	prop->value = value;
275 	prop = mono_property_bag_add (&klass->infrequent_data, prop);
276 	return prop->value;
277 }
278 
279 typedef struct {
280 	MonoPropertyBagItem head;
281 	gpointer value;
282 } PointerProperty;
283 
284 static void
set_pointer_property(MonoClass * klass,InfrequentDataKind property,gpointer value)285 set_pointer_property (MonoClass *klass, InfrequentDataKind property, gpointer value)
286 {
287 	PointerProperty *prop = mono_class_alloc (klass, sizeof (PointerProperty));
288 	prop->head.tag = property;
289 	prop->value = value;
290 	mono_property_bag_add (&klass->infrequent_data, prop);
291 }
292 
293 static gpointer
get_pointer_property(MonoClass * klass,InfrequentDataKind property)294 get_pointer_property (MonoClass *klass, InfrequentDataKind property)
295 {
296 	PointerProperty *prop = (PointerProperty*)mono_property_bag_get (&klass->infrequent_data, property);
297 	return prop ? prop->value : NULL;
298 }
299 
300 MonoErrorBoxed*
mono_class_get_exception_data(MonoClass * klass)301 mono_class_get_exception_data (MonoClass *klass)
302 {
303 	return (MonoErrorBoxed*)get_pointer_property (klass, PROP_EXCEPTION_DATA);
304 }
305 
306 void
mono_class_set_exception_data(MonoClass * klass,MonoErrorBoxed * value)307 mono_class_set_exception_data (MonoClass *klass, MonoErrorBoxed *value)
308 {
309 	set_pointer_property (klass, PROP_EXCEPTION_DATA, value);
310 }
311 
312 GList*
mono_class_get_nested_classes_property(MonoClass * klass)313 mono_class_get_nested_classes_property (MonoClass *klass)
314 {
315 	return (GList*)get_pointer_property (klass, PROP_NESTED_CLASSES);
316 }
317 
318 void
mono_class_set_nested_classes_property(MonoClass * klass,GList * value)319 mono_class_set_nested_classes_property (MonoClass *klass, GList *value)
320 {
321 	set_pointer_property (klass, PROP_NESTED_CLASSES, value);
322 }
323 
324 MonoClassPropertyInfo*
mono_class_get_property_info(MonoClass * klass)325 mono_class_get_property_info (MonoClass *klass)
326 {
327 	return mono_property_bag_get (&klass->infrequent_data, PROP_PROPERTY_INFO);
328 }
329 
330 void
mono_class_set_property_info(MonoClass * klass,MonoClassPropertyInfo * info)331 mono_class_set_property_info (MonoClass *klass, MonoClassPropertyInfo *info)
332 {
333 	info->head.tag = PROP_PROPERTY_INFO;
334 	mono_property_bag_add (&klass->infrequent_data, info);
335 }
336 
337 MonoClassEventInfo*
mono_class_get_event_info(MonoClass * klass)338 mono_class_get_event_info (MonoClass *klass)
339 {
340 	return mono_property_bag_get (&klass->infrequent_data, PROP_EVENT_INFO);
341 }
342 
343 void
mono_class_set_event_info(MonoClass * klass,MonoClassEventInfo * info)344 mono_class_set_event_info (MonoClass *klass, MonoClassEventInfo *info)
345 {
346 	info->head.tag = PROP_EVENT_INFO;
347 	mono_property_bag_add (&klass->infrequent_data, info);
348 }
349 
350 MonoFieldDefaultValue*
mono_class_get_field_def_values(MonoClass * klass)351 mono_class_get_field_def_values (MonoClass *klass)
352 {
353 	return (MonoFieldDefaultValue*)get_pointer_property (klass, PROP_FIELD_DEF_VALUES);
354 }
355 
356 void
mono_class_set_field_def_values(MonoClass * klass,MonoFieldDefaultValue * values)357 mono_class_set_field_def_values (MonoClass *klass, MonoFieldDefaultValue *values)
358 {
359 	set_pointer_property (klass, PROP_FIELD_DEF_VALUES, values);
360 }
361 
362 guint32
mono_class_get_declsec_flags(MonoClass * klass)363 mono_class_get_declsec_flags (MonoClass *klass)
364 {
365 	Uint32Property *prop = mono_property_bag_get (&klass->infrequent_data, PROP_DECLSEC_FLAGS);
366 	return prop ? prop->value : 0;
367 }
368 
369 void
mono_class_set_declsec_flags(MonoClass * klass,guint32 value)370 mono_class_set_declsec_flags (MonoClass *klass, guint32 value)
371 {
372 	Uint32Property *prop = mono_class_alloc (klass, sizeof (Uint32Property));
373 	prop->head.tag = PROP_DECLSEC_FLAGS;
374 	prop->value = value;
375 	mono_property_bag_add (&klass->infrequent_data, prop);
376 }
377 
378 void
mono_class_set_is_com_object(MonoClass * klass)379 mono_class_set_is_com_object (MonoClass *klass)
380 {
381 #ifndef DISABLE_COM
382 	mono_loader_lock ();
383 	klass->is_com_object = 1;
384 	mono_loader_unlock ();
385 #endif
386 }
387 
388 MonoType*
mono_class_gtd_get_canonical_inst(MonoClass * klass)389 mono_class_gtd_get_canonical_inst (MonoClass *klass)
390 {
391 	g_assert (mono_class_is_gtd (klass));
392 	return &((MonoClassGtd*)klass)->canonical_inst;
393 }
394 
395 typedef struct {
396 	MonoPropertyBagItem head;
397 
398 	int nbits;
399 	gsize *bits;
400 } WeakBitmapData;
401 
402 void
mono_class_set_weak_bitmap(MonoClass * klass,int nbits,gsize * bits)403 mono_class_set_weak_bitmap (MonoClass *klass, int nbits, gsize *bits)
404 {
405 	WeakBitmapData *info = mono_class_alloc (klass, sizeof (WeakBitmapData));
406 	info->nbits = nbits;
407 	info->bits = bits;
408 
409 	info->head.tag = PROP_WEAK_BITMAP;
410 	mono_property_bag_add (&klass->infrequent_data, info);
411 }
412 
413 gsize*
mono_class_get_weak_bitmap(MonoClass * klass,int * nbits)414 mono_class_get_weak_bitmap (MonoClass *klass, int *nbits)
415 {
416 	WeakBitmapData *prop = mono_property_bag_get (&klass->infrequent_data, PROP_WEAK_BITMAP);
417 
418 	g_assert (prop);
419 	*nbits = prop->nbits;
420 	return prop->bits;
421 }
422