1 /**
2  * \file
3  * Class management for the Mono runtime
4  *
5  * Author:
6  *   Miguel de Icaza (miguel@ximian.com)
7  *
8  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
9  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
10  * Copyright 2012 Xamarin Inc (http://www.xamarin.com)
11  * Licensed under the MIT license. See LICENSE file in the project root for full license information.
12  */
13 #include <config.h>
14 #ifdef HAVE_ALLOCA_H
15 #include <alloca.h>
16 #endif
17 #include <glib.h>
18 #include <stdio.h>
19 #include <string.h>
20 #include <stdlib.h>
21 #include <mono/metadata/image.h>
22 #include <mono/metadata/image-internals.h>
23 #include <mono/metadata/assembly.h>
24 #include <mono/metadata/assembly-internals.h>
25 #include <mono/metadata/metadata.h>
26 #include <mono/metadata/metadata-internals.h>
27 #include <mono/metadata/profiler-private.h>
28 #include <mono/metadata/tabledefs.h>
29 #include <mono/metadata/tokentype.h>
30 #include <mono/metadata/class-internals.h>
31 #include <mono/metadata/object.h>
32 #include <mono/metadata/appdomain.h>
33 #include <mono/metadata/mono-endian.h>
34 #include <mono/metadata/debug-helpers.h>
35 #include <mono/metadata/reflection.h>
36 #include <mono/metadata/exception.h>
37 #include <mono/metadata/security-manager.h>
38 #include <mono/metadata/security-core-clr.h>
39 #include <mono/metadata/attrdefs.h>
40 #include <mono/metadata/gc-internals.h>
41 #include <mono/metadata/verify-internals.h>
42 #include <mono/metadata/mono-debug.h>
43 #include <mono/metadata/custom-attrs-internals.h>
44 #include <mono/utils/mono-counters.h>
45 #include <mono/utils/mono-string.h>
46 #include <mono/utils/mono-error-internals.h>
47 #include <mono/utils/mono-logger-internals.h>
48 #include <mono/utils/mono-memory-model.h>
49 #include <mono/utils/atomic.h>
50 #include <mono/utils/unlocked.h>
51 #include <mono/utils/bsearch.h>
52 #include <mono/utils/checked-build.h>
53 
54 MonoStats mono_stats;
55 
56 gboolean mono_print_vtable = FALSE;
57 gboolean mono_align_small_structs = FALSE;
58 
59 /* Statistics */
60 gint32 inflated_classes_size, inflated_methods_size;
61 gint32 classes_size;
62 gint32 class_def_count, class_gtd_count, class_ginst_count, class_gparam_count, class_array_count, class_pointer_count;
63 
64 /* Low level lock which protects data structures in this module */
65 static mono_mutex_t classes_mutex;
66 
67 /* Function supplied by the runtime to find classes by name using information from the AOT file */
68 static MonoGetClassFromName get_class_from_name = NULL;
69 
70 static MonoClass * mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error);
71 static gboolean mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res);
72 static gboolean can_access_type (MonoClass *access_klass, MonoClass *member_klass);
73 static MonoMethod* find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags);
74 static int generic_array_methods (MonoClass *klass);
75 static void setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos, GHashTable *cache);
76 
77 static MonoMethod* mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter);
78 static char* mono_assembly_name_from_token (MonoImage *image, guint32 type_token);
79 static void mono_field_resolve_type (MonoClassField *field, MonoError *error);
80 static guint32 mono_field_resolve_flags (MonoClassField *field);
81 static void mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup);
82 static void mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gklass);
83 
84 static gboolean mono_class_set_failure (MonoClass *klass, MonoErrorBoxed *boxed_error);
85 
86 static gboolean class_kind_may_contain_generic_instances (MonoTypeKind kind);
87 
88 
89 /*
90 We use gclass recording to allow recursive system f types to be referenced by a parent.
91 
92 Given the following type hierarchy:
93 
94 class TextBox : TextBoxBase<TextBox> {}
95 class TextBoxBase<T> : TextInput<TextBox> where T : TextBoxBase<T> {}
96 class TextInput<T> : Input<T> where T: TextInput<T> {}
97 class Input<T> {}
98 
99 The runtime tries to load TextBoxBase<>.
100 To load TextBoxBase<> to do so it must resolve the parent which is TextInput<TextBox>.
101 To instantiate TextInput<TextBox> it must resolve TextInput<> and TextBox.
102 To load TextBox it must resolve the parent which is TextBoxBase<TextBox>.
103 
104 At this point the runtime must instantiate TextBoxBase<TextBox>. Both types are partially loaded
105 at this point, iow, both are registered in the type map and both and a NULL parent. This means
106 that the resulting generic instance will have a NULL parent, which is wrong and will cause breakage.
107 
108 To fix that what we do is to record all generic instantes created while resolving the parent of
109 any generic type definition and, after resolved, correct the parent field if needed.
110 
111 */
112 static int record_gclass_instantiation;
113 static GSList *gclass_recorded_list;
114 typedef gboolean (*gclass_record_func) (MonoClass*, void*);
115 
116 /* This TLS variable points to a GSList of classes which have setup_fields () executing */
117 static MonoNativeTlsKey setup_fields_tls_id;
118 
119 static MonoNativeTlsKey init_pending_tls_id;
120 
121 static inline void
classes_lock(void)122 classes_lock (void)
123 {
124 	mono_locks_os_acquire (&classes_mutex, ClassesLock);
125 }
126 
127 static inline void
classes_unlock(void)128 classes_unlock (void)
129 {
130 	mono_locks_os_release (&classes_mutex, ClassesLock);
131 }
132 
133 /*
134  * LOCKING: loader lock must be held until pairing disable_gclass_recording is called.
135 */
136 static void
enable_gclass_recording(void)137 enable_gclass_recording (void)
138 {
139 	++record_gclass_instantiation;
140 }
141 
142 /*
143  * LOCKING: loader lock must be held since pairing enable_gclass_recording was called.
144 */
145 static void
disable_gclass_recording(gclass_record_func func,void * user_data)146 disable_gclass_recording (gclass_record_func func, void *user_data)
147 {
148 	GSList **head = &gclass_recorded_list;
149 
150 	g_assert (record_gclass_instantiation > 0);
151 	--record_gclass_instantiation;
152 
153 	while (*head) {
154 		GSList *node = *head;
155 		if (func ((MonoClass*)node->data, user_data)) {
156 			*head = node->next;
157 			g_slist_free_1 (node);
158 		} else {
159 			head = &node->next;
160 		}
161 	}
162 
163 	/* We automatically discard all recorded gclasses when disabled. */
164 	if (!record_gclass_instantiation && gclass_recorded_list) {
165 		g_slist_free (gclass_recorded_list);
166 		gclass_recorded_list = NULL;
167 	}
168 }
169 
170 /**
171  * mono_class_from_typeref:
172  * \param image a MonoImage
173  * \param type_token a TypeRef token
174  *
175  * Creates the \c MonoClass* structure representing the type defined by
176  * the typeref token valid inside \p image.
177  * \returns The \c MonoClass* representing the typeref token, or NULL if it could
178  * not be loaded.
179  */
180 MonoClass *
mono_class_from_typeref(MonoImage * image,guint32 type_token)181 mono_class_from_typeref (MonoImage *image, guint32 type_token)
182 {
183 	MonoError error;
184 	MonoClass *klass = mono_class_from_typeref_checked (image, type_token, &error);
185 	g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
186 	return klass;
187 }
188 
189 /**
190  * mono_class_from_typeref_checked:
191  * \param image a MonoImage
192  * \param type_token a TypeRef token
193  * \param error error return code, if any.
194  *
195  * Creates the \c MonoClass* structure representing the type defined by
196  * the typeref token valid inside \p image.
197  *
198  * \returns The \c MonoClass* representing the typeref token, NULL if it could
199  * not be loaded with the \p error value filled with the information about the
200  * error.
201  */
202 MonoClass *
mono_class_from_typeref_checked(MonoImage * image,guint32 type_token,MonoError * error)203 mono_class_from_typeref_checked (MonoImage *image, guint32 type_token, MonoError *error)
204 {
205 	guint32 cols [MONO_TYPEREF_SIZE];
206 	MonoTableInfo  *t = &image->tables [MONO_TABLE_TYPEREF];
207 	guint32 idx;
208 	const char *name, *nspace;
209 	MonoClass *res = NULL;
210 	MonoImage *module;
211 
212 	error_init (error);
213 
214 	if (!mono_verifier_verify_typeref_row (image, (type_token & 0xffffff) - 1, error))
215 		return NULL;
216 
217 	mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
218 
219 	name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
220 	nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
221 
222 	idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
223 	switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
224 	case MONO_RESOLUTION_SCOPE_MODULE:
225 		/*
226 		LAMESPEC The spec says that a null module resolution scope should go through the exported type table.
227 		This is not the observed behavior of existing implementations.
228 		The defacto behavior is that it's just a typedef in disguise.
229 		*/
230 		/* a typedef in disguise */
231 		res = mono_class_from_name_checked (image, nspace, name, error);
232 		goto done;
233 
234 	case MONO_RESOLUTION_SCOPE_MODULEREF:
235 		module = mono_image_load_module_checked (image, idx, error);
236 		if (module)
237 			res = mono_class_from_name_checked (module, nspace, name, error);
238 		goto done;
239 
240 	case MONO_RESOLUTION_SCOPE_TYPEREF: {
241 		MonoClass *enclosing;
242 		GList *tmp;
243 
244 		if (idx == mono_metadata_token_index (type_token)) {
245 			mono_error_set_bad_image (error, image, "Image with self-referencing typeref token %08x.", type_token);
246 			return NULL;
247 		}
248 
249 		enclosing = mono_class_from_typeref_checked (image, MONO_TOKEN_TYPE_REF | idx, error);
250 		return_val_if_nok (error, NULL);
251 
252 		GList *nested_classes = mono_class_get_nested_classes_property (enclosing);
253 		if (enclosing->nested_classes_inited && nested_classes) {
254 			/* Micro-optimization: don't scan the metadata tables if enclosing is already inited */
255 			for (tmp = nested_classes; tmp; tmp = tmp->next) {
256 				res = (MonoClass *)tmp->data;
257 				if (strcmp (res->name, name) == 0)
258 					return res;
259 			}
260 		} else {
261 			/* Don't call mono_class_init as we might've been called by it recursively */
262 			int i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, 1);
263 			while (i) {
264 				guint32 class_nested = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, MONO_NESTED_CLASS_NESTED);
265 				guint32 string_offset = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_TYPEDEF], class_nested - 1, MONO_TYPEDEF_NAME);
266 				const char *nname = mono_metadata_string_heap (enclosing->image, string_offset);
267 
268 				if (strcmp (nname, name) == 0)
269 					return mono_class_create_from_typedef (enclosing->image, MONO_TOKEN_TYPE_DEF | class_nested, error);
270 
271 				i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, i + 1);
272 			}
273 		}
274 		g_warning ("TypeRef ResolutionScope not yet handled (%d) for %s.%s in image %s", idx, nspace, name, image->name);
275 		goto done;
276 	}
277 	case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
278 		break;
279 	}
280 
281 	if (idx > image->tables [MONO_TABLE_ASSEMBLYREF].rows) {
282 		mono_error_set_bad_image (error, image, "Image with invalid assemblyref token %08x.", idx);
283 		return NULL;
284 	}
285 
286 	if (!image->references || !image->references [idx - 1])
287 		mono_assembly_load_reference (image, idx - 1);
288 	g_assert (image->references [idx - 1]);
289 
290 	/* If the assembly did not load, register this as a type load exception */
291 	if (image->references [idx - 1] == REFERENCE_MISSING){
292 		MonoAssemblyName aname;
293 		char *human_name;
294 
295 		mono_assembly_get_assemblyref (image, idx - 1, &aname);
296 		human_name = mono_stringify_assembly_name (&aname);
297 		mono_error_set_assembly_load_simple (error, human_name, image->assembly ? image->assembly->ref_only : FALSE);
298 		return NULL;
299 	}
300 
301 	res = mono_class_from_name_checked (image->references [idx - 1]->image, nspace, name, error);
302 
303 done:
304 	/* Generic case, should be avoided for when a better error is possible. */
305 	if (!res && mono_error_ok (error)) {
306 		char *name = mono_class_name_from_token (image, type_token);
307 		char *assembly = mono_assembly_name_from_token (image, type_token);
308 		mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x (from typeref, class/assembly %s, %s)", type_token, name, assembly);
309 	}
310 	return res;
311 }
312 
313 
314 static void *
mono_image_memdup(MonoImage * image,void * data,guint size)315 mono_image_memdup (MonoImage *image, void *data, guint size)
316 {
317 	void *res = mono_image_alloc (image, size);
318 	memcpy (res, data, size);
319 	return res;
320 }
321 
322 /* Copy everything mono_metadata_free_array free. */
323 MonoArrayType *
mono_dup_array_type(MonoImage * image,MonoArrayType * a)324 mono_dup_array_type (MonoImage *image, MonoArrayType *a)
325 {
326 	if (image) {
327 		a = (MonoArrayType *)mono_image_memdup (image, a, sizeof (MonoArrayType));
328 		if (a->sizes)
329 			a->sizes = (int *)mono_image_memdup (image, a->sizes, a->numsizes * sizeof (int));
330 		if (a->lobounds)
331 			a->lobounds = (int *)mono_image_memdup (image, a->lobounds, a->numlobounds * sizeof (int));
332 	} else {
333 		a = (MonoArrayType *)g_memdup (a, sizeof (MonoArrayType));
334 		if (a->sizes)
335 			a->sizes = (int *)g_memdup (a->sizes, a->numsizes * sizeof (int));
336 		if (a->lobounds)
337 			a->lobounds = (int *)g_memdup (a->lobounds, a->numlobounds * sizeof (int));
338 	}
339 	return a;
340 }
341 
342 /* Copy everything mono_metadata_free_method_signature free. */
343 MonoMethodSignature*
mono_metadata_signature_deep_dup(MonoImage * image,MonoMethodSignature * sig)344 mono_metadata_signature_deep_dup (MonoImage *image, MonoMethodSignature *sig)
345 {
346 	int i;
347 
348 	sig = mono_metadata_signature_dup_full (image, sig);
349 
350 	sig->ret = mono_metadata_type_dup (image, sig->ret);
351 	for (i = 0; i < sig->param_count; ++i)
352 		sig->params [i] = mono_metadata_type_dup (image, sig->params [i]);
353 
354 	return sig;
355 }
356 
357 static void
_mono_type_get_assembly_name(MonoClass * klass,GString * str)358 _mono_type_get_assembly_name (MonoClass *klass, GString *str)
359 {
360 	MonoAssembly *ta = klass->image->assembly;
361 	char *name;
362 
363 	name = mono_stringify_assembly_name (&ta->aname);
364 	g_string_append_printf (str, ", %s", name);
365 	g_free (name);
366 }
367 
368 static inline void
mono_type_name_check_byref(MonoType * type,GString * str)369 mono_type_name_check_byref (MonoType *type, GString *str)
370 {
371 	if (type->byref)
372 		g_string_append_c (str, '&');
373 }
374 
375 /**
376  * mono_identifier_escape_type_name_chars:
377  * \param str a destination string
378  * \param identifier an IDENTIFIER in internal form
379  *
380  * \returns \p str
381  *
382  * The displayed form of the identifier is appended to str.
383  *
384  * The displayed form of an identifier has the characters ,+&*[]\
385  * that have special meaning in type names escaped with a preceeding
386  * backslash (\) character.
387  */
388 static GString*
mono_identifier_escape_type_name_chars(GString * str,const char * identifier)389 mono_identifier_escape_type_name_chars (GString* str, const char* identifier)
390 {
391 	if (!identifier)
392 		return str;
393 
394 	size_t n = str->len;
395 	// reserve space for common case: there will be no escaped characters.
396 	g_string_set_size(str, n + strlen(identifier));
397 	g_string_set_size(str, n);
398 
399 	for (const char* s = identifier; *s != 0 ; s++) {
400 		switch (*s) {
401 		case ',':
402 		case '+':
403 		case '&':
404 		case '*':
405 		case '[':
406 		case ']':
407 		case '\\':
408 			g_string_append_c (str, '\\');
409 			g_string_append_c (str, *s);
410 			break;
411 		default:
412 			g_string_append_c (str, *s);
413 			break;
414 		}
415 	}
416 	return str;
417 }
418 
419 static void
mono_type_get_name_recurse(MonoType * type,GString * str,gboolean is_recursed,MonoTypeNameFormat format)420 mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed,
421 			    MonoTypeNameFormat format)
422 {
423 	MonoClass *klass;
424 
425 	switch (type->type) {
426 	case MONO_TYPE_ARRAY: {
427 		int i, rank = type->data.array->rank;
428 		MonoTypeNameFormat nested_format;
429 
430 		nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
431 			MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
432 
433 		mono_type_get_name_recurse (
434 			&type->data.array->eklass->byval_arg, str, FALSE, nested_format);
435 		g_string_append_c (str, '[');
436 		if (rank == 1)
437 			g_string_append_c (str, '*');
438 		for (i = 1; i < rank; i++)
439 			g_string_append_c (str, ',');
440 		g_string_append_c (str, ']');
441 
442 		mono_type_name_check_byref (type, str);
443 
444 		if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
445 			_mono_type_get_assembly_name (type->data.array->eklass, str);
446 		break;
447 	}
448 	case MONO_TYPE_SZARRAY: {
449 		MonoTypeNameFormat nested_format;
450 
451 		nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
452 			MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
453 
454 		mono_type_get_name_recurse (
455 			&type->data.klass->byval_arg, str, FALSE, nested_format);
456 		g_string_append (str, "[]");
457 
458 		mono_type_name_check_byref (type, str);
459 
460 		if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
461 			_mono_type_get_assembly_name (type->data.klass, str);
462 		break;
463 	}
464 	case MONO_TYPE_PTR: {
465 		MonoTypeNameFormat nested_format;
466 
467 		nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
468 			MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
469 
470 		mono_type_get_name_recurse (
471 			type->data.type, str, FALSE, nested_format);
472 		g_string_append_c (str, '*');
473 
474 		mono_type_name_check_byref (type, str);
475 
476 		if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
477 			_mono_type_get_assembly_name (mono_class_from_mono_type (type->data.type), str);
478 		break;
479 	}
480 	case MONO_TYPE_VAR:
481 	case MONO_TYPE_MVAR:
482 		if (!mono_generic_param_info (type->data.generic_param))
483 			g_string_append_printf (str, "%s%d", type->type == MONO_TYPE_VAR ? "!" : "!!", type->data.generic_param->num);
484 		else
485 			g_string_append (str, mono_generic_param_info (type->data.generic_param)->name);
486 
487 		mono_type_name_check_byref (type, str);
488 
489 		break;
490 	default:
491 		klass = mono_class_from_mono_type (type);
492 		if (klass->nested_in) {
493 			mono_type_get_name_recurse (
494 				&klass->nested_in->byval_arg, str, TRUE, format);
495 			if (format == MONO_TYPE_NAME_FORMAT_IL)
496 				g_string_append_c (str, '.');
497 			else
498 				g_string_append_c (str, '+');
499 		} else if (*klass->name_space) {
500 			if (format == MONO_TYPE_NAME_FORMAT_IL)
501 				g_string_append (str, klass->name_space);
502 			else
503 				mono_identifier_escape_type_name_chars (str, klass->name_space);
504 			g_string_append_c (str, '.');
505 		}
506 		if (format == MONO_TYPE_NAME_FORMAT_IL) {
507 			char *s = strchr (klass->name, '`');
508 			int len = s ? s - klass->name : strlen (klass->name);
509 			g_string_append_len (str, klass->name, len);
510 		} else {
511 			mono_identifier_escape_type_name_chars (str, klass->name);
512 		}
513 		if (is_recursed)
514 			break;
515 		if (mono_class_is_ginst (klass)) {
516 			MonoGenericClass *gclass = mono_class_get_generic_class (klass);
517 			MonoGenericInst *inst = gclass->context.class_inst;
518 			MonoTypeNameFormat nested_format;
519 			int i;
520 
521 			nested_format = format == MONO_TYPE_NAME_FORMAT_FULL_NAME ?
522 				MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED : format;
523 
524 			if (format == MONO_TYPE_NAME_FORMAT_IL)
525 				g_string_append_c (str, '<');
526 			else
527 				g_string_append_c (str, '[');
528 			for (i = 0; i < inst->type_argc; i++) {
529 				MonoType *t = inst->type_argv [i];
530 
531 				if (i)
532 					g_string_append_c (str, ',');
533 				if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
534 				    (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
535 					g_string_append_c (str, '[');
536 				mono_type_get_name_recurse (inst->type_argv [i], str, FALSE, nested_format);
537 				if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
538 				    (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
539 					g_string_append_c (str, ']');
540 			}
541 			if (format == MONO_TYPE_NAME_FORMAT_IL)
542 				g_string_append_c (str, '>');
543 			else
544 				g_string_append_c (str, ']');
545 		} else if (mono_class_is_gtd (klass) &&
546 			   (format != MONO_TYPE_NAME_FORMAT_FULL_NAME) &&
547 			   (format != MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)) {
548 			int i;
549 
550 			if (format == MONO_TYPE_NAME_FORMAT_IL)
551 				g_string_append_c (str, '<');
552 			else
553 				g_string_append_c (str, '[');
554 			for (i = 0; i < mono_class_get_generic_container (klass)->type_argc; i++) {
555 				if (i)
556 					g_string_append_c (str, ',');
557 				g_string_append (str, mono_generic_container_get_param_info (mono_class_get_generic_container (klass), i)->name);
558 			}
559 			if (format == MONO_TYPE_NAME_FORMAT_IL)
560 				g_string_append_c (str, '>');
561 			else
562 				g_string_append_c (str, ']');
563 		}
564 
565 		mono_type_name_check_byref (type, str);
566 
567 		if ((format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
568 		    (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
569 			_mono_type_get_assembly_name (klass, str);
570 		break;
571 	}
572 }
573 
574 /**
575  * mono_type_get_name_full:
576  * \param type a type
577  * \param format the format for the return string.
578  *
579  *
580  * \returns The string representation in a number of formats:
581  *
582  * if \p format is \c MONO_TYPE_NAME_FORMAT_REFLECTION, the return string is
583  * returned in the format required by \c System.Reflection, this is the
584  * inverse of mono_reflection_parse_type().
585  *
586  * if \p format is \c MONO_TYPE_NAME_FORMAT_IL, it returns a syntax that can
587  * be used by the IL assembler.
588  *
589  * if \p format is \c MONO_TYPE_NAME_FORMAT_FULL_NAME
590  *
591  * if \p format is \c MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
592  */
593 char*
mono_type_get_name_full(MonoType * type,MonoTypeNameFormat format)594 mono_type_get_name_full (MonoType *type, MonoTypeNameFormat format)
595 {
596 	GString* result;
597 
598 	result = g_string_new ("");
599 
600 	mono_type_get_name_recurse (type, result, FALSE, format);
601 
602 	return g_string_free (result, FALSE);
603 }
604 
605 /**
606  * mono_type_get_full_name:
607  * \param class a class
608  *
609  * \returns The string representation for type as required by System.Reflection.
610  * The inverse of mono_reflection_parse_type().
611  */
612 char *
mono_type_get_full_name(MonoClass * klass)613 mono_type_get_full_name (MonoClass *klass)
614 {
615 	return mono_type_get_name_full (mono_class_get_type (klass), MONO_TYPE_NAME_FORMAT_REFLECTION);
616 }
617 
618 /**
619  * mono_type_get_name:
620  * \param type a type
621  * \returns The string representation for type as it would be represented in IL code.
622  */
623 char*
mono_type_get_name(MonoType * type)624 mono_type_get_name (MonoType *type)
625 {
626 	return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_IL);
627 }
628 
629 /**
630  * mono_type_get_underlying_type:
631  * \param type a type
632  * \returns The \c MonoType for the underlying integer type if \p type
633  * is an enum and byref is false, otherwise the type itself.
634  */
635 MonoType*
mono_type_get_underlying_type(MonoType * type)636 mono_type_get_underlying_type (MonoType *type)
637 {
638 	if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype && !type->byref)
639 		return mono_class_enum_basetype (type->data.klass);
640 	if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype && !type->byref)
641 		return mono_class_enum_basetype (type->data.generic_class->container_class);
642 	return type;
643 }
644 
645 /**
646  * mono_class_is_open_constructed_type:
647  * \param type a type
648  *
649  * \returns TRUE if type represents a generics open constructed type.
650  * IOW, not all type parameters required for the instantiation have
651  * been provided or it's a generic type definition.
652  *
653  * An open constructed type means it's a non realizable type. Not to
654  * be mixed up with an abstract type - we can't cast or dispatch to
655  * an open type, for example.
656  */
657 gboolean
mono_class_is_open_constructed_type(MonoType * t)658 mono_class_is_open_constructed_type (MonoType *t)
659 {
660 	switch (t->type) {
661 	case MONO_TYPE_VAR:
662 	case MONO_TYPE_MVAR:
663 		return TRUE;
664 	case MONO_TYPE_SZARRAY:
665 		return mono_class_is_open_constructed_type (&t->data.klass->byval_arg);
666 	case MONO_TYPE_ARRAY:
667 		return mono_class_is_open_constructed_type (&t->data.array->eklass->byval_arg);
668 	case MONO_TYPE_PTR:
669 		return mono_class_is_open_constructed_type (t->data.type);
670 	case MONO_TYPE_GENERICINST:
671 		return t->data.generic_class->context.class_inst->is_open;
672 	case MONO_TYPE_CLASS:
673 	case MONO_TYPE_VALUETYPE:
674 		return mono_class_is_gtd (t->data.klass);
675 	default:
676 		return FALSE;
677 	}
678 }
679 
680 /*
681 This is a simple function to catch the most common bad instances of generic types.
682 Specially those that might lead to further failures in the runtime.
683 */
684 static gboolean
is_valid_generic_argument(MonoType * type)685 is_valid_generic_argument (MonoType *type)
686 {
687 	switch (type->type) {
688 	case MONO_TYPE_VOID:
689 	//case MONO_TYPE_TYPEDBYREF:
690 		return FALSE;
691 	default:
692 		return TRUE;
693 	}
694 }
695 
696 static MonoType*
inflate_generic_type(MonoImage * image,MonoType * type,MonoGenericContext * context,MonoError * error)697 inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
698 {
699 	error_init (error);
700 
701 	switch (type->type) {
702 	case MONO_TYPE_MVAR: {
703 		MonoType *nt;
704 		int num = mono_type_get_generic_param_num (type);
705 		MonoGenericInst *inst = context->method_inst;
706 		if (!inst)
707 			return NULL;
708 		if (num >= inst->type_argc) {
709 			MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
710 			mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded in this context with %d instantiations",
711 				num, info ? info->name : "", inst->type_argc);
712 			return NULL;
713 		}
714 
715 		if (!is_valid_generic_argument (inst->type_argv [num])) {
716 			MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
717 			mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded with type 0x%x",
718 				num, info ? info->name : "", inst->type_argv [num]->type);
719 			return NULL;
720 		}
721 		/*
722 		 * Note that the VAR/MVAR cases are different from the rest.  The other cases duplicate @type,
723 		 * while the VAR/MVAR duplicates a type from the context.  So, we need to ensure that the
724 		 * ->byref and ->attrs from @type are propagated to the returned type.
725 		 */
726 		nt = mono_metadata_type_dup (image, inst->type_argv [num]);
727 		nt->byref = type->byref;
728 		nt->attrs = type->attrs;
729 		return nt;
730 	}
731 	case MONO_TYPE_VAR: {
732 		MonoType *nt;
733 		int num = mono_type_get_generic_param_num (type);
734 		MonoGenericInst *inst = context->class_inst;
735 		if (!inst)
736 			return NULL;
737 		if (num >= inst->type_argc) {
738 			MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
739 			mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded in this context with %d instantiations",
740 				num, info ? info->name : "", inst->type_argc);
741 			return NULL;
742 		}
743 		if (!is_valid_generic_argument (inst->type_argv [num])) {
744 			MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
745 			mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded with type 0x%x",
746 				num, info ? info->name : "", inst->type_argv [num]->type);
747 			return NULL;
748 		}
749 		nt = mono_metadata_type_dup (image, inst->type_argv [num]);
750 		nt->byref = type->byref;
751 		nt->attrs = type->attrs;
752 		return nt;
753 	}
754 	case MONO_TYPE_SZARRAY: {
755 		MonoClass *eclass = type->data.klass;
756 		MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
757 		if (!inflated || !mono_error_ok (error))
758 			return NULL;
759 		nt = mono_metadata_type_dup (image, type);
760 		nt->data.klass = mono_class_from_mono_type (inflated);
761 		mono_metadata_free_type (inflated);
762 		return nt;
763 	}
764 	case MONO_TYPE_ARRAY: {
765 		MonoClass *eclass = type->data.array->eklass;
766 		MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
767 		if (!inflated || !mono_error_ok (error))
768 			return NULL;
769 		nt = mono_metadata_type_dup (image, type);
770 		nt->data.array->eklass = mono_class_from_mono_type (inflated);
771 		mono_metadata_free_type (inflated);
772 		return nt;
773 	}
774 	case MONO_TYPE_GENERICINST: {
775 		MonoGenericClass *gclass = type->data.generic_class;
776 		MonoGenericInst *inst;
777 		MonoType *nt;
778 		if (!gclass->context.class_inst->is_open)
779 			return NULL;
780 
781 		inst = mono_metadata_inflate_generic_inst (gclass->context.class_inst, context, error);
782 		return_val_if_nok (error, NULL);
783 
784 		if (inst != gclass->context.class_inst)
785 			gclass = mono_metadata_lookup_generic_class (gclass->container_class, inst, gclass->is_dynamic);
786 
787 		if (gclass == type->data.generic_class)
788 			return NULL;
789 
790 		nt = mono_metadata_type_dup (image, type);
791 		nt->data.generic_class = gclass;
792 		return nt;
793 	}
794 	case MONO_TYPE_CLASS:
795 	case MONO_TYPE_VALUETYPE: {
796 		MonoClass *klass = type->data.klass;
797 		MonoGenericContainer *container = mono_class_try_get_generic_container (klass);
798 		MonoGenericInst *inst;
799 		MonoGenericClass *gclass = NULL;
800 		MonoType *nt;
801 
802 		if (!container)
803 			return NULL;
804 
805 		/* We can't use context->class_inst directly, since it can have more elements */
806 		inst = mono_metadata_inflate_generic_inst (container->context.class_inst, context, error);
807 		return_val_if_nok (error, NULL);
808 
809 		if (inst == container->context.class_inst)
810 			return NULL;
811 
812 		gclass = mono_metadata_lookup_generic_class (klass, inst, image_is_dynamic (klass->image));
813 
814 		nt = mono_metadata_type_dup (image, type);
815 		nt->type = MONO_TYPE_GENERICINST;
816 		nt->data.generic_class = gclass;
817 		return nt;
818 	}
819 	default:
820 		return NULL;
821 	}
822 	return NULL;
823 }
824 
825 MonoGenericContext *
mono_generic_class_get_context(MonoGenericClass * gclass)826 mono_generic_class_get_context (MonoGenericClass *gclass)
827 {
828 	return &gclass->context;
829 }
830 
831 MonoGenericContext *
mono_class_get_context(MonoClass * klass)832 mono_class_get_context (MonoClass *klass)
833 {
834 	MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
835 	return gklass ? mono_generic_class_get_context (gklass) : NULL;
836 }
837 
838 /*
839  * mono_class_inflate_generic_type_with_mempool:
840  * @mempool: a mempool
841  * @type: a type
842  * @context: a generics context
843  * @error: error context
844  *
845  * The same as mono_class_inflate_generic_type, but allocates the MonoType
846  * from mempool if it is non-NULL.  If it is NULL, the MonoType is
847  * allocated on the heap and is owned by the caller.
848  * The returned type can potentially be the same as TYPE, so it should not be
849  * modified by the caller, and it should be freed using mono_metadata_free_type ().
850  */
851 MonoType*
mono_class_inflate_generic_type_with_mempool(MonoImage * image,MonoType * type,MonoGenericContext * context,MonoError * error)852 mono_class_inflate_generic_type_with_mempool (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
853 {
854 	MonoType *inflated = NULL;
855 	error_init (error);
856 
857 	if (context)
858 		inflated = inflate_generic_type (image, type, context, error);
859 	return_val_if_nok (error, NULL);
860 
861 	if (!inflated) {
862 		MonoType *shared = mono_metadata_get_shared_type (type);
863 
864 		if (shared) {
865 			return shared;
866 		} else {
867 			return mono_metadata_type_dup (image, type);
868 		}
869 	}
870 
871 	UnlockedIncrement (&mono_stats.inflated_type_count);
872 	return inflated;
873 }
874 
875 /**
876  * mono_class_inflate_generic_type:
877  * \param type a type
878  * \param context a generics context
879  * \deprecated Please use \c mono_class_inflate_generic_type_checked instead
880  *
881  * If \p type is a generic type and \p context is not NULL, instantiate it using the
882  * generics context \p context.
883  *
884  * \returns The instantiated type or a copy of \p type. The returned \c MonoType is allocated
885  * on the heap and is owned by the caller. Returns NULL on error.
886  */
887 MonoType*
mono_class_inflate_generic_type(MonoType * type,MonoGenericContext * context)888 mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
889 {
890 	MonoError error;
891 	MonoType *result;
892 	result = mono_class_inflate_generic_type_checked (type, context, &error);
893 	mono_error_cleanup (&error);
894 	return result;
895 }
896 
897 /*
898  * mono_class_inflate_generic_type:
899  * @type: a type
900  * @context: a generics context
901  * @error: error context to use
902  *
903  * If @type is a generic type and @context is not NULL, instantiate it using the
904  * generics context @context.
905  *
906  * Returns: The instantiated type or a copy of @type. The returned MonoType is allocated
907  * on the heap and is owned by the caller.
908  */
909 MonoType*
mono_class_inflate_generic_type_checked(MonoType * type,MonoGenericContext * context,MonoError * error)910 mono_class_inflate_generic_type_checked (MonoType *type, MonoGenericContext *context, MonoError *error)
911 {
912 	return mono_class_inflate_generic_type_with_mempool (NULL, type, context, error);
913 }
914 
915 /*
916  * mono_class_inflate_generic_type_no_copy:
917  *
918  *   Same as inflate_generic_type_with_mempool, but return TYPE if no inflation
919  * was done.
920  */
921 static MonoType*
mono_class_inflate_generic_type_no_copy(MonoImage * image,MonoType * type,MonoGenericContext * context,MonoError * error)922 mono_class_inflate_generic_type_no_copy (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
923 {
924 	MonoType *inflated = NULL;
925 
926 	error_init (error);
927 	if (context) {
928 		inflated = inflate_generic_type (image, type, context, error);
929 		return_val_if_nok (error, NULL);
930 	}
931 
932 	if (!inflated)
933 		return type;
934 
935 	UnlockedIncrement (&mono_stats.inflated_type_count);
936 	return inflated;
937 }
938 
939 /*
940  * mono_class_inflate_generic_class:
941  *
942  *   Inflate the class @gklass with @context. Set @error on failure.
943  */
944 MonoClass*
mono_class_inflate_generic_class_checked(MonoClass * gklass,MonoGenericContext * context,MonoError * error)945 mono_class_inflate_generic_class_checked (MonoClass *gklass, MonoGenericContext *context, MonoError *error)
946 {
947 	MonoClass *res;
948 	MonoType *inflated;
949 
950 	inflated = mono_class_inflate_generic_type_checked (&gklass->byval_arg, context, error);
951 	return_val_if_nok (error, NULL);
952 
953 	res = mono_class_from_mono_type (inflated);
954 	mono_metadata_free_type (inflated);
955 
956 	return res;
957 }
958 
959 static MonoGenericContext
inflate_generic_context(MonoGenericContext * context,MonoGenericContext * inflate_with,MonoError * error)960 inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with, MonoError *error)
961 {
962 	MonoGenericInst *class_inst = NULL;
963 	MonoGenericInst *method_inst = NULL;
964 	MonoGenericContext res = { NULL, NULL };
965 
966 	error_init (error);
967 
968 	if (context->class_inst) {
969 		class_inst = mono_metadata_inflate_generic_inst (context->class_inst, inflate_with, error);
970 		if (!mono_error_ok (error))
971 			goto fail;
972 	}
973 
974 	if (context->method_inst) {
975 		method_inst = mono_metadata_inflate_generic_inst (context->method_inst, inflate_with, error);
976 		if (!mono_error_ok (error))
977 			goto fail;
978 	}
979 
980 	res.class_inst = class_inst;
981 	res.method_inst = method_inst;
982 fail:
983 	return res;
984 }
985 
986 /**
987  * mono_class_inflate_generic_method:
988  * \param method a generic method
989  * \param context a generics context
990  *
991  * Instantiate the generic method \p method using the generics context \p context.
992  *
993  * \returns The new instantiated method
994  */
995 MonoMethod *
mono_class_inflate_generic_method(MonoMethod * method,MonoGenericContext * context)996 mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context)
997 {
998 	return mono_class_inflate_generic_method_full (method, NULL, context);
999 }
1000 
1001 MonoMethod *
mono_class_inflate_generic_method_checked(MonoMethod * method,MonoGenericContext * context,MonoError * error)1002 mono_class_inflate_generic_method_checked (MonoMethod *method, MonoGenericContext *context, MonoError *error)
1003 {
1004 	return mono_class_inflate_generic_method_full_checked (method, NULL, context, error);
1005 }
1006 
1007 /**
1008  * mono_class_inflate_generic_method_full:
1009  *
1010  * Instantiate method \p method with the generic context \p context.
1011  * BEWARE: All non-trivial fields are invalid, including klass, signature, and header.
1012  *         Use mono_method_signature() and mono_method_get_header() to get the correct values.
1013  */
1014 MonoMethod*
mono_class_inflate_generic_method_full(MonoMethod * method,MonoClass * klass_hint,MonoGenericContext * context)1015 mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context)
1016 {
1017 	MonoError error;
1018 	MonoMethod *res = mono_class_inflate_generic_method_full_checked (method, klass_hint, context, &error);
1019 	if (!mono_error_ok (&error))
1020 		/*FIXME do proper error handling - on this case, kill this function. */
1021 		g_error ("Could not inflate generic method due to %s", mono_error_get_message (&error));
1022 
1023 	return res;
1024 }
1025 
1026 /**
1027  * mono_class_inflate_generic_method_full_checked:
1028  * Same as mono_class_inflate_generic_method_full but return failure using \p error.
1029  */
1030 MonoMethod*
mono_class_inflate_generic_method_full_checked(MonoMethod * method,MonoClass * klass_hint,MonoGenericContext * context,MonoError * error)1031 mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context, MonoError *error)
1032 {
1033 	MonoMethod *result;
1034 	MonoMethodInflated *iresult, *cached;
1035 	MonoMethodSignature *sig;
1036 	MonoGenericContext tmp_context;
1037 
1038 	error_init (error);
1039 
1040 	/* The `method' has already been instantiated before => we need to peel out the instantiation and create a new context */
1041 	while (method->is_inflated) {
1042 		MonoGenericContext *method_context = mono_method_get_context (method);
1043 		MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1044 
1045 		tmp_context = inflate_generic_context (method_context, context, error);
1046 		return_val_if_nok (error, NULL);
1047 
1048 		context = &tmp_context;
1049 
1050 		if (mono_metadata_generic_context_equal (method_context, context))
1051 			return method;
1052 
1053 		method = imethod->declaring;
1054 	}
1055 
1056 	/*
1057 	 * A method only needs to be inflated if the context has argument for which it is
1058 	 * parametric. Eg:
1059 	 *
1060 	 * class Foo<T> { void Bar(); } - doesn't need to be inflated if only mvars' are supplied
1061 	 * class Foo { void Bar<T> (); } - doesn't need to be if only vars' are supplied
1062 	 *
1063 	 */
1064 	if (!((method->is_generic && context->method_inst) ||
1065 		(mono_class_is_gtd (method->klass) && context->class_inst)))
1066 		return method;
1067 
1068 	iresult = g_new0 (MonoMethodInflated, 1);
1069 	iresult->context = *context;
1070 	iresult->declaring = method;
1071 
1072 	if (!context->method_inst && method->is_generic)
1073 		iresult->context.method_inst = mono_method_get_generic_container (method)->context.method_inst;
1074 
1075 	if (!context->class_inst) {
1076 		g_assert (!mono_class_is_ginst (iresult->declaring->klass));
1077 		if (mono_class_is_gtd (iresult->declaring->klass))
1078 			iresult->context.class_inst = mono_class_get_generic_container (iresult->declaring->klass)->context.class_inst;
1079 	}
1080 	/* This can happen with some callers like mono_object_get_virtual_method () */
1081 	if (!mono_class_is_gtd (iresult->declaring->klass) && !mono_class_is_ginst (iresult->declaring->klass))
1082 		iresult->context.class_inst = NULL;
1083 
1084 	MonoImageSet *set = mono_metadata_get_image_set_for_method (iresult);
1085 
1086 	// check cache
1087 	mono_image_set_lock (set);
1088 	cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1089 	mono_image_set_unlock (set);
1090 
1091 	if (cached) {
1092 		g_free (iresult);
1093 		return (MonoMethod*)cached;
1094 	}
1095 
1096 	UnlockedIncrement (&mono_stats.inflated_method_count);
1097 
1098 	UnlockedAdd (&inflated_methods_size,  sizeof (MonoMethodInflated));
1099 
1100 	sig = mono_method_signature (method);
1101 	if (!sig) {
1102 		char *name = mono_type_get_full_name (method->klass);
1103 		mono_error_set_bad_image (error, method->klass->image, "Could not resolve signature of method %s:%s", name, method->name);
1104 		g_free (name);
1105 		goto fail;
1106 	}
1107 
1108 	if (sig->pinvoke) {
1109 		memcpy (&iresult->method.pinvoke, method, sizeof (MonoMethodPInvoke));
1110 	} else {
1111 		memcpy (&iresult->method.method, method, sizeof (MonoMethod));
1112 	}
1113 
1114 	result = (MonoMethod *) iresult;
1115 	result->is_inflated = TRUE;
1116 	result->is_generic = FALSE;
1117 	result->sre_method = FALSE;
1118 	result->signature = NULL;
1119 
1120 	if (method->wrapper_type) {
1121 		MonoMethodWrapper *mw = (MonoMethodWrapper*)method;
1122 		MonoMethodWrapper *resw = (MonoMethodWrapper*)result;
1123 		int len = GPOINTER_TO_INT (((void**)mw->method_data) [0]);
1124 
1125 		resw->method_data = (void **)g_malloc (sizeof (gpointer) * (len + 1));
1126 		memcpy (resw->method_data, mw->method_data, sizeof (gpointer) * (len + 1));
1127 	}
1128 
1129 	if (iresult->context.method_inst) {
1130 		/* Set the generic_container of the result to the generic_container of method */
1131 		MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
1132 
1133 		if (generic_container && iresult->context.method_inst == generic_container->context.method_inst) {
1134 			result->is_generic = 1;
1135 			mono_method_set_generic_container (result, generic_container);
1136 		}
1137 	}
1138 
1139 	if (klass_hint) {
1140 		MonoGenericClass *gklass_hint = mono_class_try_get_generic_class (klass_hint);
1141 		if (gklass_hint && (gklass_hint->container_class != method->klass || gklass_hint->context.class_inst != context->class_inst))
1142 			klass_hint = NULL;
1143 	}
1144 
1145 	if (mono_class_is_gtd (method->klass))
1146 		result->klass = klass_hint;
1147 
1148 	if (!result->klass) {
1149 		MonoType *inflated = inflate_generic_type (NULL, &method->klass->byval_arg, context, error);
1150 		if (!mono_error_ok (error))
1151 			goto fail;
1152 
1153 		result->klass = inflated ? mono_class_from_mono_type (inflated) : method->klass;
1154 		if (inflated)
1155 			mono_metadata_free_type (inflated);
1156 	}
1157 
1158 	/*
1159 	 * FIXME: This should hold, but it doesn't:
1160 	 *
1161 	 * if (result->is_inflated && mono_method_get_context (result)->method_inst &&
1162 	 *		mono_method_get_context (result)->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)result)->declaring)->context.method_inst) {
1163 	 * 	g_assert (result->is_generic);
1164 	 * }
1165 	 *
1166 	 * Fixing this here causes other things to break, hence a very
1167 	 * ugly hack in mini-trampolines.c - see
1168 	 * is_generic_method_definition().
1169 	 */
1170 
1171 	// check cache
1172 	mono_image_set_lock (set);
1173 	cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1174 	if (!cached) {
1175 		g_hash_table_insert (set->gmethod_cache, iresult, iresult);
1176 		iresult->owner = set;
1177 		cached = iresult;
1178 	}
1179 	mono_image_set_unlock (set);
1180 
1181 	return (MonoMethod*)cached;
1182 
1183 fail:
1184 	g_free (iresult);
1185 	return NULL;
1186 }
1187 
1188 /**
1189  * mono_get_inflated_method:
1190  *
1191  * Obsolete.  We keep it around since it's mentioned in the public API.
1192  */
1193 MonoMethod*
mono_get_inflated_method(MonoMethod * method)1194 mono_get_inflated_method (MonoMethod *method)
1195 {
1196 	return method;
1197 }
1198 
1199 /*
1200  * mono_method_get_context_general:
1201  * @method: a method
1202  * @uninflated: handle uninflated methods?
1203  *
1204  * Returns the generic context of a method or NULL if it doesn't have
1205  * one.  For an inflated method that's the context stored in the
1206  * method.  Otherwise it's in the method's generic container or in the
1207  * generic container of the method's class.
1208  */
1209 MonoGenericContext*
mono_method_get_context_general(MonoMethod * method,gboolean uninflated)1210 mono_method_get_context_general (MonoMethod *method, gboolean uninflated)
1211 {
1212 	if (method->is_inflated) {
1213 		MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1214 		return &imethod->context;
1215 	}
1216 	if (!uninflated)
1217 		return NULL;
1218 	if (method->is_generic)
1219 		return &(mono_method_get_generic_container (method)->context);
1220 	if (mono_class_is_gtd (method->klass))
1221 		return &mono_class_get_generic_container (method->klass)->context;
1222 	return NULL;
1223 }
1224 
1225 /*
1226  * mono_method_get_context:
1227  * @method: a method
1228  *
1229  * Returns the generic context for method if it's inflated, otherwise
1230  * NULL.
1231  */
1232 MonoGenericContext*
mono_method_get_context(MonoMethod * method)1233 mono_method_get_context (MonoMethod *method)
1234 {
1235 	return mono_method_get_context_general (method, FALSE);
1236 }
1237 
1238 /*
1239  * mono_method_get_generic_container:
1240  *
1241  *   Returns the generic container of METHOD, which should be a generic method definition.
1242  * Returns NULL if METHOD is not a generic method definition.
1243  * LOCKING: Acquires the loader lock.
1244  */
1245 MonoGenericContainer*
mono_method_get_generic_container(MonoMethod * method)1246 mono_method_get_generic_container (MonoMethod *method)
1247 {
1248 	MonoGenericContainer *container;
1249 
1250 	if (!method->is_generic)
1251 		return NULL;
1252 
1253 	container = (MonoGenericContainer *)mono_image_property_lookup (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER);
1254 	g_assert (container);
1255 
1256 	return container;
1257 }
1258 
1259 /*
1260  * mono_method_set_generic_container:
1261  *
1262  *   Sets the generic container of METHOD to CONTAINER.
1263  * LOCKING: Acquires the image lock.
1264  */
1265 void
mono_method_set_generic_container(MonoMethod * method,MonoGenericContainer * container)1266 mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* container)
1267 {
1268 	g_assert (method->is_generic);
1269 
1270 	mono_image_property_insert (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER, container);
1271 }
1272 
1273 /**
1274  * mono_class_find_enum_basetype:
1275  * \param class The enum class
1276  *
1277  *   Determine the basetype of an enum by iterating through its fields. We do this
1278  * in a separate function since it is cheaper than calling mono_class_setup_fields.
1279  */
1280 static MonoType*
mono_class_find_enum_basetype(MonoClass * klass,MonoError * error)1281 mono_class_find_enum_basetype (MonoClass *klass, MonoError *error)
1282 {
1283 	MonoGenericContainer *container = NULL;
1284 	MonoImage *m = klass->image;
1285 	const int top = mono_class_get_field_count (klass);
1286 	int i, first_field_idx;
1287 
1288 	g_assert (klass->enumtype);
1289 
1290 	error_init (error);
1291 
1292 	container = mono_class_try_get_generic_container (klass);
1293 	if (mono_class_is_ginst (klass)) {
1294 		MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
1295 
1296 		container = mono_class_get_generic_container (gklass);
1297 		g_assert (container);
1298 	}
1299 
1300 	/*
1301 	 * Fetch all the field information.
1302 	 */
1303 	first_field_idx = mono_class_get_first_field_idx (klass);
1304 	for (i = 0; i < top; i++){
1305 		const char *sig;
1306 		guint32 cols [MONO_FIELD_SIZE];
1307 		int idx = first_field_idx + i;
1308 		MonoType *ftype;
1309 
1310 		/* first_field_idx and idx points into the fieldptr table */
1311 		mono_metadata_decode_table_row (m, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
1312 
1313 		if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC) //no need to decode static fields
1314 			continue;
1315 
1316 		if (!mono_verifier_verify_field_signature (klass->image, cols [MONO_FIELD_SIGNATURE], NULL)) {
1317 			mono_error_set_bad_image (error, klass->image, "Invalid field signature %x", cols [MONO_FIELD_SIGNATURE]);
1318 			goto fail;
1319 		}
1320 
1321 		sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
1322 		mono_metadata_decode_value (sig, &sig);
1323 		/* FIELD signature == 0x06 */
1324 		if (*sig != 0x06) {
1325 			mono_error_set_bad_image (error, klass->image, "Invalid field signature %x, expected 0x6 but got %x", cols [MONO_FIELD_SIGNATURE], *sig);
1326 			goto fail;
1327 		}
1328 
1329 		ftype = mono_metadata_parse_type_checked (m, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
1330 		if (!ftype)
1331 			goto fail;
1332 
1333 		if (mono_class_is_ginst (klass)) {
1334 			//FIXME do we leak here?
1335 			ftype = mono_class_inflate_generic_type_checked (ftype, mono_class_get_context (klass), error);
1336 			if (!mono_error_ok (error))
1337 				goto fail;
1338 			ftype->attrs = cols [MONO_FIELD_FLAGS];
1339 		}
1340 
1341 		return ftype;
1342 	}
1343 	mono_error_set_type_load_class (error, klass, "Could not find base type");
1344 
1345 fail:
1346 	return NULL;
1347 }
1348 
1349 /*
1350  * Checks for MonoClass::has_failure without resolving all MonoType's into MonoClass'es
1351  */
1352 static gboolean
mono_type_has_exceptions(MonoType * type)1353 mono_type_has_exceptions (MonoType *type)
1354 {
1355 	switch (type->type) {
1356 	case MONO_TYPE_CLASS:
1357 	case MONO_TYPE_VALUETYPE:
1358 	case MONO_TYPE_SZARRAY:
1359 		return mono_class_has_failure (type->data.klass);
1360 	case MONO_TYPE_ARRAY:
1361 		return mono_class_has_failure (type->data.array->eklass);
1362 	case MONO_TYPE_GENERICINST:
1363 		return mono_class_has_failure (mono_generic_class_get_class (type->data.generic_class));
1364 	default:
1365 		return FALSE;
1366 	}
1367 }
1368 
1369 void
mono_error_set_for_class_failure(MonoError * oerror,const MonoClass * klass)1370 mono_error_set_for_class_failure (MonoError *oerror, const MonoClass *klass)
1371 {
1372 	g_assert (mono_class_has_failure (klass));
1373 	MonoErrorBoxed *box = mono_class_get_exception_data ((MonoClass*)klass);
1374 	mono_error_set_from_boxed (oerror, box);
1375 }
1376 
1377 /*
1378  * mono_class_alloc:
1379  *
1380  *   Allocate memory for some data belonging to CLASS, either from its image's mempool,
1381  * or from the heap.
1382  */
1383 gpointer
mono_class_alloc(MonoClass * klass,int size)1384 mono_class_alloc (MonoClass *klass, int size)
1385 {
1386 	MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
1387 	if (gklass)
1388 		return mono_image_set_alloc (gklass->owner, size);
1389 	else
1390 		return mono_image_alloc (klass->image, size);
1391 }
1392 
1393 gpointer
mono_class_alloc0(MonoClass * klass,int size)1394 mono_class_alloc0 (MonoClass *klass, int size)
1395 {
1396 	gpointer res;
1397 
1398 	res = mono_class_alloc (klass, size);
1399 	memset (res, 0, size);
1400 	return res;
1401 }
1402 
1403 #define mono_class_new0(klass,struct_type, n_structs)		\
1404     ((struct_type *) mono_class_alloc0 ((klass), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
1405 
1406 /**
1407  * mono_class_setup_basic_field_info:
1408  * \param class The class to initialize
1409  *
1410  * Initializes the following fields in MonoClass:
1411  * * klass->fields (only field->parent and field->name)
1412  * * klass->field.count
1413  * * klass->first_field_idx
1414  * LOCKING: Acquires the loader lock
1415  */
1416 static void
mono_class_setup_basic_field_info(MonoClass * klass)1417 mono_class_setup_basic_field_info (MonoClass *klass)
1418 {
1419 	MonoGenericClass *gklass;
1420 	MonoClassField *field;
1421 	MonoClassField *fields;
1422 	MonoClass *gtd;
1423 	MonoImage *image;
1424 	int i, top;
1425 
1426 	if (klass->fields)
1427 		return;
1428 
1429 	gklass = mono_class_try_get_generic_class (klass);
1430 	gtd = gklass ? mono_class_get_generic_type_definition (klass) : NULL;
1431 	image = klass->image;
1432 
1433 
1434 	if (gklass && image_is_dynamic (gklass->container_class->image) && !gklass->container_class->wastypebuilder) {
1435 		/*
1436 		 * This happens when a generic instance of an unfinished generic typebuilder
1437 		 * is used as an element type for creating an array type. We can't initialize
1438 		 * the fields of this class using the fields of gklass, since gklass is not
1439 		 * finished yet, fields could be added to it later.
1440 		 */
1441 		return;
1442 	}
1443 
1444 	if (gtd) {
1445 		mono_class_setup_basic_field_info (gtd);
1446 
1447 		mono_loader_lock ();
1448 		mono_class_set_field_count (klass, mono_class_get_field_count (gtd));
1449 		mono_loader_unlock ();
1450 	}
1451 
1452 	top = mono_class_get_field_count (klass);
1453 
1454 	fields = (MonoClassField *)mono_class_alloc0 (klass, sizeof (MonoClassField) * top);
1455 
1456 	/*
1457 	 * Fetch all the field information.
1458 	 */
1459 	int first_field_idx = mono_class_has_static_metadata (klass) ? mono_class_get_first_field_idx (klass) : 0;
1460 	for (i = 0; i < top; i++) {
1461 		field = &fields [i];
1462 		field->parent = klass;
1463 
1464 		if (gtd) {
1465 			field->name = mono_field_get_name (&gtd->fields [i]);
1466 		} else {
1467 			int idx = first_field_idx + i;
1468 			/* first_field_idx and idx points into the fieldptr table */
1469 			guint32 name_idx = mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_NAME);
1470 			/* The name is needed for fieldrefs */
1471 			field->name = mono_metadata_string_heap (image, name_idx);
1472 		}
1473 	}
1474 
1475 	mono_memory_barrier ();
1476 
1477 	mono_loader_lock ();
1478 	if (!klass->fields)
1479 		klass->fields = fields;
1480 	mono_loader_unlock ();
1481 }
1482 
1483 /**
1484  * mono_class_set_failure_causedby_class:
1485  * \param klass the class that is failing
1486  * \param caused_by the class that caused the failure
1487  * \param msg Why \p klass is failing.
1488  *
1489  * If \p caused_by has a failure, sets a TypeLoadException failure on
1490  * \p klass with message "\p msg, due to: {\p caused_by message}".
1491  *
1492  * \returns TRUE if a failiure was set, or FALSE if \p caused_by doesn't have a failure.
1493  */
1494 static gboolean
mono_class_set_type_load_failure_causedby_class(MonoClass * klass,const MonoClass * caused_by,const gchar * msg)1495 mono_class_set_type_load_failure_causedby_class (MonoClass *klass, const MonoClass *caused_by, const gchar* msg)
1496 {
1497 	if (mono_class_has_failure (caused_by)) {
1498 		MonoError cause_error;
1499 		error_init (&cause_error);
1500 		mono_error_set_for_class_failure (&cause_error, caused_by);
1501 		mono_class_set_type_load_failure (klass, "%s, due to: %s", msg, mono_error_get_message (&cause_error));
1502 		mono_error_cleanup (&cause_error);
1503 		return TRUE;
1504 	} else {
1505 		return FALSE;
1506 	}
1507 }
1508 
1509 
1510 /**
1511  * mono_class_setup_fields:
1512  * \p klass The class to initialize
1513  *
1514  * Initializes klass->fields, computes class layout and sizes.
1515  * typebuilder_setup_fields () is the corresponding function for dynamic classes.
1516  * Sets the following fields in \p klass:
1517  *  - all the fields initialized by mono_class_init_sizes ()
1518  *  - element_class/cast_class (for enums)
1519  *  - sizes:element_size (for arrays)
1520  *  - field->type/offset for all fields
1521  *  - fields_inited
1522  *
1523  * LOCKING: Acquires the loader lock.
1524  */
1525 void
mono_class_setup_fields(MonoClass * klass)1526 mono_class_setup_fields (MonoClass *klass)
1527 {
1528 	MonoError error;
1529 	MonoImage *m = klass->image;
1530 	int top;
1531 	guint32 layout = mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK;
1532 	int i;
1533 	guint32 real_size = 0;
1534 	guint32 packing_size = 0;
1535 	int instance_size;
1536 	gboolean explicit_size;
1537 	MonoClassField *field;
1538 	MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
1539 	MonoClass *gtd = gklass ? mono_class_get_generic_type_definition (klass) : NULL;
1540 
1541 	if (klass->fields_inited)
1542 		return;
1543 
1544 	if (gklass && image_is_dynamic (gklass->container_class->image) && !gklass->container_class->wastypebuilder) {
1545 		/*
1546 		 * This happens when a generic instance of an unfinished generic typebuilder
1547 		 * is used as an element type for creating an array type. We can't initialize
1548 		 * the fields of this class using the fields of gklass, since gklass is not
1549 		 * finished yet, fields could be added to it later.
1550 		 */
1551 		return;
1552 	}
1553 
1554 	mono_class_setup_basic_field_info (klass);
1555 	top = mono_class_get_field_count (klass);
1556 
1557 	if (gtd) {
1558 		mono_class_setup_fields (gtd);
1559 		if (mono_class_set_type_load_failure_causedby_class (klass, gtd, "Generic type definition failed"))
1560 			return;
1561 	}
1562 
1563 	instance_size = 0;
1564 	if (klass->parent) {
1565 		/* For generic instances, klass->parent might not have been initialized */
1566 		mono_class_init (klass->parent);
1567 		mono_class_setup_fields (klass->parent);
1568 		if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Could not set up parent class"))
1569 			return;
1570 		instance_size = klass->parent->instance_size;
1571 	} else {
1572 		instance_size = sizeof (MonoObject);
1573 	}
1574 
1575 	/* Get the real size */
1576 	explicit_size = mono_metadata_packing_from_typedef (klass->image, klass->type_token, &packing_size, &real_size);
1577 	if (explicit_size)
1578 		instance_size += real_size;
1579 
1580 	/*
1581 	 * This function can recursively call itself.
1582 	 * Prevent infinite recursion by using a list in TLS.
1583 	 */
1584 	GSList *init_list = (GSList *)mono_native_tls_get_value (setup_fields_tls_id);
1585 	if (g_slist_find (init_list, klass))
1586 		return;
1587 	init_list = g_slist_prepend (init_list, klass);
1588 	mono_native_tls_set_value (setup_fields_tls_id, init_list);
1589 
1590 	/*
1591 	 * Fetch all the field information.
1592 	 */
1593 	int first_field_idx = mono_class_has_static_metadata (klass) ? mono_class_get_first_field_idx (klass) : 0;
1594 	for (i = 0; i < top; i++) {
1595 		int idx = first_field_idx + i;
1596 		field = &klass->fields [i];
1597 
1598 		if (!field->type) {
1599 			mono_field_resolve_type (field, &error);
1600 			if (!mono_error_ok (&error)) {
1601 				/*mono_field_resolve_type already failed class*/
1602 				mono_error_cleanup (&error);
1603 				break;
1604 			}
1605 			if (!field->type)
1606 				g_error ("could not resolve %s:%s\n", mono_type_get_full_name(klass), field->name);
1607 			g_assert (field->type);
1608 		}
1609 
1610 		if (!mono_type_get_underlying_type (field->type)) {
1611 			mono_class_set_type_load_failure (klass, "Field '%s' is an enum type with a bad underlying type", field->name);
1612 			break;
1613 		}
1614 
1615 		if (mono_field_is_deleted (field))
1616 			continue;
1617 		if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1618 			guint32 uoffset;
1619 			mono_metadata_field_info (m, idx, &uoffset, NULL, NULL);
1620 			int offset = uoffset;
1621 
1622 			if (offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1623 				mono_class_set_type_load_failure (klass, "Missing field layout info for %s", field->name);
1624 				break;
1625 			}
1626 			if (offset < -1) { /*-1 is used to encode special static fields */
1627 				mono_class_set_type_load_failure (klass, "Field '%s' has a negative offset %d", field->name, offset);
1628 				break;
1629 			}
1630 			if (mono_class_is_gtd (klass)) {
1631 				mono_class_set_type_load_failure (klass, "Generic class cannot have explicit layout.");
1632 				break;
1633 			}
1634 		}
1635 		if (mono_type_has_exceptions (field->type)) {
1636 			char *class_name = mono_type_get_full_name (klass);
1637 			char *type_name = mono_type_full_name (field->type);
1638 
1639 			mono_class_set_type_load_failure (klass, "Invalid type %s for instance field %s:%s", type_name, class_name, field->name);
1640 			g_free (class_name);
1641 			g_free (type_name);
1642 			break;
1643 		}
1644 		/* The def_value of fields is compute lazily during vtable creation */
1645 	}
1646 
1647 	if (!mono_class_has_failure (klass)) {
1648 		mono_loader_lock ();
1649 		mono_class_layout_fields (klass, instance_size, packing_size, real_size, FALSE);
1650 		mono_loader_unlock ();
1651 	}
1652 
1653 	init_list = g_slist_remove (init_list, klass);
1654 	mono_native_tls_set_value (setup_fields_tls_id, init_list);
1655 }
1656 
1657 static void
init_sizes_with_info(MonoClass * klass,MonoCachedClassInfo * cached_info)1658 init_sizes_with_info (MonoClass *klass, MonoCachedClassInfo *cached_info)
1659 {
1660 	if (cached_info) {
1661 		mono_loader_lock ();
1662 		klass->instance_size = cached_info->instance_size;
1663 		klass->sizes.class_size = cached_info->class_size;
1664 		klass->packing_size = cached_info->packing_size;
1665 		klass->min_align = cached_info->min_align;
1666 		klass->blittable = cached_info->blittable;
1667 		klass->has_references = cached_info->has_references;
1668 		klass->has_static_refs = cached_info->has_static_refs;
1669 		klass->no_special_static_fields = cached_info->no_special_static_fields;
1670 		klass->has_weak_fields = cached_info->has_weak_fields;
1671 		mono_loader_unlock ();
1672 	}
1673 	else {
1674 		if (!klass->size_inited)
1675 			mono_class_setup_fields (klass);
1676 	}
1677 }
1678 /*
1679 
1680  * mono_class_init_sizes:
1681  *
1682  *   Initializes the size related fields of @klass without loading all field data if possible.
1683  * Sets the following fields in @klass:
1684  * - instance_size
1685  * - sizes.class_size
1686  * - packing_size
1687  * - min_align
1688  * - blittable
1689  * - has_references
1690  * - has_static_refs
1691  * - size_inited
1692  * Can fail the class.
1693  *
1694  * LOCKING: Acquires the loader lock.
1695  */
1696 static void
mono_class_init_sizes(MonoClass * klass)1697 mono_class_init_sizes (MonoClass *klass)
1698 {
1699 	MonoCachedClassInfo cached_info;
1700 	gboolean has_cached_info;
1701 
1702 	if (klass->size_inited)
1703 		return;
1704 
1705 	has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
1706 
1707 	init_sizes_with_info (klass, has_cached_info ? &cached_info : NULL);
1708 }
1709 
1710 /*
1711  * mono_type_get_basic_type_from_generic:
1712  * @type: a type
1713  *
1714  * Returns a closed type corresponding to the possibly open type
1715  * passed to it.
1716  */
1717 MonoType*
mono_type_get_basic_type_from_generic(MonoType * type)1718 mono_type_get_basic_type_from_generic (MonoType *type)
1719 {
1720 	/* When we do generic sharing we let type variables stand for reference/primitive types. */
1721 	if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) &&
1722 		(!type->data.generic_param->gshared_constraint || type->data.generic_param->gshared_constraint->type == MONO_TYPE_OBJECT))
1723 		return &mono_defaults.object_class->byval_arg;
1724 	return type;
1725 }
1726 
1727 static gboolean
class_has_references(MonoClass * klass)1728 class_has_references (MonoClass *klass)
1729 {
1730 	mono_class_init_sizes (klass);
1731 
1732 	/*
1733 	 * has_references is not set if this is called recursively, but this is not a problem since this is only used
1734 	 * during field layout, and instance fields are initialized before static fields, and instance fields can't
1735 	 * embed themselves.
1736 	 */
1737 	return klass->has_references;
1738 }
1739 
1740 static gboolean
type_has_references(MonoClass * klass,MonoType * ftype)1741 type_has_references (MonoClass *klass, MonoType *ftype)
1742 {
1743 	if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (klass, ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && class_has_references (mono_class_from_mono_type (ftype)))))
1744 		return TRUE;
1745 	if (!ftype->byref && (ftype->type == MONO_TYPE_VAR || ftype->type == MONO_TYPE_MVAR)) {
1746 		MonoGenericParam *gparam = ftype->data.generic_param;
1747 
1748 		if (gparam->gshared_constraint)
1749 			return class_has_references (mono_class_from_mono_type (gparam->gshared_constraint));
1750 	}
1751 	return FALSE;
1752 }
1753 
1754 /*
1755  * mono_class_layout_fields:
1756  * @class: a class
1757  * @base_instance_size: base instance size
1758  * @packing_size:
1759  *
1760  * This contains the common code for computing the layout of classes and sizes.
1761  * This should only be called from mono_class_setup_fields () and
1762  * typebuilder_setup_fields ().
1763  *
1764  * LOCKING: Acquires the loader lock
1765  */
1766 void
mono_class_layout_fields(MonoClass * klass,int base_instance_size,int packing_size,int explicit_size,gboolean sre)1767 mono_class_layout_fields (MonoClass *klass, int base_instance_size, int packing_size, int explicit_size, gboolean sre)
1768 {
1769 	int i;
1770 	const int top = mono_class_get_field_count (klass);
1771 	guint32 layout = mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK;
1772 	guint32 pass, passes, real_size;
1773 	gboolean gc_aware_layout = FALSE;
1774 	gboolean has_static_fields = FALSE;
1775 	gboolean has_references = FALSE;
1776 	gboolean has_static_refs = FALSE;
1777 	MonoClassField *field;
1778 	gboolean blittable;
1779 	int instance_size = base_instance_size;
1780 	int element_size = -1;
1781 	int class_size, min_align;
1782 	int *field_offsets;
1783 	gboolean *fields_has_references;
1784 
1785 	/*
1786 	 * We want to avoid doing complicated work inside locks, so we compute all the required
1787 	 * information and write it to @klass inside a lock.
1788 	 */
1789 	if (klass->fields_inited)
1790 		return;
1791 
1792 	if ((packing_size & 0xffffff00) != 0) {
1793 		mono_class_set_type_load_failure (klass, "Could not load struct '%s' with packing size %d >= 256", klass->name, packing_size);
1794 		return;
1795 	}
1796 
1797 	if (klass->parent) {
1798 		min_align = klass->parent->min_align;
1799 		/* we use | since it may have been set already */
1800 		has_references = klass->has_references | klass->parent->has_references;
1801 	} else {
1802 		min_align = 1;
1803 	}
1804 	/* We can't really enable 16 bytes alignment until the GC supports it.
1805 	The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the
1806 	boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type.
1807 	Bug #506144 is an example of this issue.
1808 
1809 	 if (klass->simd_type)
1810 		min_align = 16;
1811 	 */
1812 
1813 	/*
1814 	 * When we do generic sharing we need to have layout
1815 	 * information for open generic classes (either with a generic
1816 	 * context containing type variables or with a generic
1817 	 * container), so we don't return in that case anymore.
1818 	 */
1819 
1820 	if (klass->enumtype) {
1821 		for (i = 0; i < top; i++) {
1822 			field = &klass->fields [i];
1823 			if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1824 				klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
1825 				break;
1826 			}
1827 		}
1828 
1829 		if (!mono_class_enum_basetype (klass)) {
1830 			mono_class_set_type_load_failure (klass, "The enumeration's base type is invalid.");
1831 			return;
1832 		}
1833 	}
1834 
1835 	/*
1836 	 * Enable GC aware auto layout: in this mode, reference
1837 	 * fields are grouped together inside objects, increasing collector
1838 	 * performance.
1839 	 * Requires that all classes whose layout is known to native code be annotated
1840 	 * with [StructLayout (LayoutKind.Sequential)]
1841 	 * Value types have gc_aware_layout disabled by default, as per
1842 	 * what the default is for other runtimes.
1843 	 */
1844 	 /* corlib is missing [StructLayout] directives in many places */
1845 	if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1846 		if (!klass->valuetype)
1847 			gc_aware_layout = TRUE;
1848 	}
1849 
1850 	/* Compute klass->blittable */
1851 	blittable = TRUE;
1852 	if (klass->parent)
1853 		blittable = klass->parent->blittable;
1854 	if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT && !(mono_is_corlib_image (klass->image) && !strcmp (klass->name_space, "System") && !strcmp (klass->name, "ValueType")) && top)
1855 		blittable = FALSE;
1856 	for (i = 0; i < top; i++) {
1857 		field = &klass->fields [i];
1858 
1859 		if (mono_field_is_deleted (field))
1860 			continue;
1861 		if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1862 			continue;
1863 		if (blittable) {
1864 			if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
1865 				blittable = FALSE;
1866 			} else {
1867 				MonoClass *field_class = mono_class_from_mono_type (field->type);
1868 				if (field_class) {
1869 					mono_class_setup_fields (field_class);
1870 					if (mono_class_has_failure (field_class)) {
1871 						MonoError field_error;
1872 						error_init (&field_error);
1873 						mono_error_set_for_class_failure (&field_error, field_class);
1874 						mono_class_set_type_load_failure (klass, "Could not set up field '%s' due to: %s", field->name, mono_error_get_message (&field_error));
1875 						mono_error_cleanup (&field_error);
1876 						break;
1877 					}
1878 				}
1879 				if (!field_class || !field_class->blittable)
1880 					blittable = FALSE;
1881 			}
1882 		}
1883 		if (klass->enumtype)
1884 			blittable = klass->element_class->blittable;
1885 	}
1886 	if (mono_class_has_failure (klass))
1887 		return;
1888 	if (klass == mono_defaults.string_class)
1889 		blittable = FALSE;
1890 
1891 	/* Compute klass->has_references */
1892 	/*
1893 	 * Process non-static fields first, since static fields might recursively
1894 	 * refer to the class itself.
1895 	 */
1896 	for (i = 0; i < top; i++) {
1897 		MonoType *ftype;
1898 
1899 		field = &klass->fields [i];
1900 
1901 		if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1902 			ftype = mono_type_get_underlying_type (field->type);
1903 			ftype = mono_type_get_basic_type_from_generic (ftype);
1904 			if (type_has_references (klass, ftype))
1905 				has_references = TRUE;
1906 		}
1907 	}
1908 
1909 	/*
1910 	 * Compute field layout and total size (not considering static fields)
1911 	 */
1912 	field_offsets = g_new0 (int, top);
1913 	fields_has_references = g_new0 (gboolean, top);
1914 	int first_field_idx = mono_class_has_static_metadata (klass) ? mono_class_get_first_field_idx (klass) : 0;
1915 	switch (layout) {
1916 	case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1917 	case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1918 		if (gc_aware_layout)
1919 			passes = 2;
1920 		else
1921 			passes = 1;
1922 
1923 		if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1924 			passes = 1;
1925 
1926 		if (klass->parent) {
1927 			mono_class_setup_fields (klass->parent);
1928 			if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Cannot initialize parent class"))
1929 				return;
1930 			real_size = klass->parent->instance_size;
1931 		} else {
1932 			real_size = sizeof (MonoObject);
1933 		}
1934 
1935 		for (pass = 0; pass < passes; ++pass) {
1936 			for (i = 0; i < top; i++){
1937 				gint32 align;
1938 				guint32 size;
1939 				MonoType *ftype;
1940 
1941 				field = &klass->fields [i];
1942 
1943 				if (mono_field_is_deleted (field))
1944 					continue;
1945 				if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1946 					continue;
1947 
1948 				ftype = mono_type_get_underlying_type (field->type);
1949 				ftype = mono_type_get_basic_type_from_generic (ftype);
1950 				if (gc_aware_layout) {
1951 					fields_has_references [i] = type_has_references (klass, ftype);
1952 					if (fields_has_references [i]) {
1953 						if (pass == 1)
1954 							continue;
1955 					} else {
1956 						if (pass == 0)
1957 							continue;
1958 					}
1959 				}
1960 
1961 				if ((top == 1) && (instance_size == sizeof (MonoObject)) &&
1962 					(strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
1963 					/* This field is a hack inserted by MCS to empty structures */
1964 					continue;
1965 				}
1966 
1967 				size = mono_type_size (field->type, &align);
1968 
1969 				/* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1970 				align = packing_size ? MIN (packing_size, align): align;
1971 				/* if the field has managed references, we need to force-align it
1972 				 * see bug #77788
1973 				 */
1974 				if (type_has_references (klass, ftype))
1975 					align = MAX (align, sizeof (gpointer));
1976 
1977 				min_align = MAX (align, min_align);
1978 				field_offsets [i] = real_size;
1979 				if (align) {
1980 					field_offsets [i] += align - 1;
1981 					field_offsets [i] &= ~(align - 1);
1982 				}
1983 				/*TypeBuilders produce all sort of weird things*/
1984 				g_assert (image_is_dynamic (klass->image) || field_offsets [i] > 0);
1985 				real_size = field_offsets [i] + size;
1986 			}
1987 
1988 			/* Make SIMD types as big as a SIMD register since they can be stored into using simd stores */
1989 			if (klass->simd_type)
1990 				real_size = MAX (real_size, sizeof (MonoObject) + 16);
1991 			instance_size = MAX (real_size, instance_size);
1992 
1993 			if (instance_size & (min_align - 1)) {
1994 				instance_size += min_align - 1;
1995 				instance_size &= ~(min_align - 1);
1996 			}
1997 		}
1998 		break;
1999 	case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT: {
2000 		guint8 *ref_bitmap;
2001 
2002 		real_size = 0;
2003 		for (i = 0; i < top; i++) {
2004 			gint32 align;
2005 			guint32 size;
2006 			MonoType *ftype;
2007 
2008 			field = &klass->fields [i];
2009 
2010 			/*
2011 			 * There must be info about all the fields in a type if it
2012 			 * uses explicit layout.
2013 			 */
2014 			if (mono_field_is_deleted (field))
2015 				continue;
2016 			if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2017 				continue;
2018 
2019 			size = mono_type_size (field->type, &align);
2020 			align = packing_size ? MIN (packing_size, align): align;
2021 			min_align = MAX (align, min_align);
2022 
2023 			if (sre) {
2024 				/* Already set by typebuilder_setup_fields () */
2025 				field_offsets [i] = field->offset + sizeof (MonoObject);
2026 			} else {
2027 				int idx = first_field_idx + i;
2028 				guint32 offset;
2029 				mono_metadata_field_info (klass->image, idx, &offset, NULL, NULL);
2030 				field_offsets [i] = offset + sizeof (MonoObject);
2031 			}
2032 			ftype = mono_type_get_underlying_type (field->type);
2033 			ftype = mono_type_get_basic_type_from_generic (ftype);
2034 			if (type_has_references (klass, ftype)) {
2035 				if (field_offsets [i] % sizeof (gpointer)) {
2036 					mono_class_set_type_load_failure (klass, "Reference typed field '%s' has explicit offset that is not pointer-size aligned.", field->name);
2037 				}
2038 			}
2039 
2040 			/*
2041 			 * Calc max size.
2042 			 */
2043 			real_size = MAX (real_size, size + field_offsets [i]);
2044 		}
2045 
2046 		if (klass->has_references) {
2047 			ref_bitmap = g_new0 (guint8, real_size / sizeof (gpointer));
2048 
2049 			/* Check for overlapping reference and non-reference fields */
2050 			for (i = 0; i < top; i++) {
2051 				MonoType *ftype;
2052 
2053 				field = &klass->fields [i];
2054 
2055 				if (mono_field_is_deleted (field))
2056 					continue;
2057 				if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2058 					continue;
2059 				ftype = mono_type_get_underlying_type (field->type);
2060 				if (MONO_TYPE_IS_REFERENCE (ftype))
2061 					ref_bitmap [field_offsets [i] / sizeof (gpointer)] = 1;
2062 			}
2063 			for (i = 0; i < top; i++) {
2064 				field = &klass->fields [i];
2065 
2066 				if (mono_field_is_deleted (field))
2067 					continue;
2068 				if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2069 					continue;
2070 
2071 				// FIXME: Too much code does this
2072 #if 0
2073 				if (!MONO_TYPE_IS_REFERENCE (field->type) && ref_bitmap [field_offsets [i] / sizeof (gpointer)]) {
2074 					mono_class_set_type_load_failure (klass, "Could not load type '%s' because it contains an object field at offset %d that is incorrectly aligned or overlapped by a non-object field.", klass->name, field_offsets [i]);
2075 				}
2076 #endif
2077 			}
2078 			g_free (ref_bitmap);
2079 		}
2080 
2081 		instance_size = MAX (real_size, instance_size);
2082 		if (!((layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) && explicit_size)) {
2083 			if (instance_size & (min_align - 1)) {
2084 				instance_size += min_align - 1;
2085 				instance_size &= ~(min_align - 1);
2086 			}
2087 		}
2088 		break;
2089 	}
2090 	}
2091 
2092 	if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
2093 		/*
2094 		 * This leads to all kinds of problems with nested structs, so only
2095 		 * enable it when a MONO_DEBUG property is set.
2096 		 *
2097 		 * For small structs, set min_align to at least the struct size to improve
2098 		 * performance, and since the JIT memset/memcpy code assumes this and generates
2099 		 * unaligned accesses otherwise. See #78990 for a testcase.
2100 		 */
2101 		if (mono_align_small_structs && top) {
2102 			if (instance_size <= sizeof (MonoObject) + sizeof (gpointer))
2103 				min_align = MAX (min_align, instance_size - sizeof (MonoObject));
2104 		}
2105 	}
2106 
2107 	if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR)
2108 		instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
2109 	else if (klass->byval_arg.type == MONO_TYPE_PTR)
2110 		instance_size = sizeof (MonoObject) + sizeof (gpointer);
2111 
2112 	if (klass->byval_arg.type == MONO_TYPE_SZARRAY || klass->byval_arg.type == MONO_TYPE_ARRAY)
2113 		element_size = mono_class_array_element_size (klass->element_class);
2114 
2115 	/* Publish the data */
2116 	mono_loader_lock ();
2117 	if (klass->instance_size && !klass->image->dynamic) {
2118 		/* Might be already set using cached info */
2119 		if (klass->instance_size != instance_size) {
2120 			/* Emit info to help debugging */
2121 			g_print ("%s\n", mono_class_full_name (klass));
2122 			g_print ("%d %d %d %d\n", klass->instance_size, instance_size, klass->blittable, blittable);
2123 			g_print ("%d %d %d %d\n", klass->has_references, has_references, klass->packing_size, packing_size);
2124 			g_print ("%d %d\n", klass->min_align, min_align);
2125 			for (i = 0; i < top; ++i) {
2126 				field = &klass->fields [i];
2127 				if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
2128 					printf ("  %s %d %d %d\n", klass->fields [i].name, klass->fields [i].offset, field_offsets [i], fields_has_references [i]);
2129 			}
2130 		}
2131 		g_assert (klass->instance_size == instance_size);
2132 	} else {
2133 		klass->instance_size = instance_size;
2134 	}
2135 	klass->blittable = blittable;
2136 	klass->has_references = has_references;
2137 	klass->packing_size = packing_size;
2138 	klass->min_align = min_align;
2139 	for (i = 0; i < top; ++i) {
2140 		field = &klass->fields [i];
2141 		if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
2142 			klass->fields [i].offset = field_offsets [i];
2143 	}
2144 
2145 	if (klass->byval_arg.type == MONO_TYPE_SZARRAY || klass->byval_arg.type == MONO_TYPE_ARRAY)
2146 		klass->sizes.element_size = element_size;
2147 
2148 	mono_memory_barrier ();
2149 	klass->size_inited = 1;
2150 	mono_loader_unlock ();
2151 
2152 	/*
2153 	 * Compute static field layout and size
2154 	 * Static fields can reference the class itself, so this has to be
2155 	 * done after instance_size etc. are initialized.
2156 	 */
2157 	class_size = 0;
2158 	for (i = 0; i < top; i++) {
2159 		gint32 align;
2160 		guint32 size;
2161 
2162 		field = &klass->fields [i];
2163 
2164 		if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
2165 			continue;
2166 		if (mono_field_is_deleted (field))
2167 			continue;
2168 
2169 		if (mono_type_has_exceptions (field->type)) {
2170 			mono_class_set_type_load_failure (klass, "Field '%s' has an invalid type.", field->name);
2171 			break;
2172 		}
2173 
2174 		has_static_fields = TRUE;
2175 
2176 		size = mono_type_size (field->type, &align);
2177 		field_offsets [i] = class_size;
2178 		/*align is always non-zero here*/
2179 		field_offsets [i] += align - 1;
2180 		field_offsets [i] &= ~(align - 1);
2181 		class_size = field_offsets [i] + size;
2182 	}
2183 
2184 	if (has_static_fields && class_size == 0)
2185 		/* Simplify code which depends on class_size != 0 if the class has static fields */
2186 		class_size = 8;
2187 
2188 	/* Compute klass->has_static_refs */
2189 	has_static_refs = FALSE;
2190 	for (i = 0; i < top; i++) {
2191 		MonoType *ftype;
2192 
2193 		field = &klass->fields [i];
2194 
2195 		if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
2196 			ftype = mono_type_get_underlying_type (field->type);
2197 			ftype = mono_type_get_basic_type_from_generic (ftype);
2198 			if (type_has_references (klass, ftype))
2199 				has_static_refs = TRUE;
2200 		}
2201 	}
2202 
2203 	/*valuetypes can't be neither bigger than 1Mb or empty. */
2204 	if (klass->valuetype && (klass->instance_size <= 0 || klass->instance_size > (0x100000 + sizeof (MonoObject)))) {
2205 		/* Special case compiler generated types */
2206 		/* Hard to check for [CompilerGenerated] here */
2207 		if (!strstr (klass->name, "StaticArrayInitTypeSize") && !strstr (klass->name, "$ArrayType"))
2208 			mono_class_set_type_load_failure (klass, "Value type instance size (%d) cannot be zero, negative, or bigger than 1Mb", klass->instance_size);
2209 	}
2210 
2211 	// Weak field support
2212 	//
2213 	// FIXME:
2214 	// - generic instances
2215 	// - Disallow on structs/static fields/nonref fields
2216 	gboolean has_weak_fields = FALSE;
2217 
2218 	if (mono_class_has_static_metadata (klass)) {
2219 		for (MonoClass *p = klass; p != NULL; p = p->parent) {
2220 			gpointer iter = NULL;
2221 			guint32 first_field_idx = mono_class_get_first_field_idx (p);
2222 
2223 			while ((field = mono_class_get_fields (p, &iter))) {
2224 				guint32 field_idx = first_field_idx + (field - p->fields);
2225 				if (MONO_TYPE_IS_REFERENCE (field->type) && mono_assembly_is_weak_field (p->image, field_idx + 1)) {
2226 					has_weak_fields = TRUE;
2227 					mono_trace_message (MONO_TRACE_TYPE, "Field %s:%s at offset %x is weak.", field->parent->name, field->name, field->offset);
2228 				}
2229 			}
2230 		}
2231 	}
2232 
2233 	/* Publish the data */
2234 	mono_loader_lock ();
2235 	if (!klass->rank)
2236 		klass->sizes.class_size = class_size;
2237 	klass->has_static_refs = has_static_refs;
2238 	klass->has_weak_fields = has_weak_fields;
2239 	for (i = 0; i < top; ++i) {
2240 		field = &klass->fields [i];
2241 
2242 		if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2243 			field->offset = field_offsets [i];
2244 	}
2245 	mono_memory_barrier ();
2246 	klass->fields_inited = 1;
2247 	mono_loader_unlock ();
2248 
2249 	g_free (field_offsets);
2250 	g_free (fields_has_references);
2251 }
2252 
2253 static MonoMethod*
create_array_method(MonoClass * klass,const char * name,MonoMethodSignature * sig)2254 create_array_method (MonoClass *klass, const char *name, MonoMethodSignature *sig)
2255 {
2256 	MonoMethod *method;
2257 
2258 	method = (MonoMethod *) mono_image_alloc0 (klass->image, sizeof (MonoMethodPInvoke));
2259 	method->klass = klass;
2260 	method->flags = METHOD_ATTRIBUTE_PUBLIC;
2261 	method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2262 	method->signature = sig;
2263 	method->name = name;
2264 	method->slot = -1;
2265 	/* .ctor */
2266 	if (name [0] == '.') {
2267 		method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2268 	} else {
2269 		method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2270 	}
2271 	return method;
2272 }
2273 
2274 /*
2275  * mono_class_setup_methods:
2276  * @class: a class
2277  *
2278  *   Initializes the 'methods' array in CLASS.
2279  * Calling this method should be avoided if possible since it allocates a lot
2280  * of long-living MonoMethod structures.
2281  * Methods belonging to an interface are assigned a sequential slot starting
2282  * from 0.
2283  *
2284  * On failure this function sets klass->has_failure and stores a MonoErrorBoxed with details
2285  */
2286 void
mono_class_setup_methods(MonoClass * klass)2287 mono_class_setup_methods (MonoClass *klass)
2288 {
2289 	int i, count;
2290 	MonoMethod **methods;
2291 
2292 	if (klass->methods)
2293 		return;
2294 
2295 	if (mono_class_is_ginst (klass)) {
2296 		MonoError error;
2297 		MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2298 
2299 		mono_class_init (gklass);
2300 		if (!mono_class_has_failure (gklass))
2301 			mono_class_setup_methods (gklass);
2302 		if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2303 			return;
2304 
2305 		/* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2306 		count = mono_class_get_method_count (gklass);
2307 		methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * (count + 1));
2308 
2309 		for (i = 0; i < count; i++) {
2310 			methods [i] = mono_class_inflate_generic_method_full_checked (
2311 				gklass->methods [i], klass, mono_class_get_context (klass), &error);
2312 			if (!mono_error_ok (&error)) {
2313 				char *method = mono_method_full_name (gklass->methods [i], TRUE);
2314 				mono_class_set_type_load_failure (klass, "Could not inflate method %s due to %s", method, mono_error_get_message (&error));
2315 
2316 				g_free (method);
2317 				mono_error_cleanup (&error);
2318 				return;
2319 			}
2320 		}
2321 	} else if (klass->rank) {
2322 		MonoError error;
2323 		MonoMethod *amethod;
2324 		MonoMethodSignature *sig;
2325 		int count_generic = 0, first_generic = 0;
2326 		int method_num = 0;
2327 		gboolean jagged_ctor = FALSE;
2328 
2329 		count = 3 + (klass->rank > 1? 2: 1);
2330 
2331 		mono_class_setup_interfaces (klass, &error);
2332 		g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2333 
2334 		if (klass->rank == 1 && klass->element_class->rank) {
2335 			jagged_ctor = TRUE;
2336 			count ++;
2337 		}
2338 
2339 		if (klass->interface_count) {
2340 			count_generic = generic_array_methods (klass);
2341 			first_generic = count;
2342 			count += klass->interface_count * count_generic;
2343 		}
2344 
2345 		methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * count);
2346 
2347 		sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2348 		sig->ret = &mono_defaults.void_class->byval_arg;
2349 		sig->pinvoke = TRUE;
2350 		sig->hasthis = TRUE;
2351 		for (i = 0; i < klass->rank; ++i)
2352 			sig->params [i] = &mono_defaults.int32_class->byval_arg;
2353 
2354 		amethod = create_array_method (klass, ".ctor", sig);
2355 		methods [method_num++] = amethod;
2356 		if (klass->rank > 1) {
2357 			sig = mono_metadata_signature_alloc (klass->image, klass->rank * 2);
2358 			sig->ret = &mono_defaults.void_class->byval_arg;
2359 			sig->pinvoke = TRUE;
2360 			sig->hasthis = TRUE;
2361 			for (i = 0; i < klass->rank * 2; ++i)
2362 				sig->params [i] = &mono_defaults.int32_class->byval_arg;
2363 
2364 			amethod = create_array_method (klass, ".ctor", sig);
2365 			methods [method_num++] = amethod;
2366 		}
2367 
2368 		if (jagged_ctor) {
2369 			/* Jagged arrays have an extra ctor in .net which creates an array of arrays */
2370 			sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2371 			sig->ret = &mono_defaults.void_class->byval_arg;
2372 			sig->pinvoke = TRUE;
2373 			sig->hasthis = TRUE;
2374 			for (i = 0; i < klass->rank + 1; ++i)
2375 				sig->params [i] = &mono_defaults.int32_class->byval_arg;
2376 			amethod = create_array_method (klass, ".ctor", sig);
2377 			methods [method_num++] = amethod;
2378 		}
2379 
2380 		/* element Get (idx11, [idx2, ...]) */
2381 		sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2382 		sig->ret = &klass->element_class->byval_arg;
2383 		sig->pinvoke = TRUE;
2384 		sig->hasthis = TRUE;
2385 		for (i = 0; i < klass->rank; ++i)
2386 			sig->params [i] = &mono_defaults.int32_class->byval_arg;
2387 		amethod = create_array_method (klass, "Get", sig);
2388 		methods [method_num++] = amethod;
2389 		/* element& Address (idx11, [idx2, ...]) */
2390 		sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2391 		sig->ret = &klass->element_class->this_arg;
2392 		sig->pinvoke = TRUE;
2393 		sig->hasthis = TRUE;
2394 		for (i = 0; i < klass->rank; ++i)
2395 			sig->params [i] = &mono_defaults.int32_class->byval_arg;
2396 		amethod = create_array_method (klass, "Address", sig);
2397 		methods [method_num++] = amethod;
2398 		/* void Set (idx11, [idx2, ...], element) */
2399 		sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2400 		sig->ret = &mono_defaults.void_class->byval_arg;
2401 		sig->pinvoke = TRUE;
2402 		sig->hasthis = TRUE;
2403 		for (i = 0; i < klass->rank; ++i)
2404 			sig->params [i] = &mono_defaults.int32_class->byval_arg;
2405 		sig->params [i] = &klass->element_class->byval_arg;
2406 		amethod = create_array_method (klass, "Set", sig);
2407 		methods [method_num++] = amethod;
2408 
2409 		GHashTable *cache = g_hash_table_new (NULL, NULL);
2410 		for (i = 0; i < klass->interface_count; i++)
2411 			setup_generic_array_ifaces (klass, klass->interfaces [i], methods, first_generic + i * count_generic, cache);
2412 		g_hash_table_destroy (cache);
2413 	} else if (mono_class_has_static_metadata (klass)) {
2414 		MonoError error;
2415 		int first_idx = mono_class_get_first_method_idx (klass);
2416 
2417 		count = mono_class_get_method_count (klass);
2418 		methods = (MonoMethod **)mono_class_alloc (klass, sizeof (MonoMethod*) * count);
2419 		for (i = 0; i < count; ++i) {
2420 			int idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_METHOD, first_idx + i + 1);
2421 			methods [i] = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | idx, klass, NULL, &error);
2422 			if (!methods [i]) {
2423 				mono_class_set_type_load_failure (klass, "Could not load method %d due to %s", i, mono_error_get_message (&error));
2424 				mono_error_cleanup (&error);
2425 			}
2426 		}
2427 	} else {
2428 		methods = (MonoMethod **)mono_class_alloc (klass, sizeof (MonoMethod*) * 1);
2429 		count = 0;
2430 	}
2431 
2432 	if (MONO_CLASS_IS_INTERFACE (klass)) {
2433 		int slot = 0;
2434 		/*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2435 		for (i = 0; i < count; ++i) {
2436 			if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2437 				methods [i]->slot = slot++;
2438 		}
2439 	}
2440 
2441 	mono_image_lock (klass->image);
2442 
2443 	if (!klass->methods) {
2444 		mono_class_set_method_count (klass, count);
2445 
2446 		/* Needed because of the double-checking locking pattern */
2447 		mono_memory_barrier ();
2448 
2449 		klass->methods = methods;
2450 	}
2451 
2452 	mono_image_unlock (klass->image);
2453 }
2454 
2455 /*
2456  * mono_class_get_method_by_index:
2457  *
2458  *   Returns klass->methods [index], initializing klass->methods if neccesary.
2459  *
2460  * LOCKING: Acquires the loader lock.
2461  */
2462 MonoMethod*
mono_class_get_method_by_index(MonoClass * klass,int index)2463 mono_class_get_method_by_index (MonoClass *klass, int index)
2464 {
2465 	MonoError error;
2466 
2467 	MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
2468 	/* Avoid calling setup_methods () if possible */
2469 	if (gklass && !klass->methods) {
2470 		MonoMethod *m;
2471 
2472 		m = mono_class_inflate_generic_method_full_checked (
2473 				gklass->container_class->methods [index], klass, mono_class_get_context (klass), &error);
2474 		g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2475 		/*
2476 		 * If setup_methods () is called later for this class, no duplicates are created,
2477 		 * since inflate_generic_method guarantees that only one instance of a method
2478 		 * is created for each context.
2479 		 */
2480 		/*
2481 		mono_class_setup_methods (klass);
2482 		g_assert (m == klass->methods [index]);
2483 		*/
2484 		return m;
2485 	} else {
2486 		mono_class_setup_methods (klass);
2487 		if (mono_class_has_failure (klass)) /*FIXME do proper error handling*/
2488 			return NULL;
2489 		g_assert (index >= 0 && index < mono_class_get_method_count (klass));
2490 		return klass->methods [index];
2491 	}
2492 }
2493 
2494 /*
2495  * mono_class_get_inflated_method:
2496  *
2497  *   Given an inflated class CLASS and a method METHOD which should be a method of
2498  * CLASS's generic definition, return the inflated method corresponding to METHOD.
2499  */
2500 MonoMethod*
mono_class_get_inflated_method(MonoClass * klass,MonoMethod * method)2501 mono_class_get_inflated_method (MonoClass *klass, MonoMethod *method)
2502 {
2503 	MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2504 	int i, mcount;
2505 
2506 	g_assert (method->klass == gklass);
2507 
2508 	mono_class_setup_methods (gklass);
2509 	g_assert (!mono_class_has_failure (gklass)); /*FIXME do proper error handling*/
2510 
2511 	mcount = mono_class_get_method_count (gklass);
2512 	for (i = 0; i < mcount; ++i) {
2513 		if (gklass->methods [i] == method) {
2514 			if (klass->methods) {
2515 				return klass->methods [i];
2516 			} else {
2517 				MonoError error;
2518 				MonoMethod *result = mono_class_inflate_generic_method_full_checked (gklass->methods [i], klass, mono_class_get_context (klass), &error);
2519 				g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2520 				return result;
2521 			}
2522 		}
2523 	}
2524 
2525 	return NULL;
2526 }
2527 
2528 /*
2529  * mono_class_get_vtable_entry:
2530  *
2531  *   Returns klass->vtable [offset], computing it if neccesary. Returns NULL on failure.
2532  * LOCKING: Acquires the loader lock.
2533  */
2534 MonoMethod*
mono_class_get_vtable_entry(MonoClass * klass,int offset)2535 mono_class_get_vtable_entry (MonoClass *klass, int offset)
2536 {
2537 	MonoMethod *m;
2538 
2539 	if (klass->rank == 1) {
2540 		/*
2541 		 * szarrays do not overwrite any methods of Array, so we can avoid
2542 		 * initializing their vtables in some cases.
2543 		 */
2544 		mono_class_setup_vtable (klass->parent);
2545 		if (offset < klass->parent->vtable_size)
2546 			return klass->parent->vtable [offset];
2547 	}
2548 
2549 	if (mono_class_is_ginst (klass)) {
2550 		MonoError error;
2551 		MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2552 		mono_class_setup_vtable (gklass);
2553 		m = gklass->vtable [offset];
2554 
2555 		m = mono_class_inflate_generic_method_full_checked (m, klass, mono_class_get_context (klass), &error);
2556 		g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2557 	} else {
2558 		mono_class_setup_vtable (klass);
2559 		if (mono_class_has_failure (klass))
2560 			return NULL;
2561 		m = klass->vtable [offset];
2562 	}
2563 
2564 	return m;
2565 }
2566 
2567 /*
2568  * mono_class_get_vtable_size:
2569  *
2570  *   Return the vtable size for KLASS.
2571  */
2572 int
mono_class_get_vtable_size(MonoClass * klass)2573 mono_class_get_vtable_size (MonoClass *klass)
2574 {
2575 	mono_class_setup_vtable (klass);
2576 
2577 	return klass->vtable_size;
2578 }
2579 
2580 /*
2581  * mono_class_setup_properties:
2582  *
2583  *   Initialize klass->ext.property and klass->ext.properties.
2584  *
2585  * This method can fail the class.
2586  */
2587 static void
mono_class_setup_properties(MonoClass * klass)2588 mono_class_setup_properties (MonoClass *klass)
2589 {
2590 	guint startm, endm, i, j;
2591 	guint32 cols [MONO_PROPERTY_SIZE];
2592 	MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2593 	MonoProperty *properties;
2594 	guint32 last;
2595 	int first, count;
2596 	MonoClassPropertyInfo *info;
2597 
2598 	info = mono_class_get_property_info (klass);
2599 	if (info)
2600 		return;
2601 
2602 	if (mono_class_is_ginst (klass)) {
2603 		MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2604 
2605 		mono_class_init (gklass);
2606 		mono_class_setup_properties (gklass);
2607 		if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2608 			return;
2609 
2610 		MonoClassPropertyInfo *ginfo = mono_class_get_property_info (gklass);
2611 		properties = mono_class_new0 (klass, MonoProperty, ginfo->count + 1);
2612 
2613 		for (i = 0; i < ginfo->count; i++) {
2614 			MonoError error;
2615 			MonoProperty *prop = &properties [i];
2616 
2617 			*prop = ginfo->properties [i];
2618 
2619 			if (prop->get)
2620 				prop->get = mono_class_inflate_generic_method_full_checked (
2621 					prop->get, klass, mono_class_get_context (klass), &error);
2622 			if (prop->set)
2623 				prop->set = mono_class_inflate_generic_method_full_checked (
2624 					prop->set, klass, mono_class_get_context (klass), &error);
2625 
2626 			g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2627 			prop->parent = klass;
2628 		}
2629 
2630 		first = ginfo->first;
2631 		count = ginfo->count;
2632 	} else {
2633 		first = mono_metadata_properties_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2634 		count = last - first;
2635 
2636 		if (count) {
2637 			mono_class_setup_methods (klass);
2638 			if (mono_class_has_failure (klass))
2639 				return;
2640 		}
2641 
2642 		properties = (MonoProperty *)mono_class_alloc0 (klass, sizeof (MonoProperty) * count);
2643 		for (i = first; i < last; ++i) {
2644 			mono_metadata_decode_table_row (klass->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2645 			properties [i - first].parent = klass;
2646 			properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2647 			properties [i - first].name = mono_metadata_string_heap (klass->image, cols [MONO_PROPERTY_NAME]);
2648 
2649 			startm = mono_metadata_methods_from_property (klass->image, i, &endm);
2650 			int first_idx = mono_class_get_first_method_idx (klass);
2651 			for (j = startm; j < endm; ++j) {
2652 				MonoMethod *method;
2653 
2654 				mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2655 
2656 				if (klass->image->uncompressed_metadata) {
2657 					MonoError error;
2658 					/* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2659 					method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2660 					mono_error_cleanup (&error); /* FIXME don't swallow this error */
2661 				} else {
2662 					method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - first_idx];
2663 				}
2664 
2665 				switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2666 				case METHOD_SEMANTIC_SETTER:
2667 					properties [i - first].set = method;
2668 					break;
2669 				case METHOD_SEMANTIC_GETTER:
2670 					properties [i - first].get = method;
2671 					break;
2672 				default:
2673 					break;
2674 				}
2675 			}
2676 		}
2677 	}
2678 
2679 	info = mono_class_alloc0 (klass, sizeof (MonoClassPropertyInfo));
2680 	info->first = first;
2681 	info->count = count;
2682 	info->properties = properties;
2683 	mono_memory_barrier ();
2684 
2685 	/* This might leak 'info' which was allocated from the image mempool */
2686 	mono_class_set_property_info (klass, info);
2687 }
2688 
2689 static MonoMethod**
inflate_method_listz(MonoMethod ** methods,MonoClass * klass,MonoGenericContext * context)2690 inflate_method_listz (MonoMethod **methods, MonoClass *klass, MonoGenericContext *context)
2691 {
2692 	MonoMethod **om, **retval;
2693 	int count;
2694 
2695 	for (om = methods, count = 0; *om; ++om, ++count)
2696 		;
2697 
2698 	retval = g_new0 (MonoMethod*, count + 1);
2699 	count = 0;
2700 	for (om = methods, count = 0; *om; ++om, ++count) {
2701 		MonoError error;
2702 		retval [count] = mono_class_inflate_generic_method_full_checked (*om, klass, context, &error);
2703 		g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2704 	}
2705 
2706 	return retval;
2707 }
2708 
2709 /*This method can fail the class.*/
2710 static void
mono_class_setup_events(MonoClass * klass)2711 mono_class_setup_events (MonoClass *klass)
2712 {
2713 	int first, count;
2714 	guint startm, endm, i, j;
2715 	guint32 cols [MONO_EVENT_SIZE];
2716 	MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2717 	guint32 last;
2718 	MonoEvent *events;
2719 
2720 	MonoClassEventInfo *info = mono_class_get_event_info (klass);
2721 	if (info)
2722 		return;
2723 
2724 	if (mono_class_is_ginst (klass)) {
2725 		MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2726 		MonoGenericContext *context = NULL;
2727 
2728 		mono_class_setup_events (gklass);
2729 		if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2730 			return;
2731 
2732 		MonoClassEventInfo *ginfo = mono_class_get_event_info (gklass);
2733 		first = ginfo->first;
2734 		count = ginfo->count;
2735 
2736 		events = mono_class_new0 (klass, MonoEvent, count);
2737 
2738 		if (count)
2739 			context = mono_class_get_context (klass);
2740 
2741 		for (i = 0; i < count; i++) {
2742 			MonoError error;
2743 			MonoEvent *event = &events [i];
2744 			MonoEvent *gevent = &ginfo->events [i];
2745 
2746 			error_init (&error); //since we do conditional calls, we must ensure the default value is ok
2747 
2748 			event->parent = klass;
2749 			event->name = gevent->name;
2750 			event->add = gevent->add ? mono_class_inflate_generic_method_full_checked (gevent->add, klass, context, &error) : NULL;
2751 			g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2752 			event->remove = gevent->remove ? mono_class_inflate_generic_method_full_checked (gevent->remove, klass, context, &error) : NULL;
2753 			g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2754 			event->raise = gevent->raise ? mono_class_inflate_generic_method_full_checked (gevent->raise, klass, context, &error) : NULL;
2755 			g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2756 
2757 #ifndef MONO_SMALL_CONFIG
2758 			event->other = gevent->other ? inflate_method_listz (gevent->other, klass, context) : NULL;
2759 #endif
2760 			event->attrs = gevent->attrs;
2761 		}
2762 	} else {
2763 		first = mono_metadata_events_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2764 		count = last - first;
2765 
2766 		if (count) {
2767 			mono_class_setup_methods (klass);
2768 			if (mono_class_has_failure (klass)) {
2769 				return;
2770 			}
2771 		}
2772 
2773 		events = (MonoEvent *)mono_class_alloc0 (klass, sizeof (MonoEvent) * count);
2774 		for (i = first; i < last; ++i) {
2775 			MonoEvent *event = &events [i - first];
2776 
2777 			mono_metadata_decode_table_row (klass->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2778 			event->parent = klass;
2779 			event->attrs = cols [MONO_EVENT_FLAGS];
2780 			event->name = mono_metadata_string_heap (klass->image, cols [MONO_EVENT_NAME]);
2781 
2782 			startm = mono_metadata_methods_from_event (klass->image, i, &endm);
2783 			int first_idx = mono_class_get_first_method_idx (klass);
2784 			for (j = startm; j < endm; ++j) {
2785 				MonoMethod *method;
2786 
2787 				mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2788 
2789 				if (klass->image->uncompressed_metadata) {
2790 					MonoError error;
2791 					/* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2792 					method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2793 					mono_error_cleanup (&error); /* FIXME don't swallow this error */
2794 				} else {
2795 					method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - first_idx];
2796 				}
2797 
2798 				switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2799 				case METHOD_SEMANTIC_ADD_ON:
2800 					event->add = method;
2801 					break;
2802 				case METHOD_SEMANTIC_REMOVE_ON:
2803 					event->remove = method;
2804 					break;
2805 				case METHOD_SEMANTIC_FIRE:
2806 					event->raise = method;
2807 					break;
2808 				case METHOD_SEMANTIC_OTHER: {
2809 #ifndef MONO_SMALL_CONFIG
2810 					int n = 0;
2811 
2812 					if (event->other == NULL) {
2813 						event->other = g_new0 (MonoMethod*, 2);
2814 					} else {
2815 						while (event->other [n])
2816 							n++;
2817 						event->other = (MonoMethod **)g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2818 					}
2819 					event->other [n] = method;
2820 					/* NULL terminated */
2821 					event->other [n + 1] = NULL;
2822 #endif
2823 					break;
2824 				}
2825 				default:
2826 					break;
2827 				}
2828 			}
2829 		}
2830 	}
2831 
2832 	info = mono_class_alloc0 (klass, sizeof (MonoClassEventInfo));
2833 	info->events = events;
2834 	info->first = first;
2835 	info->count = count;
2836 
2837 	mono_memory_barrier ();
2838 
2839 	mono_class_set_event_info (klass, info);
2840 }
2841 
2842 /*
2843  * Global pool of interface IDs, represented as a bitset.
2844  * LOCKING: Protected by the classes lock.
2845  */
2846 static MonoBitSet *global_interface_bitset = NULL;
2847 
2848 /*
2849  * mono_unload_interface_ids:
2850  * @bitset: bit set of interface IDs
2851  *
2852  * When an image is unloaded, the interface IDs associated with
2853  * the image are put back in the global pool of IDs so the numbers
2854  * can be reused.
2855  */
2856 void
mono_unload_interface_ids(MonoBitSet * bitset)2857 mono_unload_interface_ids (MonoBitSet *bitset)
2858 {
2859 	classes_lock ();
2860 	mono_bitset_sub (global_interface_bitset, bitset);
2861 	classes_unlock ();
2862 }
2863 
2864 void
mono_unload_interface_id(MonoClass * klass)2865 mono_unload_interface_id (MonoClass *klass)
2866 {
2867 	if (global_interface_bitset && klass->interface_id) {
2868 		classes_lock ();
2869 		mono_bitset_clear (global_interface_bitset, klass->interface_id);
2870 		classes_unlock ();
2871 	}
2872 }
2873 
2874 /**
2875  * mono_get_unique_iid:
2876  * \param klass interface
2877  *
2878  * Assign a unique integer ID to the interface represented by \p klass.
2879  * The ID will positive and as small as possible.
2880  * LOCKING: Acquires the classes lock.
2881  * \returns The new ID.
2882  */
2883 static guint32
mono_get_unique_iid(MonoClass * klass)2884 mono_get_unique_iid (MonoClass *klass)
2885 {
2886 	int iid;
2887 
2888 	g_assert (MONO_CLASS_IS_INTERFACE (klass));
2889 
2890 	classes_lock ();
2891 
2892 	if (!global_interface_bitset) {
2893 		global_interface_bitset = mono_bitset_new (128, 0);
2894 	}
2895 
2896 	iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2897 	if (iid < 0) {
2898 		int old_size = mono_bitset_size (global_interface_bitset);
2899 		MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2900 		mono_bitset_free (global_interface_bitset);
2901 		global_interface_bitset = new_set;
2902 		iid = old_size;
2903 	}
2904 	mono_bitset_set (global_interface_bitset, iid);
2905 	/* set the bit also in the per-image set */
2906 	if (!mono_class_is_ginst (klass)) {
2907 		if (klass->image->interface_bitset) {
2908 			if (iid >= mono_bitset_size (klass->image->interface_bitset)) {
2909 				MonoBitSet *new_set = mono_bitset_clone (klass->image->interface_bitset, iid + 1);
2910 				mono_bitset_free (klass->image->interface_bitset);
2911 				klass->image->interface_bitset = new_set;
2912 			}
2913 		} else {
2914 			klass->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2915 		}
2916 		mono_bitset_set (klass->image->interface_bitset, iid);
2917 	}
2918 
2919 	classes_unlock ();
2920 
2921 #ifndef MONO_SMALL_CONFIG
2922 	if (mono_print_vtable) {
2923 		int generic_id;
2924 		char *type_name = mono_type_full_name (&klass->byval_arg);
2925 		MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
2926 		if (gklass && !gklass->context.class_inst->is_open) {
2927 			generic_id = gklass->context.class_inst->id;
2928 			g_assert (generic_id != 0);
2929 		} else {
2930 			generic_id = 0;
2931 		}
2932 		printf ("Interface: assigned id %d to %s|%s|%d\n", iid, klass->image->name, type_name, generic_id);
2933 		g_free (type_name);
2934 	}
2935 #endif
2936 
2937 	/* I've confirmed iids safe past 16 bits, however bitset code uses a signed int while testing.
2938 	 * Once this changes, it should be safe for us to allow 2^32-1 interfaces, until then 2^31-2 is the max. */
2939 	g_assert (iid < INT_MAX);
2940 	return iid;
2941 }
2942 
2943 static void
collect_implemented_interfaces_aux(MonoClass * klass,GPtrArray ** res,GHashTable ** ifaces,MonoError * error)2944 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, GHashTable **ifaces, MonoError *error)
2945 {
2946 	int i;
2947 	MonoClass *ic;
2948 
2949 	mono_class_setup_interfaces (klass, error);
2950 	return_if_nok (error);
2951 
2952 	for (i = 0; i < klass->interface_count; i++) {
2953 		ic = klass->interfaces [i];
2954 
2955 		if (*res == NULL)
2956 			*res = g_ptr_array_new ();
2957 		if (*ifaces == NULL)
2958 			*ifaces = g_hash_table_new (NULL, NULL);
2959 		if (g_hash_table_lookup (*ifaces, ic))
2960 			continue;
2961 		/* A gparam is not an implemented interface for the purposes of
2962 		 * mono_class_get_implemented_interfaces */
2963 		if (mono_class_is_gparam (ic))
2964 			continue;
2965 		g_ptr_array_add (*res, ic);
2966 		g_hash_table_insert (*ifaces, ic, ic);
2967 		mono_class_init (ic);
2968 		if (mono_class_has_failure (ic)) {
2969 			mono_error_set_type_load_class (error, ic, "Error Loading class");
2970 			return;
2971 		}
2972 
2973 		collect_implemented_interfaces_aux (ic, res, ifaces, error);
2974 		return_if_nok (error);
2975 	}
2976 }
2977 
2978 GPtrArray*
mono_class_get_implemented_interfaces(MonoClass * klass,MonoError * error)2979 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2980 {
2981 	GPtrArray *res = NULL;
2982 	GHashTable *ifaces = NULL;
2983 
2984 	collect_implemented_interfaces_aux (klass, &res, &ifaces, error);
2985 	if (ifaces)
2986 		g_hash_table_destroy (ifaces);
2987 	if (!mono_error_ok (error)) {
2988 		if (res)
2989 			g_ptr_array_free (res, TRUE);
2990 		return NULL;
2991 	}
2992 	return res;
2993 }
2994 
2995 static int
compare_interface_ids(const void * p_key,const void * p_element)2996 compare_interface_ids (const void *p_key, const void *p_element)
2997 {
2998 	const MonoClass *key = (const MonoClass *)p_key;
2999 	const MonoClass *element = *(const MonoClass **)p_element;
3000 
3001 	return (key->interface_id - element->interface_id);
3002 }
3003 
3004 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
3005 int
mono_class_interface_offset(MonoClass * klass,MonoClass * itf)3006 mono_class_interface_offset (MonoClass *klass, MonoClass *itf)
3007 {
3008 	MonoClass **result = (MonoClass **)mono_binary_search (
3009 			itf,
3010 			klass->interfaces_packed,
3011 			klass->interface_offsets_count,
3012 			sizeof (MonoClass *),
3013 			compare_interface_ids);
3014 	if (result) {
3015 		return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
3016 	} else {
3017 		return -1;
3018 	}
3019 }
3020 
3021 /**
3022  * mono_class_interface_offset_with_variance:
3023  *
3024  * Return the interface offset of \p itf in \p klass. Sets \p non_exact_match to TRUE if the match required variance check
3025  * If \p itf is an interface with generic variant arguments, try to find the compatible one.
3026  *
3027  * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
3028  *
3029  * FIXME figure out MS disambiguation rules and fix this function.
3030  */
3031 int
mono_class_interface_offset_with_variance(MonoClass * klass,MonoClass * itf,gboolean * non_exact_match)3032 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match)
3033 {
3034 	int i = mono_class_interface_offset (klass, itf);
3035 	*non_exact_match = FALSE;
3036 	if (i >= 0)
3037 		return i;
3038 
3039 	if (itf->is_array_special_interface && klass->rank < 2) {
3040 		MonoClass *gtd = mono_class_get_generic_type_definition (itf);
3041 
3042 		for (i = 0; i < klass->interface_offsets_count; i++) {
3043 			// printf ("\t%s\n", mono_type_get_full_name (klass->interfaces_packed [i]));
3044 			if (mono_class_get_generic_type_definition (klass->interfaces_packed [i]) == gtd) {
3045 				*non_exact_match = TRUE;
3046 				return klass->interface_offsets_packed [i];
3047 			}
3048 		}
3049 	}
3050 
3051 	if (!mono_class_has_variant_generic_params (itf))
3052 		return -1;
3053 
3054 	for (i = 0; i < klass->interface_offsets_count; i++) {
3055 		if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
3056 			*non_exact_match = TRUE;
3057 			return klass->interface_offsets_packed [i];
3058 		}
3059 	}
3060 
3061 	return -1;
3062 }
3063 
3064 static void
print_implemented_interfaces(MonoClass * klass)3065 print_implemented_interfaces (MonoClass *klass)
3066 {
3067 	char *name;
3068 	MonoError error;
3069 	GPtrArray *ifaces = NULL;
3070 	int i;
3071 	int ancestor_level = 0;
3072 
3073 	name = mono_type_get_full_name (klass);
3074 	printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
3075 	g_free (name);
3076 
3077 	for (i = 0; i < klass->interface_offsets_count; i++)
3078 		printf ("  [%03d][UUID %03d][SLOT %03d][SIZE  %03d] interface %s.%s\n", i,
3079 				klass->interfaces_packed [i]->interface_id,
3080 				klass->interface_offsets_packed [i],
3081 				mono_class_get_method_count (klass->interfaces_packed [i]),
3082 				klass->interfaces_packed [i]->name_space,
3083 				klass->interfaces_packed [i]->name );
3084 	printf ("Interface flags: ");
3085 	for (i = 0; i <= klass->max_interface_id; i++)
3086 		if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
3087 			printf ("(%d,T)", i);
3088 		else
3089 			printf ("(%d,F)", i);
3090 	printf ("\n");
3091 	printf ("Dump interface flags:");
3092 #ifdef COMPRESSED_INTERFACE_BITMAP
3093 	{
3094 		const uint8_t* p = klass->interface_bitmap;
3095 		i = klass->max_interface_id;
3096 		while (i > 0) {
3097 			printf (" %d x 00 %02X", p [0], p [1]);
3098 			i -= p [0] * 8;
3099 			i -= 8;
3100 		}
3101 	}
3102 #else
3103 	for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
3104 		printf (" %02X", klass->interface_bitmap [i]);
3105 #endif
3106 	printf ("\n");
3107 	while (klass != NULL) {
3108 		printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
3109 		ifaces = mono_class_get_implemented_interfaces (klass, &error);
3110 		if (!mono_error_ok (&error)) {
3111 			printf ("  Type failed due to %s\n", mono_error_get_message (&error));
3112 			mono_error_cleanup (&error);
3113 		} else if (ifaces) {
3114 			for (i = 0; i < ifaces->len; i++) {
3115 				MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3116 				printf ("  [UIID %d] interface %s\n", ic->interface_id, ic->name);
3117 				printf ("  [%03d][UUID %03d][SLOT %03d][SIZE  %03d] interface %s.%s\n", i,
3118 						ic->interface_id,
3119 						mono_class_interface_offset (klass, ic),
3120 						mono_class_get_method_count (ic),
3121 						ic->name_space,
3122 						ic->name );
3123 			}
3124 			g_ptr_array_free (ifaces, TRUE);
3125 		}
3126 		ancestor_level ++;
3127 		klass = klass->parent;
3128 	}
3129 }
3130 
3131 /*
3132  * Return the number of virtual methods.
3133  * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3134  * Return -1 on failure.
3135  * FIXME It would be nice if this information could be cached somewhere.
3136  */
3137 static int
count_virtual_methods(MonoClass * klass)3138 count_virtual_methods (MonoClass *klass)
3139 {
3140 	int i, mcount, vcount = 0;
3141 	guint32 flags;
3142 	klass = mono_class_get_generic_type_definition (klass); /*We can find this information by looking at the GTD*/
3143 
3144 	if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
3145 		mono_class_setup_methods (klass);
3146 		if (mono_class_has_failure (klass))
3147 			return -1;
3148 
3149 		mcount = mono_class_get_method_count (klass);
3150 		for (i = 0; i < mcount; ++i) {
3151 			flags = klass->methods [i]->flags;
3152 			if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3153 				++vcount;
3154 		}
3155 	} else {
3156 		int first_idx = mono_class_get_first_method_idx (klass);
3157 		mcount = mono_class_get_method_count (klass);
3158 		for (i = 0; i < mcount; ++i) {
3159 			flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, first_idx + i, MONO_METHOD_FLAGS);
3160 
3161 			if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3162 				++vcount;
3163 		}
3164 	}
3165 	return vcount;
3166 }
3167 
3168 static int
find_interface(int num_ifaces,MonoClass ** interfaces_full,MonoClass * ic)3169 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3170 {
3171 	int m, l = 0;
3172 	if (!num_ifaces)
3173 		return -1;
3174 	while (1) {
3175 		if (l > num_ifaces)
3176 			return -1;
3177 		m = (l + num_ifaces) / 2;
3178 		if (interfaces_full [m] == ic)
3179 			return m;
3180 		if (l == num_ifaces)
3181 			return -1;
3182 		if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3183 			num_ifaces = m - 1;
3184 		} else {
3185 			l =  m + 1;
3186 		}
3187 	}
3188 }
3189 
3190 static mono_bool
set_interface_and_offset(int num_ifaces,MonoClass ** interfaces_full,int * interface_offsets_full,MonoClass * ic,int offset,mono_bool force_set)3191 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3192 {
3193 	int i = find_interface (num_ifaces, interfaces_full, ic);
3194 	if (i >= 0) {
3195 		if (!force_set)
3196 			return TRUE;
3197 		interface_offsets_full [i] = offset;
3198 		return FALSE;
3199 	}
3200 	for (i = 0; i < num_ifaces; ++i) {
3201 		if (interfaces_full [i]) {
3202 			int end;
3203 			if (interfaces_full [i]->interface_id < ic->interface_id)
3204 				continue;
3205 			end = i + 1;
3206 			while (end < num_ifaces && interfaces_full [end]) end++;
3207 			memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3208 			memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3209 		}
3210 		interfaces_full [i] = ic;
3211 		interface_offsets_full [i] = offset;
3212 		break;
3213 	}
3214 	return FALSE;
3215 }
3216 
3217 #ifdef COMPRESSED_INTERFACE_BITMAP
3218 
3219 /*
3220  * Compressed interface bitmap design.
3221  *
3222  * Interface bitmaps take a large amount of memory, because their size is
3223  * linear with the maximum interface id assigned in the process (each interface
3224  * is assigned a unique id as it is loaded). The number of interface classes
3225  * is high because of the many implicit interfaces implemented by arrays (we'll
3226  * need to lazy-load them in the future).
3227  * Most classes implement a very small number of interfaces, so the bitmap is
3228  * sparse. This bitmap needs to be checked by interface casts, so access to the
3229  * needed bit must be fast and doable with few jit instructions.
3230  *
3231  * The current compression format is as follows:
3232  * *) it is a sequence of one or more two-byte elements
3233  * *) the first byte in the element is the count of empty bitmap bytes
3234  * at the current bitmap position
3235  * *) the second byte in the element is an actual bitmap byte at the current
3236  * bitmap position
3237  *
3238  * As an example, the following compressed bitmap bytes:
3239  * 	0x07 0x01 0x00 0x7
3240  * correspond to the following bitmap:
3241  * 	0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3242  *
3243  * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3244  * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3245  * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3246  */
3247 
3248 /**
3249  * mono_compress_bitmap:
3250  * \param dest destination buffer
3251  * \param bitmap bitmap buffer
3252  * \param size size of \p bitmap in bytes
3253  *
3254  * This is a mono internal function.
3255  * The \p bitmap data is compressed into a format that is small but
3256  * still searchable in few instructions by the JIT and runtime.
3257  * The compressed data is stored in the buffer pointed to by the
3258  * \p dest array. Passing a NULL value for \p dest allows to just compute
3259  * the size of the buffer.
3260  * This compression algorithm assumes the bits set in the bitmap are
3261  * few and far between, like in interface bitmaps.
3262  * \returns The size of the compressed bitmap in bytes.
3263  */
3264 int
mono_compress_bitmap(uint8_t * dest,const uint8_t * bitmap,int size)3265 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3266 {
3267 	int numz = 0;
3268 	int res = 0;
3269 	const uint8_t *end = bitmap + size;
3270 	while (bitmap < end) {
3271 		if (*bitmap || numz == 255) {
3272 			if (dest) {
3273 				*dest++ = numz;
3274 				*dest++ = *bitmap;
3275 			}
3276 			res += 2;
3277 			numz = 0;
3278 			bitmap++;
3279 			continue;
3280 		}
3281 		bitmap++;
3282 		numz++;
3283 	}
3284 	if (numz) {
3285 		res += 2;
3286 		if (dest) {
3287 			*dest++ = numz;
3288 			*dest++ = 0;
3289 		}
3290 	}
3291 	return res;
3292 }
3293 
3294 /**
3295  * mono_class_interface_match:
3296  * \param bitmap a compressed bitmap buffer
3297  * \param id the index to check in the bitmap
3298  *
3299  * This is a mono internal function.
3300  * Checks if a bit is set in a compressed interface bitmap. \p id must
3301  * be already checked for being smaller than the maximum id encoded in the
3302  * bitmap.
3303  *
3304  * \returns A non-zero value if bit \p id is set in the bitmap \p bitmap,
3305  * FALSE otherwise.
3306  */
3307 int
mono_class_interface_match(const uint8_t * bitmap,int id)3308 mono_class_interface_match (const uint8_t *bitmap, int id)
3309 {
3310 	while (TRUE) {
3311 		id -= bitmap [0] * 8;
3312 		if (id < 8) {
3313 			if (id < 0)
3314 				return 0;
3315 			return bitmap [1] & (1 << id);
3316 		}
3317 		bitmap += 2;
3318 		id -= 8;
3319 	}
3320 }
3321 #endif
3322 
3323 /*
3324  * Return -1 on failure and set klass->has_failure and store a MonoErrorBoxed with the details.
3325  * LOCKING: Acquires the loader lock.
3326  */
3327 static int
setup_interface_offsets(MonoClass * klass,int cur_slot,gboolean overwrite)3328 setup_interface_offsets (MonoClass *klass, int cur_slot, gboolean overwrite)
3329 {
3330 	MonoError error;
3331 	MonoClass *k, *ic;
3332 	int i, j, num_ifaces;
3333 	guint32 max_iid;
3334 	MonoClass **interfaces_full = NULL;
3335 	int *interface_offsets_full = NULL;
3336 	GPtrArray *ifaces;
3337 	GPtrArray **ifaces_array = NULL;
3338 	int interface_offsets_count;
3339 
3340 	mono_loader_lock ();
3341 
3342 	mono_class_setup_supertypes (klass);
3343 
3344 	/* compute maximum number of slots and maximum interface id */
3345 	max_iid = 0;
3346 	num_ifaces = 0; /* this can include duplicated ones */
3347 	ifaces_array = g_new0 (GPtrArray *, klass->idepth);
3348 	for (j = 0; j < klass->idepth; j++) {
3349 		k = klass->supertypes [j];
3350 		g_assert (k);
3351 		num_ifaces += k->interface_count;
3352 		for (i = 0; i < k->interface_count; i++) {
3353 			ic = k->interfaces [i];
3354 
3355 			/* A gparam does not have any interface_id set. */
3356 			if (! mono_class_is_gparam (ic))
3357 				mono_class_init (ic);
3358 
3359 			if (max_iid < ic->interface_id)
3360 				max_iid = ic->interface_id;
3361 		}
3362 		ifaces = mono_class_get_implemented_interfaces (k, &error);
3363 		if (!mono_error_ok (&error)) {
3364 			char *name = mono_type_get_full_name (k);
3365 			mono_class_set_type_load_failure (klass, "Error getting the interfaces of %s due to %s", name, mono_error_get_message (&error));
3366 			g_free (name);
3367 			mono_error_cleanup (&error);
3368 			cur_slot = -1;
3369 			goto end;
3370 		}
3371 		if (ifaces) {
3372 			num_ifaces += ifaces->len;
3373 			for (i = 0; i < ifaces->len; ++i) {
3374 				ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3375 				if (max_iid < ic->interface_id)
3376 					max_iid = ic->interface_id;
3377 			}
3378 			ifaces_array [j] = ifaces;
3379 		}
3380 	}
3381 
3382 	if (MONO_CLASS_IS_INTERFACE (klass)) {
3383 		num_ifaces++;
3384 		if (max_iid < klass->interface_id)
3385 			max_iid = klass->interface_id;
3386 	}
3387 
3388 	/* compute vtable offset for interfaces */
3389 	interfaces_full = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3390 	interface_offsets_full = (int *)g_malloc (sizeof (int) * num_ifaces);
3391 
3392 	for (i = 0; i < num_ifaces; i++)
3393 		interface_offsets_full [i] = -1;
3394 
3395 	/* skip the current class */
3396 	for (j = 0; j < klass->idepth - 1; j++) {
3397 		k = klass->supertypes [j];
3398 		ifaces = ifaces_array [j];
3399 
3400 		if (ifaces) {
3401 			for (i = 0; i < ifaces->len; ++i) {
3402 				int io;
3403 				ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3404 
3405 				/*Force the sharing of interface offsets between parent and subtypes.*/
3406 				io = mono_class_interface_offset (k, ic);
3407 				g_assert (io >= 0);
3408 				set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3409 			}
3410 		}
3411 	}
3412 
3413 	g_assert (klass == klass->supertypes [klass->idepth - 1]);
3414 	ifaces = ifaces_array [klass->idepth - 1];
3415 	if (ifaces) {
3416 		for (i = 0; i < ifaces->len; ++i) {
3417 			int count;
3418 			ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3419 			if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3420 				continue;
3421 			count = count_virtual_methods (ic);
3422 			if (count == -1) {
3423 				char *name = mono_type_get_full_name (ic);
3424 				mono_class_set_type_load_failure (klass, "Error calculating interface offset of %s", name);
3425 				g_free (name);
3426 				cur_slot = -1;
3427 				goto end;
3428 			}
3429 			cur_slot += count;
3430 		}
3431 	}
3432 
3433 	if (MONO_CLASS_IS_INTERFACE (klass))
3434 		set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, klass, cur_slot, TRUE);
3435 
3436 	for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3437 		if (interface_offsets_full [i] != -1)
3438 			interface_offsets_count ++;
3439 	}
3440 
3441 	/* Publish the data */
3442 	klass->max_interface_id = max_iid;
3443 	/*
3444 	 * We might get called multiple times:
3445 	 * - mono_class_init ()
3446 	 * - mono_class_setup_vtable ().
3447 	 * - mono_class_setup_interface_offsets ().
3448 	 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3449 	 * means we have to overwrite those when called from other places (#4440).
3450 	 */
3451 	if (klass->interfaces_packed) {
3452 		if (!overwrite)
3453 			g_assert (klass->interface_offsets_count == interface_offsets_count);
3454 	} else {
3455 		uint8_t *bitmap;
3456 		int bsize;
3457 		klass->interface_offsets_count = interface_offsets_count;
3458 		klass->interfaces_packed = (MonoClass **)mono_class_alloc (klass, sizeof (MonoClass*) * interface_offsets_count);
3459 		klass->interface_offsets_packed = (guint16 *)mono_class_alloc (klass, sizeof (guint16) * interface_offsets_count);
3460 		bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3461 #ifdef COMPRESSED_INTERFACE_BITMAP
3462 		bitmap = g_malloc0 (bsize);
3463 #else
3464 		bitmap = (uint8_t *)mono_class_alloc0 (klass, bsize);
3465 #endif
3466 		for (i = 0; i < interface_offsets_count; i++) {
3467 			guint32 id = interfaces_full [i]->interface_id;
3468 			bitmap [id >> 3] |= (1 << (id & 7));
3469 			klass->interfaces_packed [i] = interfaces_full [i];
3470 			klass->interface_offsets_packed [i] = interface_offsets_full [i];
3471 		}
3472 #ifdef COMPRESSED_INTERFACE_BITMAP
3473 		i = mono_compress_bitmap (NULL, bitmap, bsize);
3474 		klass->interface_bitmap = mono_class_alloc0 (klass, i);
3475 		mono_compress_bitmap (klass->interface_bitmap, bitmap, bsize);
3476 		g_free (bitmap);
3477 #else
3478 		klass->interface_bitmap = bitmap;
3479 #endif
3480 	}
3481 end:
3482 	mono_loader_unlock ();
3483 
3484 	g_free (interfaces_full);
3485 	g_free (interface_offsets_full);
3486 	for (i = 0; i < klass->idepth; i++) {
3487 		ifaces = ifaces_array [i];
3488 		if (ifaces)
3489 			g_ptr_array_free (ifaces, TRUE);
3490 	}
3491 	g_free (ifaces_array);
3492 
3493 	//printf ("JUST DONE: ");
3494 	//print_implemented_interfaces (klass);
3495 
3496  	return cur_slot;
3497 }
3498 
3499 /*
3500  * Setup interface offsets for interfaces.
3501  * Initializes:
3502  * - klass->max_interface_id
3503  * - klass->interface_offsets_count
3504  * - klass->interfaces_packed
3505  * - klass->interface_offsets_packed
3506  * - klass->interface_bitmap
3507  *
3508  * This function can fail @class.
3509  *
3510  */
3511 void
mono_class_setup_interface_offsets(MonoClass * klass)3512 mono_class_setup_interface_offsets (MonoClass *klass)
3513 {
3514 	/* NOTE: This function is only correct for interfaces.
3515 	 *
3516 	 * It assumes that klass's interfaces can be assigned offsets starting
3517 	 * from 0. That assumption is incorrect for classes and valuetypes.
3518 	 */
3519 	g_assert (MONO_CLASS_IS_INTERFACE (klass) && !mono_class_is_ginst (klass));
3520 	setup_interface_offsets (klass, 0, FALSE);
3521 }
3522 
3523 /*Checks if @klass has @parent as one of it's parents type gtd
3524  *
3525  * For example:
3526  * 	Foo<T>
3527  *	Bar<T> : Foo<Bar<Bar<T>>>
3528  *
3529  */
3530 static gboolean
mono_class_has_gtd_parent(MonoClass * klass,MonoClass * parent)3531 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3532 {
3533 	klass = mono_class_get_generic_type_definition (klass);
3534 	parent = mono_class_get_generic_type_definition (parent);
3535 	mono_class_setup_supertypes (klass);
3536 	mono_class_setup_supertypes (parent);
3537 
3538 	return klass->idepth >= parent->idepth &&
3539 		mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3540 }
3541 
3542 gboolean
mono_class_check_vtable_constraints(MonoClass * klass,GList * in_setup)3543 mono_class_check_vtable_constraints (MonoClass *klass, GList *in_setup)
3544 {
3545 	MonoGenericInst *ginst;
3546 	int i;
3547 
3548 	if (!mono_class_is_ginst (klass)) {
3549 		mono_class_setup_vtable_full (klass, in_setup);
3550 		return !mono_class_has_failure (klass);
3551 	}
3552 
3553 	mono_class_setup_vtable_full (mono_class_get_generic_type_definition (klass), in_setup);
3554 	if (mono_class_set_type_load_failure_causedby_class (klass, mono_class_get_generic_class (klass)->container_class, "Failed to load generic definition vtable"))
3555 		return FALSE;
3556 
3557 	ginst = mono_class_get_generic_class (klass)->context.class_inst;
3558 	for (i = 0; i < ginst->type_argc; ++i) {
3559 		MonoClass *arg;
3560 		if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3561 			continue;
3562 		arg = mono_class_from_mono_type (ginst->type_argv [i]);
3563 		/*Those 2 will be checked by mono_class_setup_vtable itself*/
3564 		if (mono_class_has_gtd_parent (klass, arg) || mono_class_has_gtd_parent (arg, klass))
3565 			continue;
3566 		if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3567 			mono_class_set_type_load_failure (klass, "Failed to load generic parameter %d", i);
3568 			return FALSE;
3569 		}
3570 	}
3571 	return TRUE;
3572 }
3573 
3574 /*
3575  * mono_class_setup_vtable:
3576  *
3577  *   Creates the generic vtable of CLASS.
3578  * Initializes the following fields in MonoClass:
3579  * - vtable
3580  * - vtable_size
3581  * Plus all the fields initialized by setup_interface_offsets ().
3582  * If there is an error during vtable construction, klass->has_failure
3583  * is set and details are stored in a MonoErrorBoxed.
3584  *
3585  * LOCKING: Acquires the loader lock.
3586  */
3587 void
mono_class_setup_vtable(MonoClass * klass)3588 mono_class_setup_vtable (MonoClass *klass)
3589 {
3590 	mono_class_setup_vtable_full (klass, NULL);
3591 }
3592 
3593 static void
mono_class_setup_vtable_full(MonoClass * klass,GList * in_setup)3594 mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup)
3595 {
3596 	MonoError error;
3597 	MonoMethod **overrides;
3598 	MonoGenericContext *context;
3599 	guint32 type_token;
3600 	int onum = 0;
3601 	gboolean ok = TRUE;
3602 
3603 	if (klass->vtable)
3604 		return;
3605 
3606 	if (MONO_CLASS_IS_INTERFACE (klass)) {
3607 		/* This sets method->slot for all methods if this is an interface */
3608 		mono_class_setup_methods (klass);
3609 		return;
3610 	}
3611 
3612 	if (mono_class_has_failure (klass))
3613 		return;
3614 
3615 	if (g_list_find (in_setup, klass))
3616 		return;
3617 
3618 	mono_loader_lock ();
3619 
3620 	if (klass->vtable) {
3621 		mono_loader_unlock ();
3622 		return;
3623 	}
3624 
3625 	UnlockedIncrement (&mono_stats.generic_vtable_count);
3626 	in_setup = g_list_prepend (in_setup, klass);
3627 
3628 	if (mono_class_is_ginst (klass)) {
3629 		if (!mono_class_check_vtable_constraints (klass, in_setup)) {
3630 			mono_loader_unlock ();
3631 			g_list_remove (in_setup, klass);
3632 			return;
3633 		}
3634 
3635 		context = mono_class_get_context (klass);
3636 		type_token = mono_class_get_generic_class (klass)->container_class->type_token;
3637 	} else {
3638 		context = (MonoGenericContext *) mono_class_try_get_generic_container (klass); //FIXME is this a case of a try?
3639 		type_token = klass->type_token;
3640 	}
3641 
3642 	if (image_is_dynamic (klass->image)) {
3643 		/* Generic instances can have zero method overrides without causing any harm.
3644 		 * This is true since we don't do layout all over again for them, we simply inflate
3645 		 * the layout of the parent.
3646 		 */
3647 		mono_reflection_get_dynamic_overrides (klass, &overrides, &onum, &error);
3648 		if (!is_ok (&error)) {
3649 			mono_loader_unlock ();
3650 			g_list_remove (in_setup, klass);
3651 			mono_class_set_type_load_failure (klass, "Could not load list of method overrides due to %s", mono_error_get_message (&error));
3652 			mono_error_cleanup (&error);
3653 			return;
3654 		}
3655 	} else {
3656 		/* The following call fails if there are missing methods in the type */
3657 		/* FIXME it's probably a good idea to avoid this for generic instances. */
3658 		ok = mono_class_get_overrides_full (klass->image, type_token, &overrides, &onum, context);
3659 	}
3660 
3661 	if (ok)
3662 		mono_class_setup_vtable_general (klass, overrides, onum, in_setup);
3663 	else
3664 		mono_class_set_type_load_failure (klass, "Could not load list of method overrides");
3665 
3666 	g_free (overrides);
3667 
3668 	mono_loader_unlock ();
3669 	g_list_remove (in_setup, klass);
3670 
3671 	return;
3672 }
3673 
3674 #define DEBUG_INTERFACE_VTABLE_CODE 0
3675 #define TRACE_INTERFACE_VTABLE_CODE 0
3676 #define VERIFY_INTERFACE_VTABLE_CODE 0
3677 #define VTABLE_SELECTOR (1)
3678 
3679 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3680 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3681 	if (!(VTABLE_SELECTOR)) break; \
3682 	stmt;\
3683 } while (0)
3684 #else
3685 #define DEBUG_INTERFACE_VTABLE(stmt)
3686 #endif
3687 
3688 #if TRACE_INTERFACE_VTABLE_CODE
3689 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3690 	if (!(VTABLE_SELECTOR)) break; \
3691 	stmt;\
3692 } while (0)
3693 #else
3694 #define TRACE_INTERFACE_VTABLE(stmt)
3695 #endif
3696 
3697 #if VERIFY_INTERFACE_VTABLE_CODE
3698 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3699 	if (!(VTABLE_SELECTOR)) break; \
3700 	stmt;\
3701 } while (0)
3702 #else
3703 #define VERIFY_INTERFACE_VTABLE(stmt)
3704 #endif
3705 
3706 
3707 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3708 static char*
mono_signature_get_full_desc(MonoMethodSignature * sig,gboolean include_namespace)3709 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3710 {
3711 	int i;
3712 	char *result;
3713 	GString *res = g_string_new ("");
3714 
3715 	g_string_append_c (res, '(');
3716 	for (i = 0; i < sig->param_count; ++i) {
3717 		if (i > 0)
3718 			g_string_append_c (res, ',');
3719 		mono_type_get_desc (res, sig->params [i], include_namespace);
3720 	}
3721 	g_string_append (res, ")=>");
3722 	if (sig->ret != NULL) {
3723 		mono_type_get_desc (res, sig->ret, include_namespace);
3724 	} else {
3725 		g_string_append (res, "NULL");
3726 	}
3727 	result = res->str;
3728 	g_string_free (res, FALSE);
3729 	return result;
3730 }
3731 static void
print_method_signatures(MonoMethod * im,MonoMethod * cm)3732 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3733 	char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3734 	char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3735 	printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
3736 	g_free (im_sig);
3737 	g_free (cm_sig);
3738 
3739 }
3740 
3741 #endif
3742 static gboolean
is_wcf_hack_disabled(void)3743 is_wcf_hack_disabled (void)
3744 {
3745 	static gboolean disabled;
3746 	static gboolean inited = FALSE;
3747 	if (!inited) {
3748 		disabled = g_hasenv ("MONO_DISABLE_WCF_HACK");
3749 		inited = TRUE;
3750 	}
3751 	return disabled;
3752 }
3753 
3754 static gboolean
check_interface_method_override(MonoClass * klass,MonoMethod * im,MonoMethod * cm,gboolean require_newslot,gboolean interface_is_explicitly_implemented_by_class,gboolean slot_is_empty)3755 check_interface_method_override (MonoClass *klass, MonoMethod *im, MonoMethod *cm, gboolean require_newslot, gboolean interface_is_explicitly_implemented_by_class, gboolean slot_is_empty)
3756 {
3757 	MonoMethodSignature *cmsig, *imsig;
3758 	if (strcmp (im->name, cm->name) == 0) {
3759 		if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
3760 			TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
3761 			return FALSE;
3762 		}
3763 		if (! slot_is_empty) {
3764 			if (require_newslot) {
3765 				if (! interface_is_explicitly_implemented_by_class) {
3766 					TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
3767 					return FALSE;
3768 				}
3769 				if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
3770 					TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
3771 					return FALSE;
3772 				}
3773 			} else {
3774 				TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
3775 			}
3776 		}
3777 		cmsig = mono_method_signature (cm);
3778 		imsig = mono_method_signature (im);
3779 		if (!cmsig || !imsig) {
3780 			mono_class_set_type_load_failure (klass, "Could not resolve the signature of a virtual method");
3781 			return FALSE;
3782 		}
3783 
3784 		if (! mono_metadata_signature_equal (cmsig, imsig)) {
3785 			TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED  "));
3786 			TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3787 			TRACE_INTERFACE_VTABLE (printf ("]"));
3788 			return FALSE;
3789 		}
3790 		TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
3791 		if (mono_security_core_clr_enabled ())
3792 			mono_security_core_clr_check_override (klass, cm, im);
3793 
3794 		TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
3795 		if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3796 			char *body_name = mono_method_full_name (cm, TRUE);
3797 			char *decl_name = mono_method_full_name (im, TRUE);
3798 			mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
3799 			g_free (body_name);
3800 			g_free (decl_name);
3801 			return FALSE;
3802 		}
3803 
3804 		return TRUE;
3805 	} else {
3806 		MonoClass *ic = im->klass;
3807 		const char *ic_name_space = ic->name_space;
3808 		const char *ic_name = ic->name;
3809 		char *subname;
3810 
3811 		if (! require_newslot) {
3812 			TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
3813 			return FALSE;
3814 		}
3815 		if (cm->klass->rank == 0) {
3816 			TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
3817 			return FALSE;
3818 		}
3819 		cmsig = mono_method_signature (cm);
3820 		imsig = mono_method_signature (im);
3821 		if (!cmsig || !imsig) {
3822 			mono_class_set_type_load_failure (klass, "Could not resolve the signature of a virtual method");
3823 			return FALSE;
3824 		}
3825 
3826 		if (! mono_metadata_signature_equal (cmsig, imsig)) {
3827 			TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED  "));
3828 			TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3829 			TRACE_INTERFACE_VTABLE (printf ("]"));
3830 			return FALSE;
3831 		}
3832 		if (mono_class_get_image (ic) != mono_defaults.corlib) {
3833 			TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
3834 			return FALSE;
3835 		}
3836 		if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
3837 			TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
3838 			return FALSE;
3839 		}
3840 		if ((ic_name == NULL) || ((strcmp (ic_name, "IEnumerable`1") != 0) && (strcmp (ic_name, "ICollection`1") != 0) && (strcmp (ic_name, "IList`1") != 0) && (strcmp (ic_name, "IReadOnlyList`1") != 0) && (strcmp (ic_name, "IReadOnlyCollection`1") != 0))) {
3841 			TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
3842 			return FALSE;
3843 		}
3844 
3845 		subname = strstr (cm->name, ic_name_space);
3846 		if (subname != cm->name) {
3847 			TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
3848 			return FALSE;
3849 		}
3850 		subname += strlen (ic_name_space);
3851 		if (subname [0] != '.') {
3852 			TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
3853 			return FALSE;
3854 		}
3855 		subname ++;
3856 		if (strstr (subname, ic_name) != subname) {
3857 			TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
3858 			return FALSE;
3859 		}
3860 		subname += strlen (ic_name);
3861 		if (subname [0] != '.') {
3862 			TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
3863 			return FALSE;
3864 		}
3865 		subname ++;
3866 		if (strcmp (subname, im->name) != 0) {
3867 			TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
3868 			return FALSE;
3869 		}
3870 
3871 		TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
3872 		if (mono_security_core_clr_enabled ())
3873 			mono_security_core_clr_check_override (klass, cm, im);
3874 
3875 		TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
3876 		if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3877 			char *body_name = mono_method_full_name (cm, TRUE);
3878 			char *decl_name = mono_method_full_name (im, TRUE);
3879 			mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
3880 			g_free (body_name);
3881 			g_free (decl_name);
3882 			return FALSE;
3883 		}
3884 
3885 		return TRUE;
3886 	}
3887 }
3888 
3889 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3890 static void
foreach_override(gpointer key,gpointer value,gpointer user_data)3891 foreach_override (gpointer key, gpointer value, gpointer user_data) {
3892 	MonoMethod *method = key;
3893 	MonoMethod *override = value;
3894 	MonoClass *method_class = mono_method_get_class (method);
3895 	MonoClass *override_class = mono_method_get_class (override);
3896 
3897 	printf ("  Method '%s.%s:%s' has override '%s.%s:%s'\n",
3898 			mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
3899 			mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
3900 }
3901 static void
print_overrides(GHashTable * override_map,const char * message)3902 print_overrides (GHashTable *override_map, const char *message) {
3903 	if (override_map) {
3904 		printf ("Override map \"%s\" START:\n", message);
3905 		g_hash_table_foreach (override_map, foreach_override, NULL);
3906 		printf ("Override map \"%s\" END.\n", message);
3907 	} else {
3908 		printf ("Override map \"%s\" EMPTY.\n", message);
3909 	}
3910 }
3911 static void
print_vtable_full(MonoClass * klass,MonoMethod ** vtable,int size,int first_non_interface_slot,const char * message,gboolean print_interfaces)3912 print_vtable_full (MonoClass *klass, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
3913 	char *full_name = mono_type_full_name (&klass->byval_arg);
3914 	int i;
3915 	int parent_size;
3916 
3917 	printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
3918 
3919 	if (print_interfaces) {
3920 		print_implemented_interfaces (klass);
3921 		printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
3922 	}
3923 
3924 	if (klass->parent) {
3925 		parent_size = klass->parent->vtable_size;
3926 	} else {
3927 		parent_size = 0;
3928 	}
3929 	for (i = 0; i < size; ++i) {
3930 		MonoMethod *cm = vtable [i];
3931 		char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
3932 		char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
3933 
3934 		printf ("  [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
3935 		g_free (cm_name);
3936 	}
3937 
3938 	g_free (full_name);
3939 }
3940 #endif
3941 
3942 #if VERIFY_INTERFACE_VTABLE_CODE
3943 static int
mono_method_try_get_vtable_index(MonoMethod * method)3944 mono_method_try_get_vtable_index (MonoMethod *method)
3945 {
3946 	if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
3947 		MonoMethodInflated *imethod = (MonoMethodInflated*)method;
3948 		if (imethod->declaring->is_generic)
3949 			return imethod->declaring->slot;
3950 	}
3951 	return method->slot;
3952 }
3953 
3954 static void
mono_class_verify_vtable(MonoClass * klass)3955 mono_class_verify_vtable (MonoClass *klass)
3956 {
3957 	int i, count;
3958 	char *full_name = mono_type_full_name (&klass->byval_arg);
3959 
3960 	printf ("*** Verifying VTable of class '%s' \n", full_name);
3961 	g_free (full_name);
3962 	full_name = NULL;
3963 
3964 	if (!klass->methods)
3965 		return;
3966 
3967 	count = mono_class_get_method_count (klass);
3968 	for (i = 0; i < count; ++i) {
3969 		MonoMethod *cm = klass->methods [i];
3970 		int slot;
3971 
3972 		if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
3973 			continue;
3974 
3975 		g_free (full_name);
3976 		full_name = mono_method_full_name (cm, TRUE);
3977 
3978 		slot = mono_method_try_get_vtable_index (cm);
3979 		if (slot >= 0) {
3980 			if (slot >= klass->vtable_size) {
3981 				printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, klass->vtable_size);
3982 				continue;
3983 			}
3984 
3985 			if (slot >= 0 && klass->vtable [slot] != cm && (klass->vtable [slot])) {
3986 				char *other_name = klass->vtable [slot] ? mono_method_full_name (klass->vtable [slot], TRUE) : g_strdup ("[null value]");
3987 				printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
3988 				g_free (other_name);
3989 			}
3990 		} else
3991 			printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
3992 	}
3993 	g_free (full_name);
3994 }
3995 #endif
3996 
3997 static void
print_unimplemented_interface_method_info(MonoClass * klass,MonoClass * ic,MonoMethod * im,int im_slot,MonoMethod ** overrides,int onum)3998 print_unimplemented_interface_method_info (MonoClass *klass, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum)
3999 {
4000 	int index, mcount;
4001 	char *method_signature;
4002 	char *type_name;
4003 
4004 	for (index = 0; index < onum; ++index) {
4005 		mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)", im_slot, overrides [index*2+1]->name,
4006 			 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
4007 	}
4008 	method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
4009 	type_name = mono_type_full_name (&klass->byval_arg);
4010 	mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s",
4011 		mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
4012 	g_free (method_signature);
4013 	g_free (type_name);
4014 	mono_class_setup_methods (klass);
4015 	if (mono_class_has_failure (klass)) {
4016 		char *name = mono_type_get_full_name (klass);
4017 		mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods", name);
4018 		g_free (name);
4019 		return;
4020 	}
4021 	mcount = mono_class_get_method_count (klass);
4022 	for (index = 0; index < mcount; ++index) {
4023 		MonoMethod *cm = klass->methods [index];
4024 		method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
4025 
4026 		mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)", cm->name, method_signature);
4027 		g_free (method_signature);
4028 	}
4029 }
4030 
4031 static MonoMethod*
mono_method_get_method_definition(MonoMethod * method)4032 mono_method_get_method_definition (MonoMethod *method)
4033 {
4034 	while (method->is_inflated)
4035 		method = ((MonoMethodInflated*)method)->declaring;
4036 	return method;
4037 }
4038 
4039 static gboolean
verify_class_overrides(MonoClass * klass,MonoMethod ** overrides,int onum)4040 verify_class_overrides (MonoClass *klass, MonoMethod **overrides, int onum)
4041 {
4042 	int i;
4043 
4044 	for (i = 0; i < onum; ++i) {
4045 		MonoMethod *decl = overrides [i * 2];
4046 		MonoMethod *body = overrides [i * 2 + 1];
4047 
4048 		if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (klass)) {
4049 			mono_class_set_type_load_failure (klass, "Method belongs to a different class than the declared one");
4050 			return FALSE;
4051 		}
4052 
4053 		if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4054 			if (body->flags & METHOD_ATTRIBUTE_STATIC)
4055 				mono_class_set_type_load_failure (klass, "Method must not be static to override a base type");
4056 			else
4057 				mono_class_set_type_load_failure (klass, "Method must be virtual to override a base type");
4058 			return FALSE;
4059 		}
4060 
4061 		if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4062 			if (body->flags & METHOD_ATTRIBUTE_STATIC)
4063 				mono_class_set_type_load_failure (klass, "Cannot override a static method in a base type");
4064 			else
4065 				mono_class_set_type_load_failure (klass, "Cannot override a non virtual method in a base type");
4066 			return FALSE;
4067 		}
4068 
4069 		if (!mono_class_is_assignable_from_slow (decl->klass, klass)) {
4070 			mono_class_set_type_load_failure (klass, "Method overrides a class or interface that is not extended or implemented by this type");
4071 			return FALSE;
4072 		}
4073 
4074 		body = mono_method_get_method_definition (body);
4075 		decl = mono_method_get_method_definition (decl);
4076 
4077 		if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4078 			char *body_name = mono_method_full_name (body, TRUE);
4079 			char *decl_name = mono_method_full_name (decl, TRUE);
4080 			mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4081 			g_free (body_name);
4082 			g_free (decl_name);
4083 			return FALSE;
4084 		}
4085 	}
4086 	return TRUE;
4087 }
4088 
4089 static gboolean
mono_class_need_stelemref_method(MonoClass * klass)4090 mono_class_need_stelemref_method (MonoClass *klass)
4091 {
4092 	return klass->rank == 1 && MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg);
4093 }
4094 
4095 static int
apply_override(MonoClass * klass,MonoMethod ** vtable,MonoMethod * decl,MonoMethod * override)4096 apply_override (MonoClass *klass, MonoMethod **vtable, MonoMethod *decl, MonoMethod *override)
4097 {
4098 	int dslot;
4099 	dslot = mono_method_get_vtable_slot (decl);
4100 	if (dslot == -1) {
4101 		mono_class_set_type_load_failure (klass, "");
4102 		return FALSE;
4103 	}
4104 
4105 	dslot += mono_class_interface_offset (klass, decl->klass);
4106 	vtable [dslot] = override;
4107 	if (!MONO_CLASS_IS_INTERFACE (override->klass)) {
4108 		/*
4109 		 * If override from an interface, then it is an override of a default interface method,
4110 		 * don't override its slot.
4111 		 */
4112 		vtable [dslot]->slot = dslot;
4113 	}
4114 
4115 	if (mono_security_core_clr_enabled ())
4116 		mono_security_core_clr_check_override (klass, vtable [dslot], decl);
4117 
4118 	return TRUE;
4119 }
4120 
4121 /*
4122  * LOCKING: this is supposed to be called with the loader lock held.
4123  */
4124 void
mono_class_setup_vtable_general(MonoClass * klass,MonoMethod ** overrides,int onum,GList * in_setup)4125 mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int onum, GList *in_setup)
4126 {
4127 	MonoError error;
4128 	MonoClass *k, *ic;
4129 	MonoMethod **vtable = NULL;
4130 	int i, max_vtsize = 0, cur_slot = 0;
4131 	guint32 max_iid;
4132 	GPtrArray *ifaces = NULL;
4133 	GHashTable *override_map = NULL;
4134 	MonoMethod *cm;
4135 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4136 	int first_non_interface_slot;
4137 #endif
4138 	GSList *virt_methods = NULL, *l;
4139 	int stelemref_slot = 0;
4140 
4141 	if (klass->vtable)
4142 		return;
4143 
4144 	if (overrides && !verify_class_overrides (klass, overrides, onum))
4145 		return;
4146 
4147 	ifaces = mono_class_get_implemented_interfaces (klass, &error);
4148 	if (!mono_error_ok (&error)) {
4149 		char *name = mono_type_get_full_name (klass);
4150 		mono_class_set_type_load_failure (klass, "Could not resolve %s interfaces due to %s", name, mono_error_get_message (&error));
4151 		g_free (name);
4152 		mono_error_cleanup (&error);
4153 		return;
4154 	} else if (ifaces) {
4155 		for (i = 0; i < ifaces->len; i++) {
4156 			MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
4157 			max_vtsize += mono_class_get_method_count (ic);
4158 		}
4159 		g_ptr_array_free (ifaces, TRUE);
4160 		ifaces = NULL;
4161 	}
4162 
4163 	if (klass->parent) {
4164 		mono_class_init (klass->parent);
4165 		mono_class_setup_vtable_full (klass->parent, in_setup);
4166 
4167 		if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class failed to load"))
4168 			return;
4169 
4170 		max_vtsize += klass->parent->vtable_size;
4171 		cur_slot = klass->parent->vtable_size;
4172 	}
4173 
4174 	max_vtsize += mono_class_get_method_count (klass);
4175 
4176 	/*Array have a slot for stelemref*/
4177 	if (mono_class_need_stelemref_method (klass)) {
4178 		stelemref_slot = cur_slot;
4179 		++max_vtsize;
4180 		++cur_slot;
4181 	}
4182 
4183 	/* printf ("METAINIT %s.%s\n", klass->name_space, klass->name); */
4184 
4185 	cur_slot = setup_interface_offsets (klass, cur_slot, TRUE);
4186 	if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4187 		return;
4188 
4189 	max_iid = klass->max_interface_id;
4190 	DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4191 
4192 	/* Optimized version for generic instances */
4193 	if (mono_class_is_ginst (klass)) {
4194 		MonoError error;
4195 		MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4196 		MonoMethod **tmp;
4197 
4198 		mono_class_setup_vtable_full (gklass, in_setup);
4199 		if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Could not load generic definition"))
4200 			return;
4201 
4202 		tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * gklass->vtable_size);
4203 		klass->vtable_size = gklass->vtable_size;
4204 		for (i = 0; i < gklass->vtable_size; ++i)
4205 			if (gklass->vtable [i]) {
4206 				MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], klass, mono_class_get_context (klass), &error);
4207 				if (!mono_error_ok (&error)) {
4208 					mono_class_set_type_load_failure (klass, "Could not inflate method due to %s", mono_error_get_message (&error));
4209 					mono_error_cleanup (&error);
4210 					return;
4211 				}
4212 				tmp [i] = inflated;
4213 				tmp [i]->slot = gklass->vtable [i]->slot;
4214 			}
4215 		mono_memory_barrier ();
4216 		klass->vtable = tmp;
4217 
4218 		/* Have to set method->slot for abstract virtual methods */
4219 		if (klass->methods && gklass->methods) {
4220 			int mcount = mono_class_get_method_count (klass);
4221 			for (i = 0; i < mcount; ++i)
4222 				if (klass->methods [i]->slot == -1)
4223 					klass->methods [i]->slot = gklass->methods [i]->slot;
4224 		}
4225 
4226 		return;
4227 	}
4228 
4229 	vtable = (MonoMethod **)g_malloc0 (sizeof (gpointer) * max_vtsize);
4230 
4231 	if (klass->parent && klass->parent->vtable_size) {
4232 		MonoClass *parent = klass->parent;
4233 		int i;
4234 
4235 		memcpy (vtable, parent->vtable,  sizeof (gpointer) * parent->vtable_size);
4236 
4237 		// Also inherit parent interface vtables, just as a starting point.
4238 		// This is needed otherwise bug-77127.exe fails when the property methods
4239 		// have different names in the iterface and the class, because for child
4240 		// classes the ".override" information is not used anymore.
4241 		for (i = 0; i < parent->interface_offsets_count; i++) {
4242 			MonoClass *parent_interface = parent->interfaces_packed [i];
4243 			int interface_offset = mono_class_interface_offset (klass, parent_interface);
4244 			/*FIXME this is now dead code as this condition will never hold true.
4245 			Since interface offsets are inherited then the offset of an interface implemented
4246 			by a parent will never be the out of it's vtable boundary.
4247 			*/
4248 			if (interface_offset >= parent->vtable_size) {
4249 				int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4250 				int j;
4251 
4252 				mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4253 				TRACE_INTERFACE_VTABLE (printf ("    +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4254 				int mcount = mono_class_get_method_count (parent_interface);
4255 				for (j = 0; j < mcount && !mono_class_has_failure (klass); j++) {
4256 					vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4257 					TRACE_INTERFACE_VTABLE (printf ("    --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4258 							parent_interface_offset + j, parent_interface_offset, j,
4259 							interface_offset + j, interface_offset, j));
4260 				}
4261 			}
4262 
4263 		}
4264 	}
4265 
4266 	/*Array have a slot for stelemref*/
4267 	if (mono_class_need_stelemref_method (klass)) {
4268 		MonoMethod *method = mono_marshal_get_virtual_stelemref (klass);
4269 		if (!method->slot)
4270 			method->slot = stelemref_slot;
4271 		else
4272 			g_assert (method->slot == stelemref_slot);
4273 
4274 		vtable [stelemref_slot] = method;
4275 	}
4276 
4277 	TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4278 
4279 	/* Process overrides from interface default methods */
4280 	// FIXME: Ordering between interfaces
4281 	for (int ifindex = 0; ifindex < klass->interface_offsets_count; ifindex++) {
4282 		ic = klass->interfaces_packed [ifindex];
4283 
4284 		mono_class_setup_methods (ic);
4285 		if (mono_class_has_failure (ic))
4286 			goto fail;
4287 
4288 		MonoMethod **iface_overrides;
4289 		int iface_onum;
4290 		gboolean ok = mono_class_get_overrides_full (ic->image, ic->type_token, &iface_overrides, &iface_onum, mono_class_get_context (ic));
4291 		if (ok) {
4292 			for (int i = 0; i < iface_onum; i++) {
4293 				MonoMethod *decl = iface_overrides [i*2];
4294 				MonoMethod *override = iface_overrides [i*2 + 1];
4295 				if (!apply_override (klass, vtable, decl, override))
4296 					goto fail;
4297 
4298 				if (!override_map)
4299 					override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4300 				g_hash_table_insert (override_map, decl, override);
4301 			}
4302 			g_free (iface_overrides);
4303 		}
4304 	}
4305 
4306 	/* override interface methods */
4307 	for (i = 0; i < onum; i++) {
4308 		MonoMethod *decl = overrides [i*2];
4309 		MonoMethod *override = overrides [i*2 + 1];
4310 		if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4311 			if (!apply_override (klass, vtable, decl, override))
4312 				goto fail;
4313 
4314 			if (!override_map)
4315 				override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4316 			g_hash_table_insert (override_map, decl, override);
4317 		}
4318 	}
4319 
4320 	TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4321 	TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4322 
4323 	/*
4324 	 * Create a list of virtual methods to avoid calling
4325 	 * mono_class_get_virtual_methods () which is slow because of the metadata
4326 	 * optimization.
4327 	 */
4328 	{
4329 		gpointer iter = NULL;
4330 		MonoMethod *cm;
4331 
4332 		virt_methods = NULL;
4333 		while ((cm = mono_class_get_virtual_methods (klass, &iter))) {
4334 			virt_methods = g_slist_prepend (virt_methods, cm);
4335 		}
4336 		if (mono_class_has_failure (klass))
4337 			goto fail;
4338 	}
4339 
4340 	// Loop on all implemented interfaces...
4341 	for (i = 0; i < klass->interface_offsets_count; i++) {
4342 		MonoClass *parent = klass->parent;
4343 		int ic_offset;
4344 		gboolean interface_is_explicitly_implemented_by_class;
4345 		int im_index;
4346 
4347 		ic = klass->interfaces_packed [i];
4348 		ic_offset = mono_class_interface_offset (klass, ic);
4349 
4350 		mono_class_setup_methods (ic);
4351 		if (mono_class_has_failure (ic))
4352 			goto fail;
4353 
4354 		// Check if this interface is explicitly implemented (instead of just inherited)
4355 		if (parent != NULL) {
4356 			int implemented_interfaces_index;
4357 			interface_is_explicitly_implemented_by_class = FALSE;
4358 			for (implemented_interfaces_index = 0; implemented_interfaces_index < klass->interface_count; implemented_interfaces_index++) {
4359 				if (ic == klass->interfaces [implemented_interfaces_index]) {
4360 					interface_is_explicitly_implemented_by_class = TRUE;
4361 					break;
4362 				}
4363 			}
4364 		} else {
4365 			interface_is_explicitly_implemented_by_class = TRUE;
4366 		}
4367 
4368 		// Loop on all interface methods...
4369 		int mcount = mono_class_get_method_count (ic);
4370 		for (im_index = 0; im_index < mcount; im_index++) {
4371 			MonoMethod *im = ic->methods [im_index];
4372 			int im_slot = ic_offset + im->slot;
4373 			MonoMethod *override_im = (override_map != NULL) ? (MonoMethod *)g_hash_table_lookup (override_map, im) : NULL;
4374 
4375 			if (im->flags & METHOD_ATTRIBUTE_STATIC)
4376 				continue;
4377 
4378 			TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4379 
4380 			// If there is an explicit implementation, just use it right away,
4381 			// otherwise look for a matching method
4382 			if (override_im == NULL) {
4383 				int cm_index;
4384 				MonoMethod *cm;
4385 
4386 				// First look for a suitable method among the class methods
4387 				for (l = virt_methods; l; l = l->next) {
4388 					cm = (MonoMethod *)l->data;
4389 					TRACE_INTERFACE_VTABLE (printf ("    For slot %d ('%s'.'%s':'%s'), trying method '%s'.'%s':'%s'... [EXPLICIT IMPLEMENTATION = %d][SLOT IS NULL = %d]", im_slot, ic->name_space, ic->name, im->name, cm->klass->name_space, cm->klass->name, cm->name, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL)));
4390 					if (check_interface_method_override (klass, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL))) {
4391 						TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4392 						vtable [im_slot] = cm;
4393 						/* Why do we need this? */
4394 						if (cm->slot < 0) {
4395 							cm->slot = im_slot;
4396 						}
4397 					}
4398 					TRACE_INTERFACE_VTABLE (printf ("\n"));
4399 					if (mono_class_has_failure (klass))  /*Might be set by check_interface_method_override*/
4400 						goto fail;
4401 				}
4402 
4403 				// If the slot is still empty, look in all the inherited virtual methods...
4404 				if ((vtable [im_slot] == NULL) && klass->parent != NULL) {
4405 					MonoClass *parent = klass->parent;
4406 					// Reverse order, so that last added methods are preferred
4407 					for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4408 						MonoMethod *cm = parent->vtable [cm_index];
4409 
4410 						TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("    For slot %d ('%s'.'%s':'%s'), trying (ancestor) method '%s'.'%s':'%s'... ", im_slot, ic->name_space, ic->name, im->name, cm->klass->name_space, cm->klass->name, cm->name));
4411 						if ((cm != NULL) && check_interface_method_override (klass, im, cm, FALSE, FALSE, TRUE)) {
4412 							TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4413 							vtable [im_slot] = cm;
4414 							/* Why do we need this? */
4415 							if (cm->slot < 0) {
4416 								cm->slot = im_slot;
4417 							}
4418 							break;
4419 						}
4420 						if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4421 							goto fail;
4422 						TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4423 					}
4424 				}
4425 
4426 				if (vtable [im_slot] == NULL) {
4427 					if (!(im->flags & METHOD_ATTRIBUTE_ABSTRACT)) {
4428 						TRACE_INTERFACE_VTABLE (printf ("    Using default iface method %s.\n", mono_method_full_name (im, 1)));
4429 						vtable [im_slot] = im;
4430 					}
4431 				}
4432 			} else {
4433 				g_assert (vtable [im_slot] == override_im);
4434 			}
4435 		}
4436 	}
4437 
4438 	// If the class is not abstract, check that all its interface slots are full.
4439 	// The check is done here and not directly at the end of the loop above because
4440 	// it can happen (for injected generic array interfaces) that the same slot is
4441 	// processed multiple times (those interfaces have overlapping slots), and it
4442 	// will not always be the first pass the one that fills the slot.
4443 	if (!mono_class_is_abstract (klass)) {
4444 		for (i = 0; i < klass->interface_offsets_count; i++) {
4445 			int ic_offset;
4446 			int im_index;
4447 
4448 			ic = klass->interfaces_packed [i];
4449 			ic_offset = mono_class_interface_offset (klass, ic);
4450 
4451 			int mcount = mono_class_get_method_count (ic);
4452 			for (im_index = 0; im_index < mcount; im_index++) {
4453 				MonoMethod *im = ic->methods [im_index];
4454 				int im_slot = ic_offset + im->slot;
4455 
4456 				if (im->flags & METHOD_ATTRIBUTE_STATIC)
4457 					continue;
4458 
4459 				TRACE_INTERFACE_VTABLE (printf ("      [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4460 						im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4461 				if (vtable [im_slot] == NULL) {
4462 					print_unimplemented_interface_method_info (klass, ic, im, im_slot, overrides, onum);
4463 					goto fail;
4464 				}
4465 			}
4466 		}
4467 	}
4468 
4469 	TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4470 	for (l = virt_methods; l; l = l->next) {
4471 		cm = (MonoMethod *)l->data;
4472 		/*
4473 		 * If the method is REUSE_SLOT, we must check in the
4474 		 * base class for a method to override.
4475 		 */
4476 		if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4477 			int slot = -1;
4478 			for (k = klass->parent; k ; k = k->parent) {
4479 				gpointer k_iter;
4480 				MonoMethod *m1;
4481 
4482 				k_iter = NULL;
4483 				while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4484 					MonoMethodSignature *cmsig, *m1sig;
4485 
4486 					cmsig = mono_method_signature (cm);
4487 					m1sig = mono_method_signature (m1);
4488 
4489 					if (!cmsig || !m1sig) {
4490 						/* FIXME proper error message */
4491 						mono_class_set_type_load_failure (klass, "");
4492 						return;
4493 					}
4494 
4495 					if (!strcmp(cm->name, m1->name) &&
4496 					    mono_metadata_signature_equal (cmsig, m1sig)) {
4497 
4498 						if (mono_security_core_clr_enabled ())
4499 							mono_security_core_clr_check_override (klass, cm, m1);
4500 
4501 						slot = mono_method_get_vtable_slot (m1);
4502 						if (slot == -1)
4503 							goto fail;
4504 
4505 						if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4506 							char *body_name = mono_method_full_name (cm, TRUE);
4507 							char *decl_name = mono_method_full_name (m1, TRUE);
4508 							mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4509 							g_free (body_name);
4510 							g_free (decl_name);
4511 							goto fail;
4512 						}
4513 
4514 						g_assert (cm->slot < max_vtsize);
4515 						if (!override_map)
4516 							override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4517 						TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4518 							mono_method_full_name (m1, 1), m1,
4519 							mono_method_full_name (cm, 1), cm));
4520 						g_hash_table_insert (override_map, m1, cm);
4521 						break;
4522 					}
4523 				}
4524 				if (mono_class_has_failure (k))
4525 					goto fail;
4526 
4527 				if (slot >= 0)
4528 					break;
4529 			}
4530 			if (slot >= 0)
4531 				cm->slot = slot;
4532 		}
4533 
4534 		/*Non final newslot methods must be given a non-interface vtable slot*/
4535 		if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4536 			cm->slot = -1;
4537 
4538 		if (cm->slot < 0)
4539 			cm->slot = cur_slot++;
4540 
4541 		if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4542 			vtable [cm->slot] = cm;
4543 	}
4544 
4545 	/* override non interface methods */
4546 	for (i = 0; i < onum; i++) {
4547 		MonoMethod *decl = overrides [i*2];
4548 		if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4549 			g_assert (decl->slot != -1);
4550 			vtable [decl->slot] = overrides [i*2 + 1];
4551  			overrides [i * 2 + 1]->slot = decl->slot;
4552 			if (!override_map)
4553 				override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4554 			TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4555 				mono_method_full_name (decl, 1), decl,
4556 				mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4557 			g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4558 
4559 			if (mono_security_core_clr_enabled ())
4560 				mono_security_core_clr_check_override (klass, vtable [decl->slot], decl);
4561 		}
4562 	}
4563 
4564 	/*
4565 	 * If a method occupies more than one place in the vtable, and it is
4566 	 * overriden, then change the other occurances too.
4567 	 */
4568 	if (override_map) {
4569 		MonoMethod *cm;
4570 
4571 		for (i = 0; i < max_vtsize; ++i)
4572 			if (vtable [i]) {
4573 				TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4574 
4575 				cm = (MonoMethod *)g_hash_table_lookup (override_map, vtable [i]);
4576 				if (cm)
4577 					vtable [i] = cm;
4578 			}
4579 
4580 		g_hash_table_destroy (override_map);
4581 		override_map = NULL;
4582 	}
4583 
4584 	g_slist_free (virt_methods);
4585 	virt_methods = NULL;
4586 
4587 	g_assert (cur_slot <= max_vtsize);
4588 
4589 	/* Ensure that all vtable slots are filled with concrete instance methods */
4590 	if (!mono_class_is_abstract (klass)) {
4591 		for (i = 0; i < cur_slot; ++i) {
4592 			if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4593 				char *type_name = mono_type_get_full_name (klass);
4594 				char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4595 				mono_class_set_type_load_failure (klass, "Type %s has invalid vtable method slot %d with method %s", type_name, i, method_name);
4596 				g_free (type_name);
4597 				g_free (method_name);
4598 				g_free (vtable);
4599 				return;
4600 			}
4601 		}
4602 	}
4603 
4604 	if (mono_class_is_ginst (klass)) {
4605 		MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4606 
4607 		mono_class_init (gklass);
4608 
4609 		klass->vtable_size = MAX (gklass->vtable_size, cur_slot);
4610 	} else {
4611 		/* Check that the vtable_size value computed in mono_class_init () is correct */
4612 		if (klass->vtable_size)
4613 			g_assert (cur_slot == klass->vtable_size);
4614 		klass->vtable_size = cur_slot;
4615 	}
4616 
4617 	/* Try to share the vtable with our parent. */
4618 	if (klass->parent && (klass->parent->vtable_size == klass->vtable_size) && (memcmp (klass->parent->vtable, vtable, sizeof (gpointer) * klass->vtable_size) == 0)) {
4619 		mono_memory_barrier ();
4620 		klass->vtable = klass->parent->vtable;
4621 	} else {
4622 		MonoMethod **tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * klass->vtable_size);
4623 		memcpy (tmp, vtable,  sizeof (gpointer) * klass->vtable_size);
4624 		mono_memory_barrier ();
4625 		klass->vtable = tmp;
4626 	}
4627 
4628 	DEBUG_INTERFACE_VTABLE (print_vtable_full (klass, klass->vtable, klass->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4629 	if (mono_print_vtable) {
4630 		int icount = 0;
4631 
4632 		print_implemented_interfaces (klass);
4633 
4634 		for (i = 0; i <= max_iid; i++)
4635 			if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
4636 				icount++;
4637 
4638 		printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&klass->byval_arg),
4639 			klass->vtable_size, icount);
4640 
4641 		for (i = 0; i < cur_slot; ++i) {
4642 			MonoMethod *cm;
4643 
4644 			cm = vtable [i];
4645 			if (cm) {
4646 				printf ("  slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4647 					mono_method_full_name (cm, TRUE));
4648 			}
4649 		}
4650 
4651 
4652 		if (icount) {
4653 			printf ("Interfaces %s.%s (max_iid = %d)\n", klass->name_space,
4654 				klass->name, max_iid);
4655 
4656 			for (i = 0; i < klass->interface_count; i++) {
4657 				ic = klass->interfaces [i];
4658 				printf ("  slot offset: %03d, method count: %03d, iid: %03d %s\n",
4659 					mono_class_interface_offset (klass, ic),
4660 					count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4661 			}
4662 
4663 			for (k = klass->parent; k ; k = k->parent) {
4664 				for (i = 0; i < k->interface_count; i++) {
4665 					ic = k->interfaces [i];
4666 					printf ("  parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4667 						mono_class_interface_offset (klass, ic),
4668 						count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4669 				}
4670 			}
4671 		}
4672 	}
4673 
4674 	g_free (vtable);
4675 
4676 	VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (klass));
4677 	return;
4678 
4679 fail:
4680 	{
4681 	char *name = mono_type_get_full_name (klass);
4682 	mono_class_set_type_load_failure (klass, "VTable setup of type %s failed", name);
4683 	g_free (name);
4684 	g_free (vtable);
4685 	if (override_map)
4686 		g_hash_table_destroy (override_map);
4687 	if (virt_methods)
4688 		g_slist_free (virt_methods);
4689 	}
4690 }
4691 
4692 /*
4693  * mono_method_get_vtable_slot:
4694  *
4695  *   Returns method->slot, computing it if neccesary. Return -1 on failure.
4696  * LOCKING: Acquires the loader lock.
4697  *
4698  * FIXME Use proper MonoError machinery here.
4699  */
4700 int
mono_method_get_vtable_slot(MonoMethod * method)4701 mono_method_get_vtable_slot (MonoMethod *method)
4702 {
4703 	if (method->slot == -1) {
4704 		mono_class_setup_vtable (method->klass);
4705 		if (mono_class_has_failure (method->klass))
4706 			return -1;
4707 		if (method->slot == -1) {
4708 			MonoClass *gklass;
4709 			int i, mcount;
4710 
4711 			if (!mono_class_is_ginst (method->klass)) {
4712 				g_assert (method->is_inflated);
4713 				return mono_method_get_vtable_slot (((MonoMethodInflated*)method)->declaring);
4714 			}
4715 
4716 			/* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4717 			g_assert (mono_class_is_ginst (method->klass));
4718 			gklass = mono_class_get_generic_class (method->klass)->container_class;
4719 			mono_class_setup_methods (method->klass);
4720 			g_assert (method->klass->methods);
4721 			mcount = mono_class_get_method_count (method->klass);
4722 			for (i = 0; i < mcount; ++i) {
4723 				if (method->klass->methods [i] == method)
4724 					break;
4725 			}
4726 			g_assert (i < mcount);
4727 			g_assert (gklass->methods);
4728 			method->slot = gklass->methods [i]->slot;
4729 		}
4730 		g_assert (method->slot != -1);
4731 	}
4732 	return method->slot;
4733 }
4734 
4735 /**
4736  * mono_method_get_vtable_index:
4737  * \param method a method
4738  *
4739  * Returns the index into the runtime vtable to access the method or,
4740  * in the case of a virtual generic method, the virtual generic method
4741  * thunk. Returns -1 on failure.
4742  *
4743  * FIXME Use proper MonoError machinery here.
4744  */
4745 int
mono_method_get_vtable_index(MonoMethod * method)4746 mono_method_get_vtable_index (MonoMethod *method)
4747 {
4748 	if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4749 		MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4750 		if (imethod->declaring->is_generic)
4751 			return mono_method_get_vtable_slot (imethod->declaring);
4752 	}
4753 	return mono_method_get_vtable_slot (method);
4754 }
4755 
4756 static MonoMethod *default_ghc = NULL;
4757 static MonoMethod *default_finalize = NULL;
4758 static int finalize_slot = -1;
4759 static int ghc_slot = -1;
4760 
4761 static void
initialize_object_slots(MonoClass * klass)4762 initialize_object_slots (MonoClass *klass)
4763 {
4764 	int i;
4765 	if (default_ghc)
4766 		return;
4767 	if (klass == mono_defaults.object_class) {
4768 		mono_class_setup_vtable (klass);
4769 		for (i = 0; i < klass->vtable_size; ++i) {
4770 			MonoMethod *cm = klass->vtable [i];
4771 
4772 			if (!strcmp (cm->name, "GetHashCode"))
4773 				ghc_slot = i;
4774 			else if (!strcmp (cm->name, "Finalize"))
4775 				finalize_slot = i;
4776 		}
4777 
4778 		g_assert (ghc_slot > 0);
4779 		default_ghc = klass->vtable [ghc_slot];
4780 
4781 		g_assert (finalize_slot > 0);
4782 		default_finalize = klass->vtable [finalize_slot];
4783 	}
4784 }
4785 
4786 typedef struct {
4787 	MonoMethod *array_method;
4788 	char *name;
4789 } GenericArrayMethodInfo;
4790 
4791 static int generic_array_method_num = 0;
4792 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4793 
4794 static int
generic_array_methods(MonoClass * klass)4795 generic_array_methods (MonoClass *klass)
4796 {
4797 	int i, count_generic = 0, mcount;
4798 	GList *list = NULL, *tmp;
4799 	if (generic_array_method_num)
4800 		return generic_array_method_num;
4801 	mono_class_setup_methods (klass->parent); /*This is setting up System.Array*/
4802 	g_assert (!mono_class_has_failure (klass->parent)); /*So hitting this assert is a huge problem*/
4803 	mcount = mono_class_get_method_count (klass->parent);
4804 	for (i = 0; i < mcount; i++) {
4805 		MonoMethod *m = klass->parent->methods [i];
4806 		if (!strncmp (m->name, "InternalArray__", 15)) {
4807 			count_generic++;
4808 			list = g_list_prepend (list, m);
4809 		}
4810 	}
4811 	list = g_list_reverse (list);
4812 	generic_array_method_info = (GenericArrayMethodInfo *)mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
4813 	i = 0;
4814 	for (tmp = list; tmp; tmp = tmp->next) {
4815 		const char *mname, *iname;
4816 		gchar *name;
4817 		MonoMethod *m = (MonoMethod *)tmp->data;
4818 		const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
4819 		const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
4820 
4821 		generic_array_method_info [i].array_method = m;
4822 		if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
4823 			iname = "System.Collections.Generic.ICollection`1.";
4824 			mname = m->name + 27;
4825 		} else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
4826 			iname = "System.Collections.Generic.IEnumerable`1.";
4827 			mname = m->name + 27;
4828 		} else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
4829 			iname = "System.Collections.Generic.IReadOnlyList`1.";
4830 			mname = m->name + strlen (ireadonlylist_prefix);
4831 		} else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
4832 			iname = "System.Collections.Generic.IReadOnlyCollection`1.";
4833 			mname = m->name + strlen (ireadonlycollection_prefix);
4834 		} else if (!strncmp (m->name, "InternalArray__", 15)) {
4835 			iname = "System.Collections.Generic.IList`1.";
4836 			mname = m->name + 15;
4837 		} else {
4838 			g_assert_not_reached ();
4839 		}
4840 
4841 		name = (gchar *)mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
4842 		strcpy (name, iname);
4843 		strcpy (name + strlen (iname), mname);
4844 		generic_array_method_info [i].name = name;
4845 		i++;
4846 	}
4847 	/*g_print ("array generic methods: %d\n", count_generic);*/
4848 
4849 	generic_array_method_num = count_generic;
4850 	g_list_free (list);
4851 	return generic_array_method_num;
4852 }
4853 
4854 static void
setup_generic_array_ifaces(MonoClass * klass,MonoClass * iface,MonoMethod ** methods,int pos,GHashTable * cache)4855 setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos, GHashTable *cache)
4856 {
4857 	MonoGenericContext tmp_context;
4858 	int i;
4859 
4860 	tmp_context.class_inst = NULL;
4861 	tmp_context.method_inst = mono_class_get_generic_class (iface)->context.class_inst;
4862 	//g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
4863 
4864 	for (i = 0; i < generic_array_method_num; i++) {
4865 		MonoError error;
4866 		MonoMethod *m = generic_array_method_info [i].array_method;
4867 		MonoMethod *inflated, *helper;
4868 
4869 		inflated = mono_class_inflate_generic_method_checked (m, &tmp_context, &error);
4870 		mono_error_assert_ok (&error);
4871 		helper = g_hash_table_lookup (cache, inflated);
4872 		if (!helper) {
4873 			helper = mono_marshal_get_generic_array_helper (klass, generic_array_method_info [i].name, inflated);
4874 			g_hash_table_insert (cache, inflated, helper);
4875 		}
4876 		methods [pos ++] = helper;
4877 	}
4878 }
4879 
4880 static char*
concat_two_strings_with_zero(MonoImage * image,const char * s1,const char * s2)4881 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
4882 {
4883 	int null_length = strlen ("(null)");
4884 	int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
4885 	char *s = (char *)mono_image_alloc (image, len);
4886 	int result;
4887 
4888 	result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
4889 	g_assert (result == len - 1);
4890 
4891 	return s;
4892 }
4893 
4894 /**
4895  * mono_class_init:
4896  * \param klass the class to initialize
4897  *
4898  * Compute the \c instance_size, \c class_size and other infos that cannot be
4899  * computed at \c mono_class_get time. Also compute vtable_size if possible.
4900  * Initializes the following fields in \p klass:
4901  * - all the fields initialized by \c mono_class_init_sizes
4902  * - has_cctor
4903  * - ghcimpl
4904  * - inited
4905  *
4906  * LOCKING: Acquires the loader lock.
4907  *
4908  * \returns TRUE on success or FALSE if there was a problem in loading
4909  * the type (incorrect assemblies, missing assemblies, methods, etc).
4910  */
4911 gboolean
mono_class_init(MonoClass * klass)4912 mono_class_init (MonoClass *klass)
4913 {
4914 	int i, vtable_size = 0, array_method_count = 0;
4915 	MonoCachedClassInfo cached_info;
4916 	gboolean has_cached_info;
4917 	gboolean locked = FALSE;
4918 	gboolean ghcimpl = FALSE;
4919 	gboolean has_cctor = FALSE;
4920 	int first_iface_slot = 0;
4921 
4922 	g_assert (klass);
4923 
4924 	/* Double-checking locking pattern */
4925 	if (klass->inited || mono_class_has_failure (klass))
4926 		return !mono_class_has_failure (klass);
4927 
4928 	/*g_print ("Init class %s\n", mono_type_get_full_name (klass));*/
4929 
4930 	/*
4931 	 * This function can recursively call itself.
4932 	 */
4933 	GSList *init_list = (GSList *)mono_native_tls_get_value (init_pending_tls_id);
4934 	if (g_slist_find (init_list, klass)) {
4935 		mono_class_set_type_load_failure (klass, "Recursive type definition detected");
4936 		goto leave_no_init_pending;
4937 	}
4938 	init_list = g_slist_prepend (init_list, klass);
4939 	mono_native_tls_set_value (init_pending_tls_id, init_list);
4940 
4941 	/*
4942 	 * We want to avoid doing complicated work inside locks, so we compute all the required
4943 	 * information and write it to @klass inside a lock.
4944 	 */
4945 
4946 	if (mono_verifier_is_enabled_for_class (klass) && !mono_verifier_verify_class (klass)) {
4947 		mono_class_set_type_load_failure (klass, "%s", concat_two_strings_with_zero (klass->image, klass->name, klass->image->assembly_name));
4948 		goto leave;
4949 	}
4950 
4951 	if (klass->byval_arg.type == MONO_TYPE_ARRAY || klass->byval_arg.type == MONO_TYPE_SZARRAY) {
4952 		MonoClass *element_class = klass->element_class;
4953 		if (!element_class->inited)
4954 			mono_class_init (element_class);
4955 		if (mono_class_set_type_load_failure_causedby_class (klass, element_class, "Could not load array element class"))
4956 			goto leave;
4957 	}
4958 
4959 	UnlockedIncrement (&mono_stats.initialized_class_count);
4960 
4961 	if (mono_class_is_ginst (klass) && !mono_class_get_generic_class (klass)->is_dynamic) {
4962 		MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4963 
4964 		mono_class_init (gklass);
4965 		if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic Type Definition failed to init"))
4966 			goto leave;
4967 
4968 		if (MONO_CLASS_IS_INTERFACE (klass))
4969 			mono_class_setup_interface_id (klass);
4970 	}
4971 
4972 	if (klass->parent && !klass->parent->inited)
4973 		mono_class_init (klass->parent);
4974 
4975 	has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
4976 
4977 	/* Compute instance size etc. */
4978 	init_sizes_with_info (klass, has_cached_info ? &cached_info : NULL);
4979 	if (mono_class_has_failure (klass))
4980 		goto leave;
4981 
4982 	mono_class_setup_supertypes (klass);
4983 
4984 	if (!default_ghc)
4985 		initialize_object_slots (klass);
4986 
4987 	/*
4988 	 * Initialize the rest of the data without creating a generic vtable if possible.
4989 	 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
4990 	 * also avoid computing a generic vtable.
4991 	 */
4992 	if (has_cached_info) {
4993 		/* AOT case */
4994 		vtable_size = cached_info.vtable_size;
4995 		ghcimpl = cached_info.ghcimpl;
4996 		has_cctor = cached_info.has_cctor;
4997 	} else if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
4998 		/* SZARRAY can have 3 vtable layouts, with and without the stelemref method and enum element type
4999 		 * The first slot if for array with.
5000 		 */
5001 		static int szarray_vtable_size[3] = { 0 };
5002 
5003 		int slot;
5004 
5005 		if (MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg))
5006 			slot = 0;
5007 		else if (klass->element_class->enumtype)
5008 			slot = 1;
5009 		else
5010 			slot = 2;
5011 
5012 		/* SZARRAY case */
5013 		if (!szarray_vtable_size [slot]) {
5014 			mono_class_setup_vtable (klass);
5015 			szarray_vtable_size [slot] = klass->vtable_size;
5016 			vtable_size = klass->vtable_size;
5017 		} else {
5018 			vtable_size = szarray_vtable_size[slot];
5019 		}
5020 	} else if (mono_class_is_ginst (klass) && !MONO_CLASS_IS_INTERFACE (klass)) {
5021 		MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5022 
5023 		/* Generic instance case */
5024 		ghcimpl = gklass->ghcimpl;
5025 		has_cctor = gklass->has_cctor;
5026 
5027 		mono_class_setup_vtable (gklass);
5028 		if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to init"))
5029 			goto leave;
5030 
5031 		vtable_size = gklass->vtable_size;
5032 	} else {
5033 		/* General case */
5034 
5035 		/* ghcimpl is not currently used
5036 		klass->ghcimpl = 1;
5037 		if (klass->parent) {
5038 			MonoMethod *cmethod = klass->vtable [ghc_slot];
5039 			if (cmethod->is_inflated)
5040 				cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5041 			if (cmethod == default_ghc) {
5042 				klass->ghcimpl = 0;
5043 			}
5044 		}
5045 		*/
5046 
5047 		/* C# doesn't allow interfaces to have cctors */
5048 		if (!MONO_CLASS_IS_INTERFACE (klass) || klass->image != mono_defaults.corlib) {
5049 			MonoMethod *cmethod = NULL;
5050 
5051 			if (mono_class_is_ginst (klass)) {
5052 				MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5053 
5054 				/* Generic instance case */
5055 				ghcimpl = gklass->ghcimpl;
5056 				has_cctor = gklass->has_cctor;
5057 			} else if (klass->type_token && !image_is_dynamic(klass->image)) {
5058 				cmethod = find_method_in_metadata (klass, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
5059 				/* The find_method function ignores the 'flags' argument */
5060 				if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5061 					has_cctor = 1;
5062 			} else {
5063 				mono_class_setup_methods (klass);
5064 				if (mono_class_has_failure (klass))
5065 					goto leave;
5066 
5067 				int mcount = mono_class_get_method_count (klass);
5068 				for (i = 0; i < mcount; ++i) {
5069 					MonoMethod *method = klass->methods [i];
5070 					if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5071 						(strcmp (".cctor", method->name) == 0)) {
5072 						has_cctor = 1;
5073 						break;
5074 					}
5075 				}
5076 			}
5077 		}
5078 	}
5079 
5080 	if (klass->rank) {
5081 		array_method_count = 3 + (klass->rank > 1? 2: 1);
5082 
5083 		if (klass->interface_count) {
5084 			int count_generic = generic_array_methods (klass);
5085 			array_method_count += klass->interface_count * count_generic;
5086 		}
5087 	}
5088 
5089 	if (klass->parent) {
5090 		if (!klass->parent->vtable_size)
5091 			mono_class_setup_vtable (klass->parent);
5092 		if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class vtable failed to initialize"))
5093 			goto leave;
5094 		g_assert (klass->parent->vtable_size);
5095 		first_iface_slot = klass->parent->vtable_size;
5096 		if (mono_class_need_stelemref_method (klass))
5097 			++first_iface_slot;
5098 	}
5099 
5100 	/*
5101 	 * Do the actual changes to @klass inside the loader lock
5102 	 */
5103 	mono_loader_lock ();
5104 	locked = TRUE;
5105 
5106 	if (klass->inited || mono_class_has_failure (klass)) {
5107 		mono_loader_unlock ();
5108 		/* Somebody might have gotten in before us */
5109 		return !mono_class_has_failure (klass);
5110 	}
5111 
5112 	UnlockedIncrement (&mono_stats.initialized_class_count);
5113 
5114 	if (mono_class_is_ginst (klass) && !mono_class_get_generic_class (klass)->is_dynamic)
5115 		UnlockedIncrement (&mono_stats.generic_class_count);
5116 
5117 	if (mono_class_is_ginst (klass) || image_is_dynamic (klass->image) || !klass->type_token || (has_cached_info && !cached_info.has_nested_classes))
5118 		klass->nested_classes_inited = TRUE;
5119 	klass->ghcimpl = ghcimpl;
5120 	klass->has_cctor = has_cctor;
5121 	if (vtable_size)
5122 		klass->vtable_size = vtable_size;
5123 	if (has_cached_info) {
5124 		klass->has_finalize = cached_info.has_finalize;
5125 		klass->has_finalize_inited = TRUE;
5126 	}
5127 	if (klass->rank)
5128 		mono_class_set_method_count (klass, array_method_count);
5129 
5130 	mono_loader_unlock ();
5131 	locked = FALSE;
5132 
5133 	setup_interface_offsets (klass, first_iface_slot, TRUE);
5134 
5135 	if (mono_security_core_clr_enabled ())
5136 		mono_security_core_clr_check_inheritance (klass);
5137 
5138 	if (mono_class_is_ginst (klass) && !mono_verifier_class_is_valid_generic_instantiation (klass))
5139 		mono_class_set_type_load_failure (klass, "Invalid generic instantiation");
5140 
5141 	goto leave;
5142 
5143 leave:
5144 	init_list = mono_native_tls_get_value (init_pending_tls_id);
5145 	init_list = g_slist_remove (init_list, klass);
5146 	mono_native_tls_set_value (init_pending_tls_id, init_list);
5147 
5148 leave_no_init_pending:
5149 	if (locked)
5150 		mono_loader_unlock ();
5151 
5152 	/* Leave this for last */
5153 	mono_loader_lock ();
5154 	klass->inited = 1;
5155 	mono_loader_unlock ();
5156 
5157 	return !mono_class_has_failure (klass);
5158 }
5159 
5160 /*
5161  * mono_class_has_finalizer:
5162  *
5163  *   Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5164  * process.
5165  */
5166 gboolean
mono_class_has_finalizer(MonoClass * klass)5167 mono_class_has_finalizer (MonoClass *klass)
5168 {
5169 	gboolean has_finalize = FALSE;
5170 
5171 	if (klass->has_finalize_inited)
5172 		return klass->has_finalize;
5173 
5174 	/* Interfaces and valuetypes are not supposed to have finalizers */
5175 	if (!(MONO_CLASS_IS_INTERFACE (klass) || klass->valuetype)) {
5176 		MonoMethod *cmethod = NULL;
5177 
5178 		if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5179 		} else if (mono_class_is_ginst (klass)) {
5180 			MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5181 
5182 			has_finalize = mono_class_has_finalizer (gklass);
5183 		} else if (klass->parent && klass->parent->has_finalize) {
5184 			has_finalize = TRUE;
5185 		} else {
5186 			if (klass->parent) {
5187 				/*
5188 				 * Can't search in metadata for a method named Finalize, because that
5189 				 * ignores overrides.
5190 				 */
5191 				mono_class_setup_vtable (klass);
5192 				if (mono_class_has_failure (klass))
5193 					cmethod = NULL;
5194 				else
5195 					cmethod = klass->vtable [finalize_slot];
5196 			}
5197 
5198 			if (cmethod) {
5199 				g_assert (klass->vtable_size > finalize_slot);
5200 
5201 				if (klass->parent) {
5202 					if (cmethod->is_inflated)
5203 						cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5204 					if (cmethod != default_finalize)
5205 						has_finalize = TRUE;
5206 				}
5207 			}
5208 		}
5209 	}
5210 
5211 	mono_loader_lock ();
5212 	if (!klass->has_finalize_inited) {
5213 		klass->has_finalize = has_finalize ? 1 : 0;
5214 
5215 		mono_memory_barrier ();
5216 		klass->has_finalize_inited = TRUE;
5217 	}
5218 	mono_loader_unlock ();
5219 
5220 	return klass->has_finalize;
5221 }
5222 
5223 gboolean
mono_is_corlib_image(MonoImage * image)5224 mono_is_corlib_image (MonoImage *image)
5225 {
5226 	return image == mono_defaults.corlib;
5227 }
5228 
5229 /*
5230  * LOCKING: this assumes the loader lock is held
5231  */
5232 void
mono_class_setup_mono_type(MonoClass * klass)5233 mono_class_setup_mono_type (MonoClass *klass)
5234 {
5235 	const char *name = klass->name;
5236 	const char *nspace = klass->name_space;
5237 	gboolean is_corlib = mono_is_corlib_image (klass->image);
5238 
5239 	klass->this_arg.byref = 1;
5240 	klass->this_arg.data.klass = klass;
5241 	klass->this_arg.type = MONO_TYPE_CLASS;
5242 	klass->byval_arg.data.klass = klass;
5243 	klass->byval_arg.type = MONO_TYPE_CLASS;
5244 
5245 	if (is_corlib && !strcmp (nspace, "System")) {
5246 		if (!strcmp (name, "ValueType")) {
5247 			/*
5248 			 * do not set the valuetype bit for System.ValueType.
5249 			 * klass->valuetype = 1;
5250 			 */
5251 			klass->blittable = TRUE;
5252 		} else if (!strcmp (name, "Enum")) {
5253 			/*
5254 			 * do not set the valuetype bit for System.Enum.
5255 			 * klass->valuetype = 1;
5256 			 */
5257 			klass->valuetype = 0;
5258 			klass->enumtype = 0;
5259 		} else if (!strcmp (name, "Object")) {
5260 			klass->byval_arg.type = MONO_TYPE_OBJECT;
5261 			klass->this_arg.type = MONO_TYPE_OBJECT;
5262 		} else if (!strcmp (name, "String")) {
5263 			klass->byval_arg.type = MONO_TYPE_STRING;
5264 			klass->this_arg.type = MONO_TYPE_STRING;
5265 		} else if (!strcmp (name, "TypedReference")) {
5266 			klass->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5267 			klass->this_arg.type = MONO_TYPE_TYPEDBYREF;
5268 		}
5269 	}
5270 
5271 	if (klass->valuetype) {
5272 		int t = MONO_TYPE_VALUETYPE;
5273 
5274 		if (is_corlib && !strcmp (nspace, "System")) {
5275 			switch (*name) {
5276 			case 'B':
5277 				if (!strcmp (name, "Boolean")) {
5278 					t = MONO_TYPE_BOOLEAN;
5279 				} else if (!strcmp(name, "Byte")) {
5280 					t = MONO_TYPE_U1;
5281 					klass->blittable = TRUE;
5282 				}
5283 				break;
5284 			case 'C':
5285 				if (!strcmp (name, "Char")) {
5286 					t = MONO_TYPE_CHAR;
5287 				}
5288 				break;
5289 			case 'D':
5290 				if (!strcmp (name, "Double")) {
5291 					t = MONO_TYPE_R8;
5292 					klass->blittable = TRUE;
5293 				}
5294 				break;
5295 			case 'I':
5296 				if (!strcmp (name, "Int32")) {
5297 					t = MONO_TYPE_I4;
5298 					klass->blittable = TRUE;
5299 				} else if (!strcmp(name, "Int16")) {
5300 					t = MONO_TYPE_I2;
5301 					klass->blittable = TRUE;
5302 				} else if (!strcmp(name, "Int64")) {
5303 					t = MONO_TYPE_I8;
5304 					klass->blittable = TRUE;
5305 				} else if (!strcmp(name, "IntPtr")) {
5306 					t = MONO_TYPE_I;
5307 					klass->blittable = TRUE;
5308 				}
5309 				break;
5310 			case 'S':
5311 				if (!strcmp (name, "Single")) {
5312 					t = MONO_TYPE_R4;
5313 					klass->blittable = TRUE;
5314 				} else if (!strcmp(name, "SByte")) {
5315 					t = MONO_TYPE_I1;
5316 					klass->blittable = TRUE;
5317 				}
5318 				break;
5319 			case 'U':
5320 				if (!strcmp (name, "UInt32")) {
5321 					t = MONO_TYPE_U4;
5322 					klass->blittable = TRUE;
5323 				} else if (!strcmp(name, "UInt16")) {
5324 					t = MONO_TYPE_U2;
5325 					klass->blittable = TRUE;
5326 				} else if (!strcmp(name, "UInt64")) {
5327 					t = MONO_TYPE_U8;
5328 					klass->blittable = TRUE;
5329 				} else if (!strcmp(name, "UIntPtr")) {
5330 					t = MONO_TYPE_U;
5331 					klass->blittable = TRUE;
5332 				}
5333 				break;
5334 			case 'T':
5335 				if (!strcmp (name, "TypedReference")) {
5336 					t = MONO_TYPE_TYPEDBYREF;
5337 					klass->blittable = TRUE;
5338 				}
5339 				break;
5340 			case 'V':
5341 				if (!strcmp (name, "Void")) {
5342 					t = MONO_TYPE_VOID;
5343 				}
5344 				break;
5345 			default:
5346 				break;
5347 			}
5348 		}
5349 		klass->byval_arg.type = (MonoTypeEnum)t;
5350 		klass->this_arg.type = (MonoTypeEnum)t;
5351 	}
5352 
5353 	if (MONO_CLASS_IS_INTERFACE (klass)) {
5354 		klass->interface_id = mono_get_unique_iid (klass);
5355 
5356 		if (is_corlib && !strcmp (nspace, "System.Collections.Generic")) {
5357 			//FIXME IEnumerator needs to be special because GetEnumerator uses magic under the hood
5358 		    /* FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
5359 		    * MS returns diferrent types based on which instance is called. For example:
5360 		    * 	object obj = new byte[10][];
5361 		    *	Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
5362 		    *	Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
5363 		    * 	a != b ==> true
5364 			*/
5365 			if (!strcmp (name, "IList`1") || !strcmp (name, "ICollection`1") || !strcmp (name, "IEnumerable`1") || !strcmp (name, "IEnumerator`1"))
5366 				klass->is_array_special_interface = 1;
5367 		}
5368 	}
5369 }
5370 
5371 #ifndef DISABLE_COM
5372 /*
5373  * COM initialization is delayed until needed.
5374  * However when a [ComImport] attribute is present on a type it will trigger
5375  * the initialization. This is not a problem unless the BCL being executed
5376  * lacks the types that COM depends on (e.g. Variant on Silverlight).
5377  */
5378 static void
init_com_from_comimport(MonoClass * klass)5379 init_com_from_comimport (MonoClass *klass)
5380 {
5381 	/* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5382 	if (mono_security_core_clr_enabled ()) {
5383 		/* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5384 		if (!mono_security_core_clr_determine_platform_image (klass->image)) {
5385 			/* but it can not be made available for application (i.e. user code) since all COM calls
5386 			 * are considered native calls. In this case we fail with a TypeLoadException (just like
5387 			 * Silverlight 2 does */
5388 			mono_class_set_type_load_failure (klass, "");
5389 			return;
5390 		}
5391 	}
5392 
5393 	/* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5394 }
5395 #endif /*DISABLE_COM*/
5396 
5397 /*
5398  * LOCKING: this assumes the loader lock is held
5399  */
5400 void
mono_class_setup_parent(MonoClass * klass,MonoClass * parent)5401 mono_class_setup_parent (MonoClass *klass, MonoClass *parent)
5402 {
5403 	gboolean system_namespace;
5404 	gboolean is_corlib = mono_is_corlib_image (klass->image);
5405 
5406 	system_namespace = !strcmp (klass->name_space, "System") && is_corlib;
5407 
5408 	/* if root of the hierarchy */
5409 	if (system_namespace && !strcmp (klass->name, "Object")) {
5410 		klass->parent = NULL;
5411 		klass->instance_size = sizeof (MonoObject);
5412 		return;
5413 	}
5414 	if (!strcmp (klass->name, "<Module>")) {
5415 		klass->parent = NULL;
5416 		klass->instance_size = 0;
5417 		return;
5418 	}
5419 
5420 	if (!MONO_CLASS_IS_INTERFACE (klass)) {
5421 		/* Imported COM Objects always derive from __ComObject. */
5422 #ifndef DISABLE_COM
5423 		if (MONO_CLASS_IS_IMPORT (klass)) {
5424 			init_com_from_comimport (klass);
5425 			if (parent == mono_defaults.object_class)
5426 				parent = mono_class_get_com_object_class ();
5427 		}
5428 #endif
5429 		if (!parent) {
5430 			/* set the parent to something useful and safe, but mark the type as broken */
5431 			parent = mono_defaults.object_class;
5432 			mono_class_set_type_load_failure (klass, "");
5433 			g_assert (parent);
5434 		}
5435 
5436 		klass->parent = parent;
5437 
5438 		if (mono_class_is_ginst (parent) && !parent->name) {
5439 			/*
5440 			 * If the parent is a generic instance, we may get
5441 			 * called before it is fully initialized, especially
5442 			 * before it has its name.
5443 			 */
5444 			return;
5445 		}
5446 
5447 #ifndef DISABLE_REMOTING
5448 		klass->marshalbyref = parent->marshalbyref;
5449 		klass->contextbound  = parent->contextbound;
5450 #endif
5451 
5452 		klass->delegate  = parent->delegate;
5453 
5454 		if (MONO_CLASS_IS_IMPORT (klass) || mono_class_is_com_object (parent))
5455 			mono_class_set_is_com_object (klass);
5456 
5457 		if (system_namespace) {
5458 #ifndef DISABLE_REMOTING
5459 			if (klass->name [0] == 'M' && !strcmp (klass->name, "MarshalByRefObject"))
5460 				klass->marshalbyref = 1;
5461 
5462 			if (klass->name [0] == 'C' && !strcmp (klass->name, "ContextBoundObject"))
5463 				klass->contextbound  = 1;
5464 #endif
5465 			if (klass->name [0] == 'D' && !strcmp (klass->name, "Delegate"))
5466 				klass->delegate  = 1;
5467 		}
5468 
5469 		if (klass->parent->enumtype || (mono_is_corlib_image (klass->parent->image) && (strcmp (klass->parent->name, "ValueType") == 0) &&
5470 						(strcmp (klass->parent->name_space, "System") == 0)))
5471 			klass->valuetype = 1;
5472 		if (mono_is_corlib_image (klass->parent->image) && ((strcmp (klass->parent->name, "Enum") == 0) && (strcmp (klass->parent->name_space, "System") == 0))) {
5473 			klass->valuetype = klass->enumtype = 1;
5474 		}
5475 		/*klass->enumtype = klass->parent->enumtype; */
5476 	} else {
5477 		/* initialize com types if COM interfaces are present */
5478 #ifndef DISABLE_COM
5479 		if (MONO_CLASS_IS_IMPORT (klass))
5480 			init_com_from_comimport (klass);
5481 #endif
5482 		klass->parent = NULL;
5483 	}
5484 
5485 }
5486 
5487 /*
5488  * mono_class_setup_supertypes:
5489  * @class: a class
5490  *
5491  * Build the data structure needed to make fast type checks work.
5492  * This currently sets two fields in @class:
5493  *  - idepth: distance between @class and System.Object in the type
5494  *    hierarchy + 1
5495  *  - supertypes: array of classes: each element has a class in the hierarchy
5496  *    starting from @class up to System.Object
5497  *
5498  * LOCKING: Acquires the loader lock.
5499  */
5500 void
mono_class_setup_supertypes(MonoClass * klass)5501 mono_class_setup_supertypes (MonoClass *klass)
5502 {
5503 	int ms, idepth;
5504 	MonoClass **supertypes;
5505 
5506 	mono_atomic_load_acquire (supertypes, MonoClass **, &klass->supertypes);
5507 	if (supertypes)
5508 		return;
5509 
5510 	if (klass->parent && !klass->parent->supertypes)
5511 		mono_class_setup_supertypes (klass->parent);
5512 	if (klass->parent)
5513 		idepth = klass->parent->idepth + 1;
5514 	else
5515 		idepth = 1;
5516 
5517 	ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, idepth);
5518 	supertypes = (MonoClass **)mono_class_alloc0 (klass, sizeof (MonoClass *) * ms);
5519 
5520 	if (klass->parent) {
5521 		CHECKED_METADATA_WRITE_PTR ( supertypes [idepth - 1] , klass );
5522 
5523 		int supertype_idx;
5524 		for (supertype_idx = 0; supertype_idx < klass->parent->idepth; supertype_idx++)
5525 			CHECKED_METADATA_WRITE_PTR ( supertypes [supertype_idx] , klass->parent->supertypes [supertype_idx] );
5526 	} else {
5527 		CHECKED_METADATA_WRITE_PTR ( supertypes [0] , klass );
5528 	}
5529 
5530 	mono_memory_barrier ();
5531 
5532 	mono_loader_lock ();
5533 	klass->idepth = idepth;
5534 	/* Needed so idepth is visible before supertypes is set */
5535 	mono_memory_barrier ();
5536 	klass->supertypes = supertypes;
5537 	mono_loader_unlock ();
5538 }
5539 
5540 static gboolean
discard_gclass_due_to_failure(MonoClass * gclass,void * user_data)5541 discard_gclass_due_to_failure (MonoClass *gclass, void *user_data)
5542 {
5543 	return mono_class_get_generic_class (gclass)->container_class == user_data;
5544 }
5545 
5546 static gboolean
fix_gclass_incomplete_instantiation(MonoClass * gclass,void * user_data)5547 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5548 {
5549 	MonoClass *gtd = (MonoClass*)user_data;
5550 	/* Only try to fix generic instances of @gtd */
5551 	if (mono_class_get_generic_class (gclass)->container_class != gtd)
5552 		return FALSE;
5553 
5554 	/* Check if the generic instance has no parent. */
5555 	if (gtd->parent && !gclass->parent)
5556 		mono_generic_class_setup_parent (gclass, gtd);
5557 
5558 	return TRUE;
5559 }
5560 
5561 static void
mono_class_set_failure_and_error(MonoClass * klass,MonoError * error,const char * msg)5562 mono_class_set_failure_and_error (MonoClass *klass, MonoError *error, const char *msg)
5563 {
5564 	mono_class_set_type_load_failure (klass, "%s", msg);
5565 	mono_error_set_type_load_class (error, klass, "%s", msg);
5566 }
5567 
5568 /**
5569  * mono_class_create_from_typedef:
5570  * \param image: image where the token is valid
5571  * \param type_token:  typedef token
5572  * \param error:  used to return any error found while creating the type
5573  *
5574  * Create the MonoClass* representing the specified type token.
5575  * \p type_token must be a TypeDef token.
5576  *
5577  * FIXME: don't return NULL on failure, just let the caller figure it out.
5578  */
5579 static MonoClass *
mono_class_create_from_typedef(MonoImage * image,guint32 type_token,MonoError * error)5580 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5581 {
5582 	MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5583 	MonoClass *klass, *parent = NULL;
5584 	guint32 cols [MONO_TYPEDEF_SIZE];
5585 	guint32 cols_next [MONO_TYPEDEF_SIZE];
5586 	guint tidx = mono_metadata_token_index (type_token);
5587 	MonoGenericContext *context = NULL;
5588 	const char *name, *nspace;
5589 	guint icount = 0;
5590 	MonoClass **interfaces;
5591 	guint32 field_last, method_last;
5592 	guint32 nesting_tokeen;
5593 
5594 	error_init (error);
5595 
5596 	if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5597 		mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5598 		return NULL;
5599 	}
5600 
5601 	mono_loader_lock ();
5602 
5603 	if ((klass = (MonoClass *)mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5604 		mono_loader_unlock ();
5605 		return klass;
5606 	}
5607 
5608 	mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5609 
5610 	name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5611 	nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5612 
5613 	if (mono_metadata_has_generic_params (image, type_token)) {
5614 		klass = mono_image_alloc0 (image, sizeof (MonoClassGtd));
5615 		klass->class_kind = MONO_CLASS_GTD;
5616 		UnlockedAdd (&classes_size, sizeof (MonoClassGtd));
5617 		++class_gtd_count;
5618 	} else {
5619 		klass = mono_image_alloc0 (image, sizeof (MonoClassDef));
5620 		klass->class_kind = MONO_CLASS_DEF;
5621 		UnlockedAdd (&classes_size, sizeof (MonoClassDef));
5622 		++class_def_count;
5623 	}
5624 
5625 	klass->name = name;
5626 	klass->name_space = nspace;
5627 
5628 	MONO_PROFILER_RAISE (class_loading, (klass));
5629 
5630 	klass->image = image;
5631 	klass->type_token = type_token;
5632 	mono_class_set_flags (klass, cols [MONO_TYPEDEF_FLAGS]);
5633 
5634 	mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), klass);
5635 
5636 	/*
5637 	 * Check whether we're a generic type definition.
5638 	 */
5639 	if (mono_class_is_gtd (klass)) {
5640 		MonoGenericContainer *generic_container = mono_metadata_load_generic_params (image, klass->type_token, NULL);
5641 		generic_container->owner.klass = klass;
5642 		generic_container->is_anonymous = FALSE; // Owner class is now known, container is no longer anonymous
5643 		context = &generic_container->context;
5644 		mono_class_set_generic_container (klass, generic_container);
5645 		MonoType *canonical_inst = &((MonoClassGtd*)klass)->canonical_inst;
5646 		canonical_inst->type = MONO_TYPE_GENERICINST;
5647 		canonical_inst->data.generic_class = mono_metadata_lookup_generic_class (klass, context->class_inst, FALSE);
5648 		enable_gclass_recording ();
5649 	}
5650 
5651 	if (cols [MONO_TYPEDEF_EXTENDS]) {
5652 		MonoClass *tmp;
5653 		guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5654 
5655 		if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5656 			/*WARNING: this must satisfy mono_metadata_type_hash*/
5657 			klass->this_arg.byref = 1;
5658 			klass->this_arg.data.klass = klass;
5659 			klass->this_arg.type = MONO_TYPE_CLASS;
5660 			klass->byval_arg.data.klass = klass;
5661 			klass->byval_arg.type = MONO_TYPE_CLASS;
5662 		}
5663 		parent = mono_class_get_checked (image, parent_token, error);
5664 		if (parent && context) /* Always inflate */
5665 			parent = mono_class_inflate_generic_class_checked (parent, context, error);
5666 
5667 		if (parent == NULL) {
5668 			mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5669 			goto parent_failure;
5670 		}
5671 
5672 		for (tmp = parent; tmp; tmp = tmp->parent) {
5673 			if (tmp == klass) {
5674 				mono_class_set_failure_and_error (klass, error, "Cycle found while resolving parent");
5675 				goto parent_failure;
5676 			}
5677 			if (mono_class_is_gtd (klass) && mono_class_is_ginst (tmp) && mono_class_get_generic_class (tmp)->container_class == klass) {
5678 				mono_class_set_failure_and_error (klass, error, "Parent extends generic instance of this type");
5679 				goto parent_failure;
5680 			}
5681 		}
5682 	}
5683 
5684 	mono_class_setup_parent (klass, parent);
5685 
5686 	/* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5687 	mono_class_setup_mono_type (klass);
5688 
5689 	if (mono_class_is_gtd (klass))
5690 		disable_gclass_recording (fix_gclass_incomplete_instantiation, klass);
5691 
5692 	/*
5693 	 * This might access klass->byval_arg for recursion generated by generic constraints,
5694 	 * so it has to come after setup_mono_type ().
5695 	 */
5696 	if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5697 		klass->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5698 		if (!mono_error_ok (error)) {
5699 			/*FIXME implement a mono_class_set_failure_from_mono_error */
5700 			mono_class_set_type_load_failure (klass, "%s",  mono_error_get_message (error));
5701 			mono_loader_unlock ();
5702 			MONO_PROFILER_RAISE (class_failed, (klass));
5703 			return NULL;
5704 		}
5705 	}
5706 
5707 	if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5708 		klass->unicode = 1;
5709 
5710 #ifdef HOST_WIN32
5711 	if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5712 		klass->unicode = 1;
5713 #endif
5714 
5715 	klass->cast_class = klass->element_class = klass;
5716 	if (mono_is_corlib_image (klass->image)) {
5717 		switch (klass->byval_arg.type) {
5718 			case MONO_TYPE_I1:
5719 				if (mono_defaults.byte_class)
5720 					klass->cast_class = mono_defaults.byte_class;
5721 				break;
5722 			case MONO_TYPE_U1:
5723 				if (mono_defaults.sbyte_class)
5724 					mono_defaults.sbyte_class = klass;
5725 				break;
5726 			case MONO_TYPE_I2:
5727 				if (mono_defaults.uint16_class)
5728 					mono_defaults.uint16_class = klass;
5729 				break;
5730 			case MONO_TYPE_U2:
5731 				if (mono_defaults.int16_class)
5732 					klass->cast_class = mono_defaults.int16_class;
5733 				break;
5734 			case MONO_TYPE_I4:
5735 				if (mono_defaults.uint32_class)
5736 					mono_defaults.uint32_class = klass;
5737 				break;
5738 			case MONO_TYPE_U4:
5739 				if (mono_defaults.int32_class)
5740 					klass->cast_class = mono_defaults.int32_class;
5741 				break;
5742 			case MONO_TYPE_I8:
5743 				if (mono_defaults.uint64_class)
5744 					mono_defaults.uint64_class = klass;
5745 				break;
5746 			case MONO_TYPE_U8:
5747 				if (mono_defaults.int64_class)
5748 					klass->cast_class = mono_defaults.int64_class;
5749 				break;
5750 		}
5751 	}
5752 
5753 	if (!klass->enumtype) {
5754 		if (!mono_metadata_interfaces_from_typedef_full (
5755 			    image, type_token, &interfaces, &icount, FALSE, context, error)){
5756 
5757 			mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5758 			mono_loader_unlock ();
5759 			MONO_PROFILER_RAISE (class_failed, (klass));
5760 			return NULL;
5761 		}
5762 
5763 		/* This is required now that it is possible for more than 2^16 interfaces to exist. */
5764 		g_assert(icount <= 65535);
5765 
5766 		klass->interfaces = interfaces;
5767 		klass->interface_count = icount;
5768 		klass->interfaces_inited = 1;
5769 	}
5770 
5771 	/*g_print ("Load class %s\n", name);*/
5772 
5773 	/*
5774 	 * Compute the field and method lists
5775 	 */
5776 	int first_field_idx = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5777 	mono_class_set_first_field_idx (klass, first_field_idx);
5778 	int first_method_idx = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5779 	mono_class_set_first_method_idx (klass, first_method_idx);
5780 
5781 	if (tt->rows > tidx){
5782 		mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5783 		field_last  = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5784 		method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5785 	} else {
5786 		field_last  = image->tables [MONO_TABLE_FIELD].rows;
5787 		method_last = image->tables [MONO_TABLE_METHOD].rows;
5788 	}
5789 
5790 	if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5791 	    cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5792 		mono_class_set_field_count (klass, field_last - first_field_idx);
5793 	if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5794 		mono_class_set_method_count (klass, method_last - first_method_idx);
5795 
5796 	/* reserve space to store vector pointer in arrays */
5797 	if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5798 		klass->instance_size += 2 * sizeof (gpointer);
5799 		g_assert (mono_class_get_field_count (klass) == 0);
5800 	}
5801 
5802 	if (klass->enumtype) {
5803 		MonoType *enum_basetype = mono_class_find_enum_basetype (klass, error);
5804 		if (!enum_basetype) {
5805 			/*set it to a default value as the whole runtime can't handle this to be null*/
5806 			klass->cast_class = klass->element_class = mono_defaults.int32_class;
5807 			mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5808 			mono_loader_unlock ();
5809 			MONO_PROFILER_RAISE (class_failed, (klass));
5810 			return NULL;
5811 		}
5812 		klass->cast_class = klass->element_class = mono_class_from_mono_type (enum_basetype);
5813 	}
5814 
5815 	/*
5816 	 * If we're a generic type definition, load the constraints.
5817 	 * We must do this after the class has been constructed to make certain recursive scenarios
5818 	 * work.
5819 	 */
5820 	if (mono_class_is_gtd (klass) && !mono_metadata_load_generic_param_constraints_checked (image, type_token, mono_class_get_generic_container (klass), error)) {
5821 		mono_class_set_type_load_failure (klass, "Could not load generic parameter constrains due to %s", mono_error_get_message (error));
5822 		mono_loader_unlock ();
5823 		MONO_PROFILER_RAISE (class_failed, (klass));
5824 		return NULL;
5825 	}
5826 
5827 	if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5828 		if (!strncmp (name, "Vector", 6))
5829 			klass->simd_type = !strcmp (name + 6, "2d") || !strcmp (name + 6, "2ul") || !strcmp (name + 6, "2l") || !strcmp (name + 6, "4f") || !strcmp (name + 6, "4ui") || !strcmp (name + 6, "4i") || !strcmp (name + 6, "8s") || !strcmp (name + 6, "8us") || !strcmp (name + 6, "16b") || !strcmp (name + 6, "16sb");
5830 	} else if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "System.Numerics") && !strcmp (nspace, "System.Numerics")) {
5831 		if (!strcmp (name, "Vector2") || !strcmp (name, "Vector3") || !strcmp (name, "Vector4"))
5832 			klass->simd_type = 1;
5833 	}
5834 
5835 	mono_loader_unlock ();
5836 
5837 	MONO_PROFILER_RAISE (class_loaded, (klass));
5838 
5839 	return klass;
5840 
5841 parent_failure:
5842 	if (mono_class_is_gtd (klass))
5843 		disable_gclass_recording (discard_gclass_due_to_failure, klass);
5844 
5845 	mono_class_setup_mono_type (klass);
5846 	mono_loader_unlock ();
5847 	MONO_PROFILER_RAISE (class_failed, (klass));
5848 	return NULL;
5849 }
5850 
5851 /** Is klass a Nullable<T> ginst? */
5852 gboolean
mono_class_is_nullable(MonoClass * klass)5853 mono_class_is_nullable (MonoClass *klass)
5854 {
5855 	MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
5856 	return gklass && gklass->container_class == mono_defaults.generic_nullable_class;
5857 }
5858 
5859 
5860 /** if klass is T? return T */
5861 MonoClass*
mono_class_get_nullable_param(MonoClass * klass)5862 mono_class_get_nullable_param (MonoClass *klass)
5863 {
5864        g_assert (mono_class_is_nullable (klass));
5865        return mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
5866 }
5867 
5868 static void
mono_generic_class_setup_parent(MonoClass * klass,MonoClass * gtd)5869 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5870 {
5871 	if (gtd->parent) {
5872 		MonoError error;
5873 		MonoGenericClass *gclass = mono_class_get_generic_class (klass);
5874 
5875 		klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5876 		if (!mono_error_ok (&error)) {
5877 			/*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5878 			klass->parent = mono_defaults.object_class;
5879 			mono_class_set_type_load_failure (klass, "Parent is a generic type instantiation that failed due to: %s", mono_error_get_message (&error));
5880 			mono_error_cleanup (&error);
5881 		}
5882 	}
5883 	mono_loader_lock ();
5884 	if (klass->parent)
5885 		mono_class_setup_parent (klass, klass->parent);
5886 
5887 	if (klass->enumtype) {
5888 		klass->cast_class = gtd->cast_class;
5889 		klass->element_class = gtd->element_class;
5890 	}
5891 	mono_loader_unlock ();
5892 }
5893 
5894 gboolean
mono_type_is_primitive(MonoType * type)5895 mono_type_is_primitive (MonoType *type)
5896 {
5897 	return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
5898 			type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
5899 }
5900 
5901 /*
5902  * Create the `MonoClass' for an instantiation of a generic type.
5903  * We only do this if we actually need it.
5904  */
5905 MonoClass*
mono_generic_class_get_class(MonoGenericClass * gclass)5906 mono_generic_class_get_class (MonoGenericClass *gclass)
5907 {
5908 	MonoClass *klass, *gklass;
5909 
5910 	if (gclass->cached_class)
5911 		return gclass->cached_class;
5912 
5913 	klass = (MonoClass *)mono_image_set_alloc0 (gclass->owner, sizeof (MonoClassGenericInst));
5914 
5915 	gklass = gclass->container_class;
5916 
5917 	if (gklass->nested_in) {
5918 		/* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
5919 		klass->nested_in = gklass->nested_in;
5920 	}
5921 
5922 	klass->name = gklass->name;
5923 	klass->name_space = gklass->name_space;
5924 
5925 	klass->image = gklass->image;
5926 	klass->type_token = gklass->type_token;
5927 
5928 	klass->class_kind = MONO_CLASS_GINST;
5929 	//FIXME add setter
5930 	((MonoClassGenericInst*)klass)->generic_class = gclass;
5931 
5932 	klass->byval_arg.type = MONO_TYPE_GENERICINST;
5933 	klass->this_arg.type = klass->byval_arg.type;
5934 	klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
5935 	klass->this_arg.byref = TRUE;
5936 	klass->enumtype = gklass->enumtype;
5937 	klass->valuetype = gklass->valuetype;
5938 
5939 
5940 	if (gklass->image->assembly_name && !strcmp (gklass->image->assembly_name, "System.Numerics.Vectors") && !strcmp (gklass->name_space, "System.Numerics") && !strcmp (gklass->name, "Vector`1")) {
5941 		g_assert (gclass->context.class_inst);
5942 		g_assert (gclass->context.class_inst->type_argc > 0);
5943 		if (mono_type_is_primitive (gclass->context.class_inst->type_argv [0]))
5944 			klass->simd_type = 1;
5945 	}
5946 	klass->is_array_special_interface = gklass->is_array_special_interface;
5947 
5948 	klass->cast_class = klass->element_class = klass;
5949 
5950 	if (gclass->is_dynamic) {
5951 		/*
5952 		 * We don't need to do any init workf with unbaked typebuilders. Generic instances created at this point will be later unregistered and/or fixed.
5953 		 * This is to avoid work that would probably give wrong results as fields change as we build the TypeBuilder.
5954 		 * See remove_instantiations_of_and_ensure_contents in reflection.c and its usage in reflection.c to understand the fixup stage of SRE banking.
5955 		*/
5956 		if (!gklass->wastypebuilder)
5957 			klass->inited = 1;
5958 
5959 		if (klass->enumtype) {
5960 			/*
5961 			 * For enums, gklass->fields might not been set, but instance_size etc. is
5962 			 * already set in mono_reflection_create_internal_class (). For non-enums,
5963 			 * these will be computed normally in mono_class_layout_fields ().
5964 			 */
5965 			klass->instance_size = gklass->instance_size;
5966 			klass->sizes.class_size = gklass->sizes.class_size;
5967 			klass->size_inited = 1;
5968 		}
5969 	}
5970 
5971 	mono_loader_lock ();
5972 
5973 	if (gclass->cached_class) {
5974 		mono_loader_unlock ();
5975 		return gclass->cached_class;
5976 	}
5977 
5978 	if (record_gclass_instantiation > 0)
5979 		gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
5980 
5981 	if (mono_class_is_nullable (klass))
5982 		klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
5983 
5984 	MONO_PROFILER_RAISE (class_loading, (klass));
5985 
5986 	mono_generic_class_setup_parent (klass, gklass);
5987 
5988 	if (gclass->is_dynamic)
5989 		mono_class_setup_supertypes (klass);
5990 
5991 	mono_memory_barrier ();
5992 	gclass->cached_class = klass;
5993 
5994 	MONO_PROFILER_RAISE (class_loaded, (klass));
5995 
5996 	++class_ginst_count;
5997 	inflated_classes_size += sizeof (MonoClassGenericInst);
5998 
5999 	mono_loader_unlock ();
6000 
6001 	return klass;
6002 }
6003 
6004 static MonoImage *
get_image_for_container(MonoGenericContainer * container)6005 get_image_for_container (MonoGenericContainer *container)
6006 {
6007 	MonoImage *result;
6008 	if (container->is_anonymous) {
6009 		result = container->owner.image;
6010 	} else {
6011 		MonoClass *klass;
6012 		if (container->is_method) {
6013 			MonoMethod *method = container->owner.method;
6014 			g_assert_checked (method);
6015 			klass = method->klass;
6016 		} else {
6017 			klass = container->owner.klass;
6018 		}
6019 		g_assert_checked (klass);
6020 		result = klass->image;
6021 	}
6022 	g_assert (result);
6023 	return result;
6024 }
6025 
6026 MonoImage *
get_image_for_generic_param(MonoGenericParam * param)6027 get_image_for_generic_param (MonoGenericParam *param)
6028 {
6029 	MonoGenericContainer *container = mono_generic_param_owner (param);
6030 	g_assert_checked (container);
6031 	return get_image_for_container (container);
6032 }
6033 
6034 // Make a string in the designated image consisting of a single integer.
6035 #define INT_STRING_SIZE 16
6036 char *
make_generic_name_string(MonoImage * image,int num)6037 make_generic_name_string (MonoImage *image, int num)
6038 {
6039 	char *name = (char *)mono_image_alloc0 (image, INT_STRING_SIZE);
6040 	g_snprintf (name, INT_STRING_SIZE, "%d", num);
6041 	return name;
6042 }
6043 
6044 // This is called by mono_class_from_generic_parameter_internal when a new class must be created.
6045 // pinfo is derived from param by the caller for us.
6046 static MonoClass*
make_generic_param_class(MonoGenericParam * param,MonoGenericParamInfo * pinfo)6047 make_generic_param_class (MonoGenericParam *param, MonoGenericParamInfo *pinfo)
6048 {
6049 	MonoClass *klass, **ptr;
6050 	int count, pos, i;
6051 	MonoGenericContainer *container = mono_generic_param_owner (param);
6052 	g_assert_checked (container);
6053 
6054 	MonoImage *image = get_image_for_container (container);
6055 	gboolean is_mvar = container->is_method;
6056 	gboolean is_anonymous = container->is_anonymous;
6057 
6058 	klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassGenericParam));
6059 	klass->class_kind = MONO_CLASS_GPARAM;
6060 	UnlockedAdd (&classes_size, sizeof (MonoClassGenericParam));
6061 	UnlockedIncrement (&class_gparam_count);
6062 
6063 	if (pinfo) {
6064 		CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name , pinfo->name );
6065 	} else {
6066 		int n = mono_generic_param_num (param);
6067 		CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->name , make_generic_name_string (image, n) );
6068 	}
6069 
6070 	if (is_anonymous) {
6071 		CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space ,  "" );
6072 	} else if (is_mvar) {
6073 		MonoMethod *omethod = container->owner.method;
6074 		CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , (omethod && omethod->klass) ? omethod->klass->name_space : "" );
6075 	} else {
6076 		MonoClass *oklass = container->owner.klass;
6077 		CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , oklass ? oklass->name_space : "" );
6078 	}
6079 
6080 	MONO_PROFILER_RAISE (class_loading, (klass));
6081 
6082 	// Count non-NULL items in pinfo->constraints
6083 	count = 0;
6084 	if (pinfo)
6085 		for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6086 			;
6087 
6088 	pos = 0;
6089 	if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6090 		CHECKED_METADATA_WRITE_PTR ( klass->parent , pinfo->constraints [0] );
6091 		pos++;
6092 	} else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) {
6093 		CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_class_load_from_name (mono_defaults.corlib, "System", "ValueType") );
6094 	} else {
6095 		CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_defaults.object_class );
6096 	}
6097 
6098 	if (count - pos > 0) {
6099 		klass->interface_count = count - pos;
6100 		CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->interfaces , (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos)) );
6101 		klass->interfaces_inited = TRUE;
6102 		for (i = pos; i < count; i++)
6103 			CHECKED_METADATA_WRITE_PTR ( klass->interfaces [i - pos] , pinfo->constraints [i] );
6104 	}
6105 
6106 	CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->image , image );
6107 
6108 	klass->inited = TRUE;
6109 	CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->cast_class ,    klass );
6110 	CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->element_class , klass );
6111 
6112 	klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6113 	klass->this_arg.type = klass->byval_arg.type;
6114 	CHECKED_METADATA_WRITE_PTR ( klass->this_arg.data.generic_param ,  param );
6115 	CHECKED_METADATA_WRITE_PTR ( klass->byval_arg.data.generic_param , param );
6116 	klass->this_arg.byref = TRUE;
6117 
6118 	/* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6119 	klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6120 
6121 	/*Init these fields to sane values*/
6122 	klass->min_align = 1;
6123 	/*
6124 	 * This makes sure the the value size of this class is equal to the size of the types the gparam is
6125 	 * constrained to, the JIT depends on this.
6126 	 */
6127 	klass->instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
6128 	mono_memory_barrier ();
6129 	klass->size_inited = 1;
6130 
6131 	mono_class_setup_supertypes (klass);
6132 
6133 	if (count - pos > 0) {
6134 		mono_class_setup_vtable (klass->parent);
6135 		if (mono_class_has_failure (klass->parent))
6136 			mono_class_set_type_load_failure (klass, "Failed to setup parent interfaces");
6137 		else
6138 			setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6139 	}
6140 
6141 	return klass;
6142 }
6143 
6144 #define FAST_CACHE_SIZE 16
6145 
6146 /*
6147  * get_anon_gparam_class and set_anon_gparam_class are helpers for mono_class_from_generic_parameter_internal.
6148  * The latter will sometimes create MonoClasses for anonymous generic params. To prevent this being wasteful,
6149  * we cache the MonoClasses.
6150  * FIXME: It would be better to instead cache anonymous MonoGenericParams, and allow anonymous params to point directly to classes using the pklass field.
6151  * LOCKING: Takes the image lock depending on @take_lock.
6152  */
6153 static MonoClass *
get_anon_gparam_class(MonoGenericParam * param,gboolean take_lock)6154 get_anon_gparam_class (MonoGenericParam *param, gboolean take_lock)
6155 {
6156 	int n = mono_generic_param_num (param);
6157 	MonoImage *image = get_image_for_generic_param (param);
6158 	gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6159 	MonoClass *klass = NULL;
6160 	GHashTable *ht;
6161 
6162 	g_assert (image);
6163 
6164 	// For params with a small num and no constraints, we use a "fast" cache which does simple num lookup in an array.
6165 	// For high numbers or constraints we have to use pointer hashes.
6166 	if (param->gshared_constraint) {
6167 		ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6168 		if (ht) {
6169 			if (take_lock)
6170 				mono_image_lock (image);
6171 			klass = (MonoClass *)g_hash_table_lookup (ht, param);
6172 			if (take_lock)
6173 				mono_image_unlock (image);
6174 		}
6175 		return klass;
6176 	}
6177 
6178 	if (n < FAST_CACHE_SIZE) {
6179 		if (is_mvar)
6180 			return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6181 		else
6182 			return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6183 	} else {
6184 		ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6185 		if (ht) {
6186 			if (take_lock)
6187 				mono_image_lock (image);
6188 			klass = (MonoClass *)g_hash_table_lookup (ht, GINT_TO_POINTER (n));
6189 			if (take_lock)
6190 				mono_image_unlock (image);
6191 		}
6192 		return klass;
6193 	}
6194 }
6195 
6196 /*
6197  * LOCKING: Image lock (param->image) must be held
6198  */
6199 static void
set_anon_gparam_class(MonoGenericParam * param,MonoClass * klass)6200 set_anon_gparam_class (MonoGenericParam *param, MonoClass *klass)
6201 {
6202 	int n = mono_generic_param_num (param);
6203 	MonoImage *image = get_image_for_generic_param (param);
6204 	gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6205 
6206 	g_assert (image);
6207 
6208 	if (param->gshared_constraint) {
6209 		GHashTable *ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6210 		if (!ht) {
6211 			ht = g_hash_table_new ((GHashFunc)mono_metadata_generic_param_hash, (GEqualFunc)mono_metadata_generic_param_equal);
6212 			mono_memory_barrier ();
6213 			if (is_mvar)
6214 				image->mvar_cache_constrained = ht;
6215 			else
6216 				image->var_cache_constrained = ht;
6217 		}
6218 		g_hash_table_insert (ht, param, klass);
6219 	} else if (n < FAST_CACHE_SIZE) {
6220 		if (is_mvar) {
6221 			/* Requires locking to avoid droping an already published class */
6222 			if (!image->mvar_cache_fast)
6223 				image->mvar_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6224 			image->mvar_cache_fast [n] = klass;
6225 		} else {
6226 			if (!image->var_cache_fast)
6227 				image->var_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6228 			image->var_cache_fast [n] = klass;
6229 		}
6230 	} else {
6231 		GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6232 		if (!ht) {
6233 			ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6234 			if (!ht) {
6235 				ht = g_hash_table_new (NULL, NULL);
6236 				mono_memory_barrier ();
6237 				if (is_mvar)
6238 					image->mvar_cache_slow = ht;
6239 				else
6240 					image->var_cache_slow = ht;
6241 			}
6242 		}
6243 		g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6244 	}
6245 }
6246 
6247 /*
6248  * LOCKING: Acquires the image lock (@image).
6249  */
6250 MonoClass *
mono_class_from_generic_parameter_internal(MonoGenericParam * param)6251 mono_class_from_generic_parameter_internal (MonoGenericParam *param)
6252 {
6253 	MonoImage *image = get_image_for_generic_param (param);
6254 	MonoGenericParamInfo *pinfo = mono_generic_param_info (param);
6255 	MonoClass *klass, *klass2;
6256 
6257 	// If a klass already exists for this object and is cached, return it.
6258 	if (pinfo) // Non-anonymous
6259 		klass = pinfo->pklass;
6260 	else     // Anonymous
6261 		klass = get_anon_gparam_class (param, TRUE);
6262 
6263 	if (klass)
6264 		return klass;
6265 
6266 	// Create a new klass
6267 	klass = make_generic_param_class (param, pinfo);
6268 
6269 	// Now we need to cache the klass we created.
6270 	// But since we wait to grab the lock until after creating the klass, we need to check to make sure
6271 	// another thread did not get in and cache a klass ahead of us. In that case, return their klass
6272 	// and allow our newly-created klass object to just leak.
6273 	mono_memory_barrier ();
6274 
6275 	mono_image_lock (image);
6276 
6277     // Here "klass2" refers to the klass potentially created by the other thread.
6278 	if (pinfo) // Repeat check from above
6279 		klass2 = pinfo->pklass;
6280 	else
6281 		klass2 = get_anon_gparam_class (param, FALSE);
6282 
6283 	if (klass2) {
6284 		klass = klass2;
6285 	} else {
6286 		// Cache here
6287 		if (pinfo)
6288 			pinfo->pklass = klass;
6289 		else
6290 			set_anon_gparam_class (param, klass);
6291 	}
6292 	mono_image_unlock (image);
6293 
6294 	/* FIXME: Should this go inside 'make_generic_param_klass'? */
6295 	if (klass2)
6296 		MONO_PROFILER_RAISE (class_failed, (klass2));
6297 	else
6298 		MONO_PROFILER_RAISE (class_loaded, (klass));
6299 
6300 	return klass;
6301 }
6302 
6303 /**
6304  * mono_class_from_generic_parameter:
6305  * \param param Parameter to find/construct a class for.
6306  * \param arg2 Is ignored.
6307  * \param arg3 Is ignored.
6308  */
6309 MonoClass *
mono_class_from_generic_parameter(MonoGenericParam * param,MonoImage * arg2 G_GNUC_UNUSED,gboolean arg3 G_GNUC_UNUSED)6310 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *arg2 G_GNUC_UNUSED, gboolean arg3 G_GNUC_UNUSED)
6311 {
6312 	return mono_class_from_generic_parameter_internal (param);
6313 }
6314 
6315 /**
6316  * mono_ptr_class_get:
6317  */
6318 MonoClass *
mono_ptr_class_get(MonoType * type)6319 mono_ptr_class_get (MonoType *type)
6320 {
6321 	MonoClass *result;
6322 	MonoClass *el_class;
6323 	MonoImage *image;
6324 	char *name;
6325 	MonoImageSet* image_set;
6326 
6327 	el_class = mono_class_from_mono_type (type);
6328 	image = el_class->image;
6329 	image_set  = class_kind_may_contain_generic_instances (el_class->class_kind) ? mono_metadata_get_image_set_for_class (el_class) : NULL;
6330 
6331 	if (image_set) {
6332 		mono_image_set_lock (image_set);
6333 		if (image_set->ptr_cache) {
6334 			if ((result = (MonoClass *)g_hash_table_lookup (image_set->ptr_cache, el_class))) {
6335 				mono_image_set_unlock (image_set);
6336 				return result;
6337 			}
6338 		}
6339 		mono_image_set_unlock (image_set);
6340 	} else {
6341 		mono_image_lock (image);
6342 		if (image->ptr_cache) {
6343 			if ((result = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6344 				mono_image_unlock (image);
6345 				return result;
6346 			}
6347 		}
6348 		mono_image_unlock (image);
6349 	}
6350 
6351 	result = image_set ? (MonoClass *)mono_image_set_alloc0 (image_set, sizeof (MonoClassPointer)) : (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassPointer));
6352 
6353 	UnlockedAdd (&classes_size, sizeof (MonoClassPointer));
6354 	++class_pointer_count;
6355 
6356 	result->parent = NULL; /* no parent for PTR types */
6357 	result->name_space = el_class->name_space;
6358 	name = g_strdup_printf ("%s*", el_class->name);
6359 	result->name = image_set ? mono_image_set_strdup (image_set, name) : mono_image_strdup (image, name);
6360 	result->class_kind = MONO_CLASS_POINTER;
6361 	g_free (name);
6362 
6363 	MONO_PROFILER_RAISE (class_loading, (result));
6364 
6365 	result->image = el_class->image;
6366 	result->inited = TRUE;
6367 	result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6368 	result->min_align = sizeof (gpointer);
6369 	result->cast_class = result->element_class = el_class;
6370 	result->blittable = TRUE;
6371 
6372 	result->byval_arg.type = MONO_TYPE_PTR;
6373 	result->this_arg.type = result->byval_arg.type;
6374 	result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6375 	result->this_arg.byref = TRUE;
6376 
6377 	mono_class_setup_supertypes (result);
6378 
6379 	if (image_set) {
6380 		mono_image_set_lock (image_set);
6381 		if (image_set->ptr_cache) {
6382 			MonoClass *result2;
6383 			if ((result2 = (MonoClass *)g_hash_table_lookup (image_set->ptr_cache, el_class))) {
6384 				mono_image_set_unlock (image_set);
6385 				MONO_PROFILER_RAISE (class_failed, (result));
6386 				return result2;
6387 			}
6388 		}
6389 		else {
6390 			image_set->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6391 		}
6392 		g_hash_table_insert (image_set->ptr_cache, el_class, result);
6393 		mono_image_set_unlock (image_set);
6394 	} else {
6395 		mono_image_lock (image);
6396 		if (image->ptr_cache) {
6397 			MonoClass *result2;
6398 			if ((result2 = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6399 				mono_image_unlock (image);
6400 				MONO_PROFILER_RAISE (class_failed, (result));
6401 				return result2;
6402 			}
6403 		} else {
6404 			image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6405 		}
6406 		g_hash_table_insert (image->ptr_cache, el_class, result);
6407 		mono_image_unlock (image);
6408 	}
6409 
6410 	MONO_PROFILER_RAISE (class_loaded, (result));
6411 
6412 	return result;
6413 }
6414 
6415 static MonoClass *
mono_fnptr_class_get(MonoMethodSignature * sig)6416 mono_fnptr_class_get (MonoMethodSignature *sig)
6417 {
6418 	MonoClass *result, *cached;
6419 	static GHashTable *ptr_hash = NULL;
6420 
6421 	/* FIXME: These should be allocate from a mempool as well, but which one ? */
6422 
6423 	mono_loader_lock ();
6424 	if (!ptr_hash)
6425 		ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6426 	cached = (MonoClass *)g_hash_table_lookup (ptr_hash, sig);
6427 	mono_loader_unlock ();
6428 	if (cached)
6429 		return cached;
6430 
6431 	result = g_new0 (MonoClass, 1);
6432 
6433 	result->parent = NULL; /* no parent for PTR types */
6434 	result->name_space = "System";
6435 	result->name = "MonoFNPtrFakeClass";
6436 	result->class_kind = MONO_CLASS_POINTER;
6437 
6438 	result->image = mono_defaults.corlib; /* need to fix... */
6439 	result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6440 	result->min_align = sizeof (gpointer);
6441 	result->cast_class = result->element_class = result;
6442 	result->byval_arg.type = MONO_TYPE_FNPTR;
6443 	result->this_arg.type = result->byval_arg.type;
6444 	result->this_arg.data.method = result->byval_arg.data.method = sig;
6445 	result->this_arg.byref = TRUE;
6446 	result->blittable = TRUE;
6447 	result->inited = TRUE;
6448 
6449 	mono_class_setup_supertypes (result);
6450 
6451 	mono_loader_lock ();
6452 
6453 	cached = (MonoClass *)g_hash_table_lookup (ptr_hash, sig);
6454 	if (cached) {
6455 		g_free (result);
6456 		mono_loader_unlock ();
6457 		return cached;
6458 	}
6459 
6460 	MONO_PROFILER_RAISE (class_loading, (result));
6461 
6462 	UnlockedAdd (&classes_size, sizeof (MonoClassPointer));
6463 	++class_pointer_count;
6464 
6465 	g_hash_table_insert (ptr_hash, sig, result);
6466 
6467 	mono_loader_unlock ();
6468 
6469 	MONO_PROFILER_RAISE (class_loaded, (result));
6470 
6471 	return result;
6472 }
6473 
6474 /**
6475  * mono_class_from_mono_type:
6476  * \param type describes the type to return
6477  * \returns a \c MonoClass for the specified \c MonoType, the value is never NULL.
6478  */
6479 MonoClass *
mono_class_from_mono_type(MonoType * type)6480 mono_class_from_mono_type (MonoType *type)
6481 {
6482 	switch (type->type) {
6483 	case MONO_TYPE_OBJECT:
6484 		return type->data.klass? type->data.klass: mono_defaults.object_class;
6485 	case MONO_TYPE_VOID:
6486 		return type->data.klass? type->data.klass: mono_defaults.void_class;
6487 	case MONO_TYPE_BOOLEAN:
6488 		return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6489 	case MONO_TYPE_CHAR:
6490 		return type->data.klass? type->data.klass: mono_defaults.char_class;
6491 	case MONO_TYPE_I1:
6492 		return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6493 	case MONO_TYPE_U1:
6494 		return type->data.klass? type->data.klass: mono_defaults.byte_class;
6495 	case MONO_TYPE_I2:
6496 		return type->data.klass? type->data.klass: mono_defaults.int16_class;
6497 	case MONO_TYPE_U2:
6498 		return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6499 	case MONO_TYPE_I4:
6500 		return type->data.klass? type->data.klass: mono_defaults.int32_class;
6501 	case MONO_TYPE_U4:
6502 		return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6503 	case MONO_TYPE_I:
6504 		return type->data.klass? type->data.klass: mono_defaults.int_class;
6505 	case MONO_TYPE_U:
6506 		return type->data.klass? type->data.klass: mono_defaults.uint_class;
6507 	case MONO_TYPE_I8:
6508 		return type->data.klass? type->data.klass: mono_defaults.int64_class;
6509 	case MONO_TYPE_U8:
6510 		return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6511 	case MONO_TYPE_R4:
6512 		return type->data.klass? type->data.klass: mono_defaults.single_class;
6513 	case MONO_TYPE_R8:
6514 		return type->data.klass? type->data.klass: mono_defaults.double_class;
6515 	case MONO_TYPE_STRING:
6516 		return type->data.klass? type->data.klass: mono_defaults.string_class;
6517 	case MONO_TYPE_TYPEDBYREF:
6518 		return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6519 	case MONO_TYPE_ARRAY:
6520 		return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6521 	case MONO_TYPE_PTR:
6522 		return mono_ptr_class_get (type->data.type);
6523 	case MONO_TYPE_FNPTR:
6524 		return mono_fnptr_class_get (type->data.method);
6525 	case MONO_TYPE_SZARRAY:
6526 		return mono_array_class_get (type->data.klass, 1);
6527 	case MONO_TYPE_CLASS:
6528 	case MONO_TYPE_VALUETYPE:
6529 		return type->data.klass;
6530 	case MONO_TYPE_GENERICINST:
6531 		return mono_generic_class_get_class (type->data.generic_class);
6532 	case MONO_TYPE_MVAR:
6533 	case MONO_TYPE_VAR:
6534 		return mono_class_from_generic_parameter_internal (type->data.generic_param);
6535 	default:
6536 		g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6537 		g_assert_not_reached ();
6538 	}
6539 
6540 	// Yes, this returns NULL, even if it is documented as not doing so, but there
6541 	// is no way for the code to make it this far, due to the assert above.
6542 	return NULL;
6543 }
6544 
6545 /**
6546  * mono_type_retrieve_from_typespec
6547  * \param image context where the image is created
6548  * \param type_spec  typespec token
6549  * \param context the generic context used to evaluate generic instantiations in
6550  */
6551 static MonoType *
mono_type_retrieve_from_typespec(MonoImage * image,guint32 type_spec,MonoGenericContext * context,gboolean * did_inflate,MonoError * error)6552 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6553 {
6554 	MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6555 
6556 	*did_inflate = FALSE;
6557 
6558 	if (!t)
6559 		return NULL;
6560 
6561 	if (context && (context->class_inst || context->method_inst)) {
6562 		MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6563 
6564 		if (!mono_error_ok (error)) {
6565 			return NULL;
6566 		}
6567 
6568 		if (inflated) {
6569 			t = inflated;
6570 			*did_inflate = TRUE;
6571 		}
6572 	}
6573 	return t;
6574 }
6575 
6576 /**
6577  * mono_class_create_from_typespec
6578  * \param image context where the image is created
6579  * \param type_spec typespec token
6580  * \param context the generic context used to evaluate generic instantiations in
6581  */
6582 static MonoClass *
mono_class_create_from_typespec(MonoImage * image,guint32 type_spec,MonoGenericContext * context,MonoError * error)6583 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6584 {
6585 	MonoClass *ret;
6586 	gboolean inflated = FALSE;
6587 	MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6588 	return_val_if_nok (error, NULL);
6589 	ret = mono_class_from_mono_type (t);
6590 	if (inflated)
6591 		mono_metadata_free_type (t);
6592 	return ret;
6593 }
6594 
6595 /**
6596  * mono_bounded_array_class_get:
6597  * \param element_class element class
6598  * \param rank the dimension of the array class
6599  * \param bounded whenever the array has non-zero bounds
6600  * \returns A class object describing the array with element type \p element_type and
6601  * dimension \p rank.
6602  */
6603 MonoClass *
mono_bounded_array_class_get(MonoClass * eclass,guint32 rank,gboolean bounded)6604 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6605 {
6606 	MonoImage *image;
6607 	MonoClass *klass, *cached, *k;
6608 	MonoClass *parent = NULL;
6609 	GSList *list, *rootlist = NULL;
6610 	int nsize;
6611 	char *name;
6612 	MonoImageSet* image_set;
6613 
6614 	g_assert (rank <= 255);
6615 
6616 	if (rank > 1)
6617 		/* bounded only matters for one-dimensional arrays */
6618 		bounded = FALSE;
6619 
6620 	image = eclass->image;
6621 	image_set = class_kind_may_contain_generic_instances (eclass->class_kind) ? mono_metadata_get_image_set_for_class (eclass) : NULL;
6622 
6623 	/* Check cache */
6624 	cached = NULL;
6625 	if (rank == 1 && !bounded) {
6626 		if (image_set) {
6627 			mono_image_set_lock (image_set);
6628 			cached = (MonoClass *)g_hash_table_lookup (image_set->szarray_cache, eclass);
6629 			mono_image_set_unlock (image_set);
6630 		} else {
6631 			/*
6632 			 * This case is very frequent not just during compilation because of calls
6633 			 * from mono_class_from_mono_type (), mono_array_new (),
6634 			 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6635 			 */
6636 			mono_os_mutex_lock (&image->szarray_cache_lock);
6637 			if (!image->szarray_cache)
6638 				image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6639 			cached = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6640 			mono_os_mutex_unlock (&image->szarray_cache_lock);
6641 		}
6642 	} else {
6643 		if (image_set) {
6644 			mono_image_set_lock (image_set);
6645 			rootlist = (GSList *)g_hash_table_lookup (image_set->array_cache, eclass);
6646 			for (list = rootlist; list; list = list->next) {
6647 				k = (MonoClass *)list->data;
6648 				if ((k->rank == rank) && (k->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6649 					cached = k;
6650 					break;
6651 				}
6652 			}
6653 			mono_image_set_unlock (image_set);
6654 		} else {
6655 			mono_loader_lock ();
6656 			if (!image->array_cache)
6657 				image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6658 			rootlist = (GSList *)g_hash_table_lookup (image->array_cache, eclass);
6659 			for (list = rootlist; list; list = list->next) {
6660 				k = (MonoClass *)list->data;
6661 				if ((k->rank == rank) && (k->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6662 					cached = k;
6663 					break;
6664 				}
6665 			}
6666 			mono_loader_unlock ();
6667 		}
6668 	}
6669 	if (cached)
6670 		return cached;
6671 
6672 	parent = mono_defaults.array_class;
6673 	if (!parent->inited)
6674 		mono_class_init (parent);
6675 
6676 	klass = image_set ? (MonoClass *)mono_image_set_alloc0 (image_set, sizeof (MonoClassArray)) : (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassArray));
6677 
6678 	klass->image = image;
6679 	klass->name_space = eclass->name_space;
6680 	klass->class_kind = MONO_CLASS_ARRAY;
6681 
6682 	nsize = strlen (eclass->name);
6683 	name = (char *)g_malloc (nsize + 2 + rank + 1);
6684 	memcpy (name, eclass->name, nsize);
6685 	name [nsize] = '[';
6686 	if (rank > 1)
6687 		memset (name + nsize + 1, ',', rank - 1);
6688 	if (bounded)
6689 		name [nsize + rank] = '*';
6690 	name [nsize + rank + bounded] = ']';
6691 	name [nsize + rank + bounded + 1] = 0;
6692 	klass->name = image_set ? mono_image_set_strdup (image_set, name) : mono_image_strdup (image, name);
6693 	g_free (name);
6694 
6695 	klass->type_token = 0;
6696 	klass->parent = parent;
6697 	klass->instance_size = mono_class_instance_size (klass->parent);
6698 
6699 	if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF) {
6700 		/*Arrays of those two types are invalid.*/
6701 		MonoError prepared_error;
6702 		error_init (&prepared_error);
6703 		mono_error_set_invalid_program (&prepared_error, "Arrays of System.TypedReference types are invalid.");
6704 		mono_class_set_failure (klass, mono_error_box (&prepared_error, klass->image));
6705 		mono_error_cleanup (&prepared_error);
6706 	} else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6707 		guint32 ref_info_handle = mono_class_get_ref_info_handle (eclass);
6708 		if (!ref_info_handle || eclass->wastypebuilder) {
6709 			g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6710 			g_assert (ref_info_handle && !eclass->wastypebuilder);
6711 		}
6712 		/* element_size -1 is ok as this is not an instantitable type*/
6713 		klass->sizes.element_size = -1;
6714 	} else
6715 		klass->sizes.element_size = -1;
6716 
6717 	mono_class_setup_supertypes (klass);
6718 
6719 	if (mono_class_is_ginst (eclass))
6720 		mono_class_init (eclass);
6721 	if (!eclass->size_inited)
6722 		mono_class_setup_fields (eclass);
6723 	mono_class_set_type_load_failure_causedby_class (klass, eclass, "Could not load array element type");
6724 	/*FIXME we fail the array type, but we have to let other fields be set.*/
6725 
6726 	klass->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6727 
6728 	klass->rank = rank;
6729 
6730 	if (eclass->enumtype)
6731 		klass->cast_class = eclass->element_class;
6732 	else
6733 		klass->cast_class = eclass;
6734 
6735 	switch (klass->cast_class->byval_arg.type) {
6736 	case MONO_TYPE_I1:
6737 		klass->cast_class = mono_defaults.byte_class;
6738 		break;
6739 	case MONO_TYPE_U2:
6740 		klass->cast_class = mono_defaults.int16_class;
6741 		break;
6742 	case MONO_TYPE_U4:
6743 #if SIZEOF_VOID_P == 4
6744 	case MONO_TYPE_I:
6745 	case MONO_TYPE_U:
6746 #endif
6747 		klass->cast_class = mono_defaults.int32_class;
6748 		break;
6749 	case MONO_TYPE_U8:
6750 #if SIZEOF_VOID_P == 8
6751 	case MONO_TYPE_I:
6752 	case MONO_TYPE_U:
6753 #endif
6754 		klass->cast_class = mono_defaults.int64_class;
6755 		break;
6756 	default:
6757 		break;
6758 	}
6759 
6760 	klass->element_class = eclass;
6761 
6762 	if ((rank > 1) || bounded) {
6763 		MonoArrayType *at = image_set ? (MonoArrayType *)mono_image_set_alloc0 (image_set, sizeof (MonoArrayType)) : (MonoArrayType *)mono_image_alloc0 (image, sizeof (MonoArrayType));
6764 		klass->byval_arg.type = MONO_TYPE_ARRAY;
6765 		klass->byval_arg.data.array = at;
6766 		at->eklass = eclass;
6767 		at->rank = rank;
6768 		/* FIXME: complete.... */
6769 	} else {
6770 		klass->byval_arg.type = MONO_TYPE_SZARRAY;
6771 		klass->byval_arg.data.klass = eclass;
6772 	}
6773 	klass->this_arg = klass->byval_arg;
6774 	klass->this_arg.byref = 1;
6775 
6776 	if (rank > 32) {
6777 		MonoError prepared_error;
6778 		error_init (&prepared_error);
6779 		name = mono_type_get_full_name (klass);
6780 		mono_error_set_type_load_class (&prepared_error, klass, "%s has too many dimensions.", name);
6781 		mono_class_set_failure (klass, mono_error_box (&prepared_error, klass->image));
6782 		mono_error_cleanup (&prepared_error);
6783 		g_free (name);
6784 	}
6785 
6786 	mono_loader_lock ();
6787 
6788 	/* Check cache again */
6789 	cached = NULL;
6790 	if (rank == 1 && !bounded) {
6791 		if (image_set) {
6792 			mono_image_set_lock (image_set);
6793 			cached = (MonoClass *)g_hash_table_lookup (image_set->szarray_cache, eclass);
6794 			mono_image_set_unlock (image_set);
6795 		} else {
6796 			mono_os_mutex_lock (&image->szarray_cache_lock);
6797 			cached = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6798 			mono_os_mutex_unlock (&image->szarray_cache_lock);
6799 		}
6800 	} else {
6801 		if (image_set) {
6802 			mono_image_set_lock (image_set);
6803 			rootlist = (GSList *)g_hash_table_lookup (image_set->array_cache, eclass);
6804 			for (list = rootlist; list; list = list->next) {
6805 				k = (MonoClass *)list->data;
6806 				if ((k->rank == rank) && (k->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6807 					cached = k;
6808 					break;
6809 				}
6810 			}
6811 			mono_image_set_unlock (image_set);
6812 		} else {
6813 			rootlist = (GSList *)g_hash_table_lookup (image->array_cache, eclass);
6814 			for (list = rootlist; list; list = list->next) {
6815 				k = (MonoClass *)list->data;
6816 				if ((k->rank == rank) && (k->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6817 					cached = k;
6818 					break;
6819 				}
6820 			}
6821 		}
6822 	}
6823 	if (cached) {
6824 		mono_loader_unlock ();
6825 		return cached;
6826 	}
6827 
6828 	MONO_PROFILER_RAISE (class_loading, (klass));
6829 
6830 	UnlockedAdd (&classes_size, sizeof (MonoClassArray));
6831 	++class_array_count;
6832 
6833 	if (rank == 1 && !bounded) {
6834 		if (image_set) {
6835 			mono_image_set_lock (image_set);
6836 			g_hash_table_insert (image_set->szarray_cache, eclass, klass);
6837 			mono_image_set_unlock (image_set);
6838 		} else {
6839 			mono_os_mutex_lock (&image->szarray_cache_lock);
6840 			g_hash_table_insert (image->szarray_cache, eclass, klass);
6841 			mono_os_mutex_unlock (&image->szarray_cache_lock);
6842 		}
6843 	} else {
6844 		if (image_set) {
6845 			mono_image_set_lock (image_set);
6846 			list = g_slist_append (rootlist, klass);
6847 			g_hash_table_insert (image_set->array_cache, eclass, list);
6848 			mono_image_set_unlock (image_set);
6849 		} else {
6850 			list = g_slist_append (rootlist, klass);
6851 			g_hash_table_insert (image->array_cache, eclass, list);
6852 		}
6853 	}
6854 
6855 	mono_loader_unlock ();
6856 
6857 	MONO_PROFILER_RAISE (class_loaded, (klass));
6858 
6859 	return klass;
6860 }
6861 
6862 /**
6863  * mono_array_class_get:
6864  * \param element_class element class
6865  * \param rank the dimension of the array class
6866  * \returns A class object describing the array with element type \p element_type and
6867  * dimension \p rank.
6868  */
6869 MonoClass *
mono_array_class_get(MonoClass * eclass,guint32 rank)6870 mono_array_class_get (MonoClass *eclass, guint32 rank)
6871 {
6872 	return mono_bounded_array_class_get (eclass, rank, FALSE);
6873 }
6874 
6875 /**
6876  * mono_class_instance_size:
6877  * \param klass a class
6878  *
6879  * Use to get the size of a class in bytes.
6880  *
6881  * \returns The size of an object instance
6882  */
6883 gint32
mono_class_instance_size(MonoClass * klass)6884 mono_class_instance_size (MonoClass *klass)
6885 {
6886 	if (!klass->size_inited)
6887 		mono_class_init (klass);
6888 
6889 	return klass->instance_size;
6890 }
6891 
6892 /**
6893  * mono_class_min_align:
6894  * \param klass a class
6895  *
6896  * Use to get the computed minimum alignment requirements for the specified class.
6897  *
6898  * Returns: minimum alignment requirements
6899  */
6900 gint32
mono_class_min_align(MonoClass * klass)6901 mono_class_min_align (MonoClass *klass)
6902 {
6903 	if (!klass->size_inited)
6904 		mono_class_init (klass);
6905 
6906 	return klass->min_align;
6907 }
6908 
6909 /**
6910  * mono_class_value_size:
6911  * \param klass a class
6912  *
6913  * This function is used for value types, and return the
6914  * space and the alignment to store that kind of value object.
6915  *
6916  * \returns the size of a value of kind \p klass
6917  */
6918 gint32
mono_class_value_size(MonoClass * klass,guint32 * align)6919 mono_class_value_size (MonoClass *klass, guint32 *align)
6920 {
6921 	gint32 size;
6922 
6923 	/* fixme: check disable, because we still have external revereces to
6924 	 * mscorlib and Dummy Objects
6925 	 */
6926 	/*g_assert (klass->valuetype);*/
6927 
6928 	size = mono_class_instance_size (klass) - sizeof (MonoObject);
6929 
6930 	if (align)
6931 		*align = klass->min_align;
6932 
6933 	return size;
6934 }
6935 
6936 /**
6937  * mono_class_data_size:
6938  * \param klass a class
6939  *
6940  * \returns The size of the static class data
6941  */
6942 gint32
mono_class_data_size(MonoClass * klass)6943 mono_class_data_size (MonoClass *klass)
6944 {
6945 	if (!klass->inited)
6946 		mono_class_init (klass);
6947 	/* This can happen with dynamically created types */
6948 	if (!klass->fields_inited)
6949 		mono_class_setup_fields (klass);
6950 
6951 	/* in arrays, sizes.class_size is unioned with element_size
6952 	 * and arrays have no static fields
6953 	 */
6954 	if (klass->rank)
6955 		return 0;
6956 	return klass->sizes.class_size;
6957 }
6958 
6959 /*
6960  * Auxiliary routine to mono_class_get_field
6961  *
6962  * Takes a field index instead of a field token.
6963  */
6964 static MonoClassField *
mono_class_get_field_idx(MonoClass * klass,int idx)6965 mono_class_get_field_idx (MonoClass *klass, int idx)
6966 {
6967 	mono_class_setup_fields (klass);
6968 	if (mono_class_has_failure (klass))
6969 		return NULL;
6970 
6971 	while (klass) {
6972 		int first_field_idx = mono_class_get_first_field_idx (klass);
6973 		int fcount = mono_class_get_field_count (klass);
6974 		if (klass->image->uncompressed_metadata) {
6975 			/*
6976 			 * first_field_idx points to the FieldPtr table, while idx points into the
6977 			 * Field table, so we have to do a search.
6978 			 */
6979 			/*FIXME this is broken for types with multiple fields with the same name.*/
6980 			const char *name = mono_metadata_string_heap (klass->image, mono_metadata_decode_row_col (&klass->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6981 			int i;
6982 
6983 			for (i = 0; i < fcount; ++i)
6984 				if (mono_field_get_name (&klass->fields [i]) == name)
6985 					return &klass->fields [i];
6986 			g_assert_not_reached ();
6987 		} else {
6988 			if (fcount) {
6989 				if ((idx >= first_field_idx) && (idx < first_field_idx + fcount)){
6990 					return &klass->fields [idx - first_field_idx];
6991 				}
6992 			}
6993 		}
6994 		klass = klass->parent;
6995 	}
6996 	return NULL;
6997 }
6998 
6999 /**
7000  * mono_class_get_field:
7001  * \param class the class to lookup the field.
7002  * \param field_token the field token
7003  *
7004  * \returns A \c MonoClassField representing the type and offset of
7005  * the field, or a NULL value if the field does not belong to this
7006  * class.
7007  */
7008 MonoClassField *
mono_class_get_field(MonoClass * klass,guint32 field_token)7009 mono_class_get_field (MonoClass *klass, guint32 field_token)
7010 {
7011 	int idx = mono_metadata_token_index (field_token);
7012 
7013 	g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
7014 
7015 	return mono_class_get_field_idx (klass, idx - 1);
7016 }
7017 
7018 /**
7019  * mono_class_get_field_from_name:
7020  * \param klass the class to lookup the field.
7021  * \param name the field name
7022  *
7023  * Search the class \p klass and its parents for a field with the name \p name.
7024  *
7025  * \returns The \c MonoClassField pointer of the named field or NULL
7026  */
7027 MonoClassField *
mono_class_get_field_from_name(MonoClass * klass,const char * name)7028 mono_class_get_field_from_name (MonoClass *klass, const char *name)
7029 {
7030 	return mono_class_get_field_from_name_full (klass, name, NULL);
7031 }
7032 
7033 /**
7034  * mono_class_get_field_from_name_full:
7035  * \param klass the class to lookup the field.
7036  * \param name the field name
7037  * \param type the type of the fields. This optional.
7038  *
7039  * Search the class \p klass and it's parents for a field with the name \p name and type \p type.
7040  *
7041  * If \p klass is an inflated generic type, the type comparison is done with the equivalent field
7042  * of its generic type definition.
7043  *
7044  * \returns The MonoClassField pointer of the named field or NULL
7045  */
7046 MonoClassField *
mono_class_get_field_from_name_full(MonoClass * klass,const char * name,MonoType * type)7047 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
7048 {
7049 	int i;
7050 
7051 	mono_class_setup_fields (klass);
7052 	if (mono_class_has_failure (klass))
7053 		return NULL;
7054 
7055 	while (klass) {
7056 		int fcount = mono_class_get_field_count (klass);
7057 		for (i = 0; i < fcount; ++i) {
7058 			MonoClassField *field = &klass->fields [i];
7059 
7060 			if (strcmp (name, mono_field_get_name (field)) != 0)
7061 				continue;
7062 
7063 			if (type) {
7064 				MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
7065 				if (!mono_metadata_type_equal_full (type, field_type, TRUE))
7066 					continue;
7067 			}
7068 			return field;
7069 		}
7070 		klass = klass->parent;
7071 	}
7072 	return NULL;
7073 }
7074 
7075 /**
7076  * mono_class_get_field_token:
7077  * \param field the field we need the token of
7078  *
7079  * Get the token of a field. Note that the tokesn is only valid for the image
7080  * the field was loaded from. Don't use this function for fields in dynamic types.
7081  *
7082  * \returns The token representing the field in the image it was loaded from.
7083  */
7084 guint32
mono_class_get_field_token(MonoClassField * field)7085 mono_class_get_field_token (MonoClassField *field)
7086 {
7087 	MonoClass *klass = field->parent;
7088 	int i;
7089 
7090 	mono_class_setup_fields (klass);
7091 
7092 	while (klass) {
7093 		if (!klass->fields)
7094 			return 0;
7095 		int first_field_idx = mono_class_get_first_field_idx (klass);
7096 		int fcount = mono_class_get_field_count (klass);
7097 		for (i = 0; i < fcount; ++i) {
7098 			if (&klass->fields [i] == field) {
7099 				int idx = first_field_idx + i + 1;
7100 
7101 				if (klass->image->uncompressed_metadata)
7102 					idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
7103 				return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
7104 			}
7105 		}
7106 		klass = klass->parent;
7107 	}
7108 
7109 	g_assert_not_reached ();
7110 	return 0;
7111 }
7112 
7113 static int
mono_field_get_index(MonoClassField * field)7114 mono_field_get_index (MonoClassField *field)
7115 {
7116 	int index = field - field->parent->fields;
7117 	g_assert (index >= 0 && index < mono_class_get_field_count (field->parent));
7118 
7119 	return index;
7120 }
7121 
7122 /*
7123  * mono_class_get_field_default_value:
7124  *
7125  * Return the default value of the field as a pointer into the metadata blob.
7126  */
7127 const char*
mono_class_get_field_default_value(MonoClassField * field,MonoTypeEnum * def_type)7128 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
7129 {
7130 	guint32 cindex;
7131 	guint32 constant_cols [MONO_CONSTANT_SIZE];
7132 	int field_index;
7133 	MonoClass *klass = field->parent;
7134 	MonoFieldDefaultValue *def_values;
7135 
7136 	g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
7137 
7138 	def_values = mono_class_get_field_def_values (klass);
7139 	if (!def_values) {
7140 		def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * mono_class_get_field_count (klass));
7141 
7142 		mono_class_set_field_def_values (klass, def_values);
7143 	}
7144 
7145 	field_index = mono_field_get_index (field);
7146 
7147 	if (!def_values [field_index].data) {
7148 		cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
7149 		if (!cindex)
7150 			return NULL;
7151 
7152 		g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
7153 
7154 		mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7155 		def_values [field_index].def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7156 		mono_memory_barrier ();
7157 		def_values [field_index].data = (const char *)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
7158 	}
7159 
7160 	*def_type = def_values [field_index].def_type;
7161 	return def_values [field_index].data;
7162 }
7163 
7164 static int
mono_property_get_index(MonoProperty * prop)7165 mono_property_get_index (MonoProperty *prop)
7166 {
7167 	MonoClassPropertyInfo *info = mono_class_get_property_info (prop->parent);
7168 	int index = prop - info->properties;
7169 
7170 	g_assert (index >= 0 && index < info->count);
7171 
7172 	return index;
7173 }
7174 
7175 /*
7176  * mono_class_get_property_default_value:
7177  *
7178  * Return the default value of the field as a pointer into the metadata blob.
7179  */
7180 const char*
mono_class_get_property_default_value(MonoProperty * property,MonoTypeEnum * def_type)7181 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
7182 {
7183 	guint32 cindex;
7184 	guint32 constant_cols [MONO_CONSTANT_SIZE];
7185 	MonoClass *klass = property->parent;
7186 
7187 	g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
7188 	/*
7189 	 * We don't cache here because it is not used by C# so it's quite rare, but
7190 	 * we still do the lookup in klass->ext because that is where the data
7191 	 * is stored for dynamic assemblies.
7192 	 */
7193 
7194 	if (image_is_dynamic (klass->image)) {
7195 		MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
7196 		int prop_index = mono_property_get_index (property);
7197 		if (info->def_values && info->def_values [prop_index].data) {
7198 			*def_type = info->def_values [prop_index].def_type;
7199 			return info->def_values [prop_index].data;
7200 		}
7201 		return NULL;
7202 	}
7203 	cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
7204 	if (!cindex)
7205 		return NULL;
7206 
7207 	mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7208 	*def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7209 	return (const char *)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7210 }
7211 
7212 /**
7213  * mono_class_get_event_token:
7214  */
7215 guint32
mono_class_get_event_token(MonoEvent * event)7216 mono_class_get_event_token (MonoEvent *event)
7217 {
7218 	MonoClass *klass = event->parent;
7219 	int i;
7220 
7221 	while (klass) {
7222 		MonoClassEventInfo *info = mono_class_get_event_info (klass);
7223 		if (info) {
7224 			for (i = 0; i < info->count; ++i) {
7225 				if (&info->events [i] == event)
7226 					return mono_metadata_make_token (MONO_TABLE_EVENT, info->first + i + 1);
7227 			}
7228 		}
7229 		klass = klass->parent;
7230 	}
7231 
7232 	g_assert_not_reached ();
7233 	return 0;
7234 }
7235 
7236 /**
7237  * mono_class_get_property_from_name:
7238  * \param klass a class
7239  * \param name name of the property to lookup in the specified class
7240  *
7241  * Use this method to lookup a property in a class
7242  * \returns the \c MonoProperty with the given name, or NULL if the property
7243  * does not exist on the \p klass.
7244  */
7245 MonoProperty*
mono_class_get_property_from_name(MonoClass * klass,const char * name)7246 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7247 {
7248 	while (klass) {
7249 		MonoProperty* p;
7250 		gpointer iter = NULL;
7251 		while ((p = mono_class_get_properties (klass, &iter))) {
7252 			if (! strcmp (name, p->name))
7253 				return p;
7254 		}
7255 		klass = klass->parent;
7256 	}
7257 	return NULL;
7258 }
7259 
7260 /**
7261  * mono_class_get_property_token:
7262  * \param prop MonoProperty to query
7263  *
7264  * \returns The ECMA token for the specified property.
7265  */
7266 guint32
mono_class_get_property_token(MonoProperty * prop)7267 mono_class_get_property_token (MonoProperty *prop)
7268 {
7269 	MonoClass *klass = prop->parent;
7270 	while (klass) {
7271 		MonoProperty* p;
7272 		int i = 0;
7273 		gpointer iter = NULL;
7274 		MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
7275 		while ((p = mono_class_get_properties (klass, &iter))) {
7276 			if (&info->properties [i] == prop)
7277 				return mono_metadata_make_token (MONO_TABLE_PROPERTY, info->first + i + 1);
7278 
7279 			i ++;
7280 		}
7281 		klass = klass->parent;
7282 	}
7283 
7284 	g_assert_not_reached ();
7285 	return 0;
7286 }
7287 
7288 /**
7289  * mono_class_name_from_token:
7290  */
7291 char *
mono_class_name_from_token(MonoImage * image,guint32 type_token)7292 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7293 {
7294 	const char *name, *nspace;
7295 	if (image_is_dynamic (image))
7296 		return g_strdup_printf ("DynamicType 0x%08x", type_token);
7297 
7298 	switch (type_token & 0xff000000){
7299 	case MONO_TOKEN_TYPE_DEF: {
7300 		guint32 cols [MONO_TYPEDEF_SIZE];
7301 		MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7302 		guint tidx = mono_metadata_token_index (type_token);
7303 
7304 		if (tidx > tt->rows)
7305 			return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7306 
7307 		mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7308 		name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7309 		nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7310 		if (strlen (nspace) == 0)
7311 			return g_strdup_printf ("%s", name);
7312 		else
7313 			return g_strdup_printf ("%s.%s", nspace, name);
7314 	}
7315 
7316 	case MONO_TOKEN_TYPE_REF: {
7317 		MonoError error;
7318 		guint32 cols [MONO_TYPEREF_SIZE];
7319 		MonoTableInfo  *t = &image->tables [MONO_TABLE_TYPEREF];
7320 		guint tidx = mono_metadata_token_index (type_token);
7321 
7322 		if (tidx > t->rows)
7323 			return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7324 
7325 		if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7326 			char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7327 			mono_error_cleanup (&error);
7328 			return msg;
7329 		}
7330 
7331 		mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7332 		name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7333 		nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7334 		if (strlen (nspace) == 0)
7335 			return g_strdup_printf ("%s", name);
7336 		else
7337 			return g_strdup_printf ("%s.%s", nspace, name);
7338 	}
7339 
7340 	case MONO_TOKEN_TYPE_SPEC:
7341 		return g_strdup_printf ("Typespec 0x%08x", type_token);
7342 	default:
7343 		return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7344 	}
7345 }
7346 
7347 static char *
mono_assembly_name_from_token(MonoImage * image,guint32 type_token)7348 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7349 {
7350 	if (image_is_dynamic (image))
7351 		return g_strdup_printf ("DynamicAssembly %s", image->name);
7352 
7353 	switch (type_token & 0xff000000){
7354 	case MONO_TOKEN_TYPE_DEF:
7355 		if (image->assembly)
7356 			return mono_stringify_assembly_name (&image->assembly->aname);
7357 		else if (image->assembly_name)
7358 			return g_strdup (image->assembly_name);
7359 		return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7360 	case MONO_TOKEN_TYPE_REF: {
7361 		MonoError error;
7362 		MonoAssemblyName aname;
7363 		guint32 cols [MONO_TYPEREF_SIZE];
7364 		MonoTableInfo  *t = &image->tables [MONO_TABLE_TYPEREF];
7365 		guint32 idx = mono_metadata_token_index (type_token);
7366 
7367 		if (idx > t->rows)
7368 			return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7369 
7370 		if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7371 			char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7372 			mono_error_cleanup (&error);
7373 			return msg;
7374 		}
7375 		mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7376 
7377 		idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7378 		switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7379 		case MONO_RESOLUTION_SCOPE_MODULE:
7380 			/* FIXME: */
7381 			return g_strdup ("");
7382 		case MONO_RESOLUTION_SCOPE_MODULEREF:
7383 			/* FIXME: */
7384 			return g_strdup ("");
7385 		case MONO_RESOLUTION_SCOPE_TYPEREF:
7386 			/* FIXME: */
7387 			return g_strdup ("");
7388 		case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7389 			mono_assembly_get_assemblyref (image, idx - 1, &aname);
7390 			return mono_stringify_assembly_name (&aname);
7391 		default:
7392 			g_assert_not_reached ();
7393 		}
7394 		break;
7395 	}
7396 	case MONO_TOKEN_TYPE_SPEC:
7397 		/* FIXME: */
7398 		return g_strdup ("");
7399 	default:
7400 		g_assert_not_reached ();
7401 	}
7402 
7403 	return NULL;
7404 }
7405 
7406 /**
7407  * mono_class_get_full:
7408  * \param image the image where the class resides
7409  * \param type_token the token for the class
7410  * \param context the generic context used to evaluate generic instantiations in
7411  * \deprecated Functions that expose \c MonoGenericContext are going away in mono 4.0
7412  * \returns The \c MonoClass that represents \p type_token in \p image
7413  */
7414 MonoClass *
mono_class_get_full(MonoImage * image,guint32 type_token,MonoGenericContext * context)7415 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7416 {
7417 	MonoError error;
7418 	MonoClass *klass;
7419 	klass = mono_class_get_checked (image, type_token, &error);
7420 
7421 	if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7422 		klass = mono_class_inflate_generic_class_checked (klass, context, &error);
7423 
7424 	g_assert (mono_error_ok (&error)); /* FIXME deprecate this function and forbit the runtime from using it. */
7425 	return klass;
7426 }
7427 
7428 
7429 MonoClass *
mono_class_get_and_inflate_typespec_checked(MonoImage * image,guint32 type_token,MonoGenericContext * context,MonoError * error)7430 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7431 {
7432 	MonoClass *klass;
7433 
7434 	error_init (error);
7435 	klass = mono_class_get_checked (image, type_token, error);
7436 
7437 	if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7438 		klass = mono_class_inflate_generic_class_checked (klass, context, error);
7439 
7440 	return klass;
7441 }
7442 /**
7443  * mono_class_get_checked:
7444  * \param image the image where the class resides
7445  * \param type_token the token for the class
7446  * \param error error object to return any error
7447  *
7448  * \returns The MonoClass that represents \p type_token in \p image, or NULL on error.
7449  */
7450 MonoClass *
mono_class_get_checked(MonoImage * image,guint32 type_token,MonoError * error)7451 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7452 {
7453 	MonoClass *klass = NULL;
7454 
7455 	error_init (error);
7456 
7457 	if (image_is_dynamic (image)) {
7458 		int table = mono_metadata_token_table (type_token);
7459 
7460 		if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7461 			mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7462 			return NULL;
7463 		}
7464 		klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, NULL, error);
7465 		goto done;
7466 	}
7467 
7468 	switch (type_token & 0xff000000){
7469 	case MONO_TOKEN_TYPE_DEF:
7470 		klass = mono_class_create_from_typedef (image, type_token, error);
7471 		break;
7472 	case MONO_TOKEN_TYPE_REF:
7473 		klass = mono_class_from_typeref_checked (image, type_token, error);
7474 		break;
7475 	case MONO_TOKEN_TYPE_SPEC:
7476 		klass = mono_class_create_from_typespec (image, type_token, NULL, error);
7477 		break;
7478 	default:
7479 		mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7480 	}
7481 
7482 done:
7483 	/* Generic case, should be avoided for when a better error is possible. */
7484 	if (!klass && mono_error_ok (error)) {
7485 		char *name = mono_class_name_from_token (image, type_token);
7486 		char *assembly = mono_assembly_name_from_token (image, type_token);
7487 		mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x (class/assembly %s, %s)", type_token, name, assembly);
7488 	}
7489 
7490 	return klass;
7491 }
7492 
7493 
7494 /**
7495  * mono_type_get_checked:
7496  * \param image the image where the type resides
7497  * \param type_token the token for the type
7498  * \param context the generic context used to evaluate generic instantiations in
7499  * \param error Error handling context
7500  *
7501  * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7502  *
7503  * \returns The MonoType that represents \p type_token in \p image
7504  */
7505 MonoType *
mono_type_get_checked(MonoImage * image,guint32 type_token,MonoGenericContext * context,MonoError * error)7506 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7507 {
7508 	MonoType *type = NULL;
7509 	gboolean inflated = FALSE;
7510 
7511 	error_init (error);
7512 
7513 	//FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7514 	if (image_is_dynamic (image)) {
7515 		MonoClass *klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, context, error);
7516 		return_val_if_nok (error, NULL);
7517 		return mono_class_get_type (klass);
7518 	}
7519 
7520 	if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7521 		MonoClass *klass = mono_class_get_checked (image, type_token, error);
7522 
7523 		if (!klass) {
7524 			return NULL;
7525 		}
7526 
7527 		g_assert (klass);
7528 		return mono_class_get_type (klass);
7529 	}
7530 
7531 	type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7532 
7533 	if (!type) {
7534 		return NULL;
7535 	}
7536 
7537 	if (inflated) {
7538 		MonoType *tmp = type;
7539 		type = mono_class_get_type (mono_class_from_mono_type (type));
7540 		/* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7541 		 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7542 		 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7543 		 *
7544 		 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7545 		 * */
7546 		if (type->type != tmp->type)
7547 			type = tmp;
7548 		else
7549 			mono_metadata_free_type (tmp);
7550 	}
7551 	return type;
7552 }
7553 
7554 /**
7555  * mono_class_get:
7556  * \param image image where the class token will be looked up.
7557  * \param type_token a type token from the image
7558  * \returns the \c MonoClass with the given \p type_token on the \p image
7559  */
7560 MonoClass *
mono_class_get(MonoImage * image,guint32 type_token)7561 mono_class_get (MonoImage *image, guint32 type_token)
7562 {
7563 	return mono_class_get_full (image, type_token, NULL);
7564 }
7565 
7566 /**
7567  * mono_image_init_name_cache:
7568  *
7569  *  Initializes the class name cache stored in image->name_cache.
7570  *
7571  * LOCKING: Acquires the corresponding image lock.
7572  */
7573 void
mono_image_init_name_cache(MonoImage * image)7574 mono_image_init_name_cache (MonoImage *image)
7575 {
7576 	MonoTableInfo  *t = &image->tables [MONO_TABLE_TYPEDEF];
7577 	guint32 cols [MONO_TYPEDEF_SIZE];
7578 	const char *name;
7579 	const char *nspace;
7580 	guint32 i, visib, nspace_index;
7581 	GHashTable *name_cache2, *nspace_table, *the_name_cache;
7582 
7583 	if (image->name_cache)
7584 		return;
7585 
7586 	the_name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7587 
7588 	if (image_is_dynamic (image)) {
7589 		mono_image_lock (image);
7590 		if (image->name_cache) {
7591 			/* Somebody initialized it before us */
7592 			g_hash_table_destroy (the_name_cache);
7593 		} else {
7594 			mono_atomic_store_release (&image->name_cache, the_name_cache);
7595 		}
7596 		mono_image_unlock (image);
7597 		return;
7598 	}
7599 
7600 	/* Temporary hash table to avoid lookups in the nspace_table */
7601 	name_cache2 = g_hash_table_new (NULL, NULL);
7602 
7603 	for (i = 1; i <= t->rows; ++i) {
7604 		mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7605 		visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7606 		/*
7607 		 * Nested types are accessed from the nesting name.  We use the fact that nested types use different visibility flags
7608 		 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7609 		 */
7610 		if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7611 			continue;
7612 		name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7613 		nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7614 
7615 		nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7616 		nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7617 		if (!nspace_table) {
7618 			nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7619 			g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7620 			g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7621 								 nspace_table);
7622 		}
7623 		g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7624 	}
7625 
7626 	/* Load type names from EXPORTEDTYPES table */
7627 	{
7628 		MonoTableInfo  *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7629 		guint32 cols [MONO_EXP_TYPE_SIZE];
7630 		int i;
7631 
7632 		for (i = 0; i < t->rows; ++i) {
7633 			mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7634 
7635 			guint32 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7636 			if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_EXP_TYPE)
7637 				/* Nested type */
7638 				continue;
7639 
7640 			name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7641 			nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7642 
7643 			nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7644 			nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7645 			if (!nspace_table) {
7646 				nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7647 				g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7648 				g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7649 									 nspace_table);
7650 			}
7651 			g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7652 		}
7653 	}
7654 
7655 	g_hash_table_destroy (name_cache2);
7656 
7657 	mono_image_lock (image);
7658 	if (image->name_cache) {
7659 		/* Somebody initialized it before us */
7660 		g_hash_table_destroy (the_name_cache);
7661 	} else {
7662 		mono_atomic_store_release (&image->name_cache, the_name_cache);
7663 	}
7664 	mono_image_unlock (image);
7665 }
7666 
7667 /*FIXME Only dynamic assemblies should allow this operation.*/
7668 /**
7669  * mono_image_add_to_name_cache:
7670  */
7671 void
mono_image_add_to_name_cache(MonoImage * image,const char * nspace,const char * name,guint32 index)7672 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7673 							  const char *name, guint32 index)
7674 {
7675 	GHashTable *nspace_table;
7676 	GHashTable *name_cache;
7677 	guint32 old_index;
7678 
7679 	mono_image_init_name_cache (image);
7680 	mono_image_lock (image);
7681 
7682 	name_cache = image->name_cache;
7683 	if (!(nspace_table = (GHashTable *)g_hash_table_lookup (name_cache, nspace))) {
7684 		nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7685 		g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7686 	}
7687 
7688 	if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7689 		g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7690 
7691 	g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7692 
7693 	mono_image_unlock (image);
7694 }
7695 
7696 typedef struct {
7697 	gconstpointer key;
7698 	gpointer value;
7699 } FindUserData;
7700 
7701 static void
find_nocase(gpointer key,gpointer value,gpointer user_data)7702 find_nocase (gpointer key, gpointer value, gpointer user_data)
7703 {
7704 	char *name = (char*)key;
7705 	FindUserData *data = (FindUserData*)user_data;
7706 
7707 	if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7708 		data->value = value;
7709 }
7710 
7711 /**
7712  * mono_class_from_name_case:
7713  * \param image The MonoImage where the type is looked up in
7714  * \param name_space the type namespace
7715  * \param name the type short name.
7716  * \deprecated use the mono_class_from_name_case_checked variant instead.
7717  *
7718  * Obtains a \c MonoClass with a given namespace and a given name which
7719  * is located in the given \c MonoImage.   The namespace and name
7720  * lookups are case insensitive.
7721  */
7722 MonoClass *
mono_class_from_name_case(MonoImage * image,const char * name_space,const char * name)7723 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7724 {
7725 	MonoError error;
7726 	MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7727 	mono_error_cleanup (&error);
7728 
7729 	return res;
7730 }
7731 
7732 /**
7733  * mono_class_from_name_case_checked:
7734  * \param image The MonoImage where the type is looked up in
7735  * \param name_space the type namespace
7736  * \param name the type short name.
7737  * \param error if
7738  *
7739  * Obtains a MonoClass with a given namespace and a given name which
7740  * is located in the given MonoImage.   The namespace and name
7741  * lookups are case insensitive.
7742  *
7743  * \returns The MonoClass if the given namespace and name were found, or NULL if it
7744  * was not found.   The \p error object will contain information about the problem
7745  * in that case.
7746  */
7747 MonoClass *
mono_class_from_name_case_checked(MonoImage * image,const char * name_space,const char * name,MonoError * error)7748 mono_class_from_name_case_checked (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7749 {
7750 	MonoTableInfo  *t = &image->tables [MONO_TABLE_TYPEDEF];
7751 	guint32 cols [MONO_TYPEDEF_SIZE];
7752 	const char *n;
7753 	const char *nspace;
7754 	guint32 i, visib;
7755 
7756 	error_init (error);
7757 
7758 	if (image_is_dynamic (image)) {
7759 		guint32 token = 0;
7760 		FindUserData user_data;
7761 
7762 		mono_image_init_name_cache (image);
7763 		mono_image_lock (image);
7764 
7765 		user_data.key = name_space;
7766 		user_data.value = NULL;
7767 		g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7768 
7769 		if (user_data.value) {
7770 			GHashTable *nspace_table = (GHashTable*)user_data.value;
7771 
7772 			user_data.key = name;
7773 			user_data.value = NULL;
7774 
7775 			g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7776 
7777 			if (user_data.value)
7778 				token = GPOINTER_TO_UINT (user_data.value);
7779 		}
7780 
7781 		mono_image_unlock (image);
7782 
7783 		if (token)
7784 			return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7785 		else
7786 			return NULL;
7787 
7788 	}
7789 
7790 	/* add a cache if needed */
7791 	for (i = 1; i <= t->rows; ++i) {
7792 		mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7793 		visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7794 		/*
7795 		 * Nested types are accessed from the nesting name.  We use the fact that nested types use different visibility flags
7796 		 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7797 		 */
7798 		if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7799 			continue;
7800 		n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7801 		nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7802 		if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7803 			return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7804 	}
7805 	return NULL;
7806 }
7807 
7808 static MonoClass*
return_nested_in(MonoClass * klass,char * nested)7809 return_nested_in (MonoClass *klass, char *nested)
7810 {
7811 	MonoClass *found;
7812 	char *s = strchr (nested, '/');
7813 	gpointer iter = NULL;
7814 
7815 	if (s) {
7816 		*s = 0;
7817 		s++;
7818 	}
7819 
7820 	while ((found = mono_class_get_nested_types (klass, &iter))) {
7821 		if (strcmp (found->name, nested) == 0) {
7822 			if (s)
7823 				return return_nested_in (found, s);
7824 			return found;
7825 		}
7826 	}
7827 	return NULL;
7828 }
7829 
7830 static MonoClass*
search_modules(MonoImage * image,const char * name_space,const char * name,MonoError * error)7831 search_modules (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7832 {
7833 	MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7834 	MonoImage *file_image;
7835 	MonoClass *klass;
7836 	int i;
7837 
7838 	error_init (error);
7839 
7840 	/*
7841 	 * The EXPORTEDTYPES table only contains public types, so have to search the
7842 	 * modules as well.
7843 	 * Note: image->modules contains the contents of the MODULEREF table, while
7844 	 * the real module list is in the FILE table.
7845 	 */
7846 	for (i = 0; i < file_table->rows; i++) {
7847 		guint32 cols [MONO_FILE_SIZE];
7848 		mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7849 		if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7850 			continue;
7851 
7852 		file_image = mono_image_load_file_for_image_checked (image, i + 1, error);
7853 		if (file_image) {
7854 			klass = mono_class_from_name_checked (file_image, name_space, name, error);
7855 			if (klass || !is_ok (error))
7856 				return klass;
7857 		}
7858 	}
7859 
7860 	return NULL;
7861 }
7862 
7863 static MonoClass *
mono_class_from_name_checked_aux(MonoImage * image,const char * name_space,const char * name,GHashTable * visited_images,MonoError * error)7864 mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, GHashTable* visited_images, MonoError *error)
7865 {
7866 	GHashTable *nspace_table;
7867 	MonoImage *loaded_image;
7868 	guint32 token = 0;
7869 	int i;
7870 	MonoClass *klass;
7871 	char *nested;
7872 	char buf [1024];
7873 
7874 	error_init (error);
7875 
7876 	// Checking visited images avoids stack overflows when cyclic references exist.
7877 	if (g_hash_table_lookup (visited_images, image))
7878 		return NULL;
7879 
7880 	g_hash_table_insert (visited_images, image, GUINT_TO_POINTER(1));
7881 
7882 	if ((nested = strchr (name, '/'))) {
7883 		int pos = nested - name;
7884 		int len = strlen (name);
7885 		if (len > 1023)
7886 			return NULL;
7887 		memcpy (buf, name, len + 1);
7888 		buf [pos] = 0;
7889 		nested = buf + pos + 1;
7890 		name = buf;
7891 	}
7892 
7893 	/* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7894 	if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7895 		gboolean res = get_class_from_name (image, name_space, name, &klass);
7896 		if (res) {
7897 			if (!klass) {
7898 				klass = search_modules (image, name_space, name, error);
7899 				if (!is_ok (error))
7900 					return NULL;
7901 			}
7902 			if (nested)
7903 				return klass ? return_nested_in (klass, nested) : NULL;
7904 			else
7905 				return klass;
7906 		}
7907 	}
7908 
7909 	mono_image_init_name_cache (image);
7910 	mono_image_lock (image);
7911 
7912 	nspace_table = (GHashTable *)g_hash_table_lookup (image->name_cache, name_space);
7913 
7914 	if (nspace_table)
7915 		token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7916 
7917 	mono_image_unlock (image);
7918 
7919 	if (!token && image_is_dynamic (image) && image->modules) {
7920 		/* Search modules as well */
7921 		for (i = 0; i < image->module_count; ++i) {
7922 			MonoImage *module = image->modules [i];
7923 
7924 			klass = mono_class_from_name_checked (module, name_space, name, error);
7925 			if (klass || !is_ok (error))
7926 				return klass;
7927 		}
7928 	}
7929 
7930 	if (!token) {
7931 		klass = search_modules (image, name_space, name, error);
7932 		if (klass || !is_ok (error))
7933 			return klass;
7934 		return NULL;
7935 	}
7936 
7937 	if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7938 		MonoTableInfo  *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7939 		guint32 cols [MONO_EXP_TYPE_SIZE];
7940 		guint32 idx, impl;
7941 
7942 		idx = mono_metadata_token_index (token);
7943 
7944 		mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7945 
7946 		impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7947 		if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7948 			loaded_image = mono_assembly_load_module_checked (image->assembly, impl >> MONO_IMPLEMENTATION_BITS, error);
7949 			if (!loaded_image)
7950 				return NULL;
7951 			klass = mono_class_from_name_checked_aux (loaded_image, name_space, name, visited_images, error);
7952 			if (nested)
7953 				return klass ? return_nested_in (klass, nested) : NULL;
7954 			return klass;
7955 		} else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7956 			guint32 assembly_idx;
7957 
7958 			assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7959 
7960 			mono_assembly_load_reference (image, assembly_idx - 1);
7961 			g_assert (image->references [assembly_idx - 1]);
7962 			if (image->references [assembly_idx - 1] == (gpointer)-1)
7963 				return NULL;
7964 			klass = mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, visited_images, error);
7965 			if (nested)
7966 				return klass ? return_nested_in (klass, nested) : NULL;
7967 			return klass;
7968 		} else {
7969 			g_assert_not_reached ();
7970 		}
7971 	}
7972 
7973 	token = MONO_TOKEN_TYPE_DEF | token;
7974 
7975 	klass = mono_class_get_checked (image, token, error);
7976 	if (nested)
7977 		return return_nested_in (klass, nested);
7978 	return klass;
7979 }
7980 
7981 /**
7982  * mono_class_from_name_checked:
7983  * \param image The MonoImage where the type is looked up in
7984  * \param name_space the type namespace
7985  * \param name the type short name.
7986  *
7987  * Obtains a MonoClass with a given namespace and a given name which
7988  * is located in the given MonoImage.
7989  *
7990  * Works like mono_class_from_name, but error handling is tricky. It can return NULL and have no error
7991  * set if the class was not found or it will return NULL and set the error if there was a loading error.
7992  */
7993 MonoClass *
mono_class_from_name_checked(MonoImage * image,const char * name_space,const char * name,MonoError * error)7994 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7995 {
7996 	MonoClass *klass;
7997 	GHashTable *visited_images;
7998 
7999 	visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
8000 
8001 	klass = mono_class_from_name_checked_aux (image, name_space, name, visited_images, error);
8002 
8003 	g_hash_table_destroy (visited_images);
8004 
8005 	return klass;
8006 }
8007 
8008 /**
8009  * mono_class_from_name:
8010  * \param image The \c MonoImage where the type is looked up in
8011  * \param name_space the type namespace
8012  * \param name the type short name.
8013  *
8014  * Obtains a \c MonoClass with a given namespace and a given name which
8015  * is located in the given \c MonoImage.
8016  *
8017  * To reference nested classes, use the "/" character as a separator.
8018  * For example use \c "Foo/Bar" to reference the class \c Bar that is nested
8019  * inside \c Foo, like this: "class Foo { class Bar {} }".
8020  */
8021 MonoClass *
mono_class_from_name(MonoImage * image,const char * name_space,const char * name)8022 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
8023 {
8024 	MonoError error;
8025 	MonoClass *klass;
8026 
8027 	klass = mono_class_from_name_checked (image, name_space, name, &error);
8028 	mono_error_cleanup (&error); /* FIXME Don't swallow the error */
8029 
8030 	return klass;
8031 }
8032 
8033 /**
8034  * mono_class_load_from_name:
8035  * \param image The MonoImage where the type is looked up in
8036  * \param name_space the type namespace
8037  * \param name the type short name.
8038  *
8039  * This function works exactly like mono_class_from_name but it will abort if the class is not found.
8040  * This function should be used by the runtime for critical types to which there's no way to recover but crash
8041  * If they are missing. Thing of System.Object or System.String.
8042  */
8043 MonoClass *
mono_class_load_from_name(MonoImage * image,const char * name_space,const char * name)8044 mono_class_load_from_name (MonoImage *image, const char* name_space, const char *name)
8045 {
8046 	MonoError error;
8047 	MonoClass *klass;
8048 
8049 	klass = mono_class_from_name_checked (image, name_space, name, &error);
8050 	if (!klass)
8051 		g_error ("Runtime critical type %s.%s not found", name_space, name);
8052 	if (!mono_error_ok (&error))
8053 		g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8054 	return klass;
8055 }
8056 
8057 /**
8058  * mono_class_try_load_from_name:
8059  * \param image The MonoImage where the type is looked up in
8060  * \param name_space the type namespace
8061  * \param name the type short name.
8062  *
8063  * This function tries to load a type, returning the class was found or NULL otherwise.
8064  * This function should be used by the runtime when probing for optional types, those that could have being linked out.
8065  *
8066  * Big design consideration. This function aborts if there was an error loading the type. This prevents us from missing
8067  * a type that we would otherwise assume to be available but was not due some error.
8068  *
8069  */
8070 MonoClass*
mono_class_try_load_from_name(MonoImage * image,const char * name_space,const char * name)8071 mono_class_try_load_from_name (MonoImage *image, const char* name_space, const char *name)
8072 {
8073 	MonoError error;
8074 	MonoClass *klass;
8075 
8076 	klass = mono_class_from_name_checked (image, name_space, name, &error);
8077 	if (!mono_error_ok (&error))
8078 		g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8079 	return klass;
8080 }
8081 
8082 
8083 /**
8084  * mono_class_is_subclass_of:
8085  * \param klass class to probe if it is a subclass of another one
8086  * \param klassc the class we suspect is the base class
8087  * \param check_interfaces whether we should perform interface checks
8088  *
8089  * This method determines whether \p klass is a subclass of \p klassc.
8090  *
8091  * If the \p check_interfaces flag is set, then if \p klassc is an interface
8092  * this method return TRUE if the \p klass implements the interface or
8093  * if \p klass is an interface, if one of its base classes is \p klass.
8094  *
8095  * If \p check_interfaces is false, then if \p klass is not an interface,
8096  * it returns TRUE if the \p klass is a subclass of \p klassc.
8097  *
8098  * if \p klass is an interface and \p klassc is \c System.Object, then this function
8099  * returns TRUE.
8100  *
8101  */
8102 gboolean
mono_class_is_subclass_of(MonoClass * klass,MonoClass * klassc,gboolean check_interfaces)8103 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
8104 			   gboolean check_interfaces)
8105 {
8106 	/* FIXME test for interfaces with variant generic arguments */
8107 	mono_class_init (klass);
8108 	mono_class_init (klassc);
8109 
8110 	if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
8111 		if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
8112 			return TRUE;
8113 	} else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
8114 		int i;
8115 
8116 		for (i = 0; i < klass->interface_count; i ++) {
8117 			MonoClass *ic =  klass->interfaces [i];
8118 			if (ic == klassc)
8119 				return TRUE;
8120 		}
8121 	} else {
8122 		if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
8123 			return TRUE;
8124 	}
8125 
8126 	/*
8127 	 * MS.NET thinks interfaces are a subclass of Object, so we think it as
8128 	 * well.
8129 	 */
8130 	if (klassc == mono_defaults.object_class)
8131 		return TRUE;
8132 
8133 	return FALSE;
8134 }
8135 
8136 static gboolean
mono_type_is_generic_argument(MonoType * type)8137 mono_type_is_generic_argument (MonoType *type)
8138 {
8139 	return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
8140 }
8141 
8142 gboolean
mono_class_has_variant_generic_params(MonoClass * klass)8143 mono_class_has_variant_generic_params (MonoClass *klass)
8144 {
8145 	int i;
8146 	MonoGenericContainer *container;
8147 
8148 	if (!mono_class_is_ginst (klass))
8149 		return FALSE;
8150 
8151 	container = mono_class_get_generic_container (mono_class_get_generic_class (klass)->container_class);
8152 
8153 	for (i = 0; i < container->type_argc; ++i)
8154 		if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
8155 			return TRUE;
8156 
8157 	return FALSE;
8158 }
8159 
8160 static gboolean
mono_gparam_is_reference_conversible(MonoClass * target,MonoClass * candidate,gboolean check_for_reference_conv)8161 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
8162 {
8163 	if (target == candidate)
8164 		return TRUE;
8165 
8166 	if (check_for_reference_conv &&
8167 		mono_type_is_generic_argument (&target->byval_arg) &&
8168 		mono_type_is_generic_argument (&candidate->byval_arg)) {
8169 		MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
8170 		MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
8171 
8172 		if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
8173 			return FALSE;
8174 	}
8175 	if (!mono_class_is_assignable_from (target, candidate))
8176 		return FALSE;
8177 	return TRUE;
8178 }
8179 
8180 /**
8181  * @container the generic container from the GTD
8182  * @klass: the class to be assigned to
8183  * @oklass: the source class
8184  *
8185  * Both @klass and @oklass must be instances of the same generic interface.
8186  *
8187  * Returns: TRUE if @klass can be assigned to a @klass variable
8188  */
8189 gboolean
mono_class_is_variant_compatible(MonoClass * klass,MonoClass * oklass,gboolean check_for_reference_conv)8190 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
8191 {
8192 	int j;
8193 	MonoType **klass_argv, **oklass_argv;
8194 	MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8195 	MonoGenericContainer *container = mono_class_get_generic_container (klass_gtd);
8196 
8197 	if (klass == oklass)
8198 		return TRUE;
8199 
8200 	/*Viable candidates are instances of the same generic interface*/
8201 	if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8202 		return FALSE;
8203 
8204 	klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
8205 	oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
8206 
8207 	for (j = 0; j < container->type_argc; ++j) {
8208 		MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8209 		MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8210 
8211 		if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
8212 			return FALSE;
8213 
8214 		/*
8215 		 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8216 		 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8217 		 */
8218 		if (param1_class != param2_class) {
8219 			if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8220 				if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
8221 					return FALSE;
8222 			} else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8223 				if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
8224 					return FALSE;
8225 			} else
8226 				return FALSE;
8227 		}
8228 	}
8229 	return TRUE;
8230 }
8231 
8232 static gboolean
mono_gparam_is_assignable_from(MonoClass * target,MonoClass * candidate)8233 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
8234 {
8235 	MonoGenericParam *gparam, *ogparam;
8236 	MonoGenericParamInfo *tinfo, *cinfo;
8237 	MonoClass **candidate_class;
8238 	gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
8239 	int tmask, cmask;
8240 
8241 	if (target == candidate)
8242 		return TRUE;
8243 	if (target->byval_arg.type != candidate->byval_arg.type)
8244 		return FALSE;
8245 
8246 	gparam = target->byval_arg.data.generic_param;
8247 	ogparam = candidate->byval_arg.data.generic_param;
8248 	tinfo = mono_generic_param_info (gparam);
8249 	cinfo = mono_generic_param_info (ogparam);
8250 
8251 	class_constraint_satisfied = FALSE;
8252 	valuetype_constraint_satisfied = FALSE;
8253 
8254 	/*candidate must have a super set of target's special constraints*/
8255 	tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8256 	cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8257 
8258 	if (cinfo->constraints) {
8259 		for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8260 			MonoClass *cc = *candidate_class;
8261 
8262 			if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8263 				class_constraint_satisfied = TRUE;
8264 			else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8265 				valuetype_constraint_satisfied = TRUE;
8266 		}
8267 	}
8268 	class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
8269 	valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
8270 
8271 	if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
8272 		return FALSE;
8273 	if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
8274 		return FALSE;
8275 	if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
8276 		valuetype_constraint_satisfied)) {
8277 		return FALSE;
8278 	}
8279 
8280 
8281 	/*candidate type constraints must be a superset of target's*/
8282 	if (tinfo->constraints) {
8283 		MonoClass **target_class;
8284 		for (target_class = tinfo->constraints; *target_class; ++target_class) {
8285 			MonoClass *tc = *target_class;
8286 
8287 			/*
8288 			 * A constraint from @target might inflate into @candidate itself and in that case we don't need
8289 			 * check it's constraints since it satisfy the constraint by itself.
8290 			 */
8291 			if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8292 				continue;
8293 
8294 			if (!cinfo->constraints)
8295 				return FALSE;
8296 
8297 			for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8298 				MonoClass *cc = *candidate_class;
8299 
8300 				if (mono_class_is_assignable_from (tc, cc))
8301 					break;
8302 
8303 				/*
8304 				 * This happens when we have the following:
8305 				 *
8306 				 * Bar<K> where K : IFace
8307 				 * Foo<T, U> where T : U where U : IFace
8308 				 * 	...
8309 				 * 	Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8310 				 *
8311 				 */
8312 				if (mono_type_is_generic_argument (&cc->byval_arg)) {
8313 					if (mono_gparam_is_assignable_from (target, cc))
8314 						break;
8315 				}
8316 			}
8317 			if (!*candidate_class)
8318 				return FALSE;
8319 		}
8320 	}
8321 
8322 	/*candidate itself must have a constraint that satisfy target*/
8323 	if (cinfo->constraints) {
8324 		for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8325 			MonoClass *cc = *candidate_class;
8326 			if (mono_class_is_assignable_from (target, cc))
8327 				return TRUE;
8328 		}
8329 	}
8330 	return FALSE;
8331 }
8332 
8333 /**
8334  * mono_class_is_assignable_from:
8335  * \param klass the class to be assigned to
8336  * \param oklass the source class
8337  *
8338  * \returns TRUE if an instance of class \p oklass can be assigned to an
8339  * instance of class \p klass
8340  */
8341 gboolean
mono_class_is_assignable_from(MonoClass * klass,MonoClass * oklass)8342 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8343 {
8344 	MonoError error;
8345 	/*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8346 	if (!klass->inited)
8347 		mono_class_init (klass);
8348 
8349 	if (!oklass->inited)
8350 		mono_class_init (oklass);
8351 
8352 	if (mono_class_has_failure (klass) || mono_class_has_failure  (oklass))
8353 		return FALSE;
8354 
8355 	if (mono_type_is_generic_argument (&klass->byval_arg)) {
8356 		if (!mono_type_is_generic_argument (&oklass->byval_arg))
8357 			return FALSE;
8358 		return mono_gparam_is_assignable_from (klass, oklass);
8359 	}
8360 
8361 	/* This can happen if oklass is a tyvar that has a constraint which is another tyvar which in turn
8362 	 * has a constraint which is a class type:
8363 	 *
8364 	 *  class Foo { }
8365 	 *  class G<T1, T2> where T1 : T2 where T2 : Foo { }
8366 	 *
8367 	 * In this case, Foo is assignable from T1.
8368 	 */
8369 	if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8370 		MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8371 		MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8372 		int i;
8373 
8374 		if (constraints) {
8375 			for (i = 0; constraints [i]; ++i) {
8376 				if (mono_class_is_assignable_from (klass, constraints [i]))
8377 					return TRUE;
8378 			}
8379 		}
8380 
8381 		return mono_class_has_parent (oklass, klass);
8382 	}
8383 
8384 	if (MONO_CLASS_IS_INTERFACE (klass)) {
8385 
8386 		/* interface_offsets might not be set for dynamic classes */
8387 		if (mono_class_get_ref_info_handle (oklass) && !oklass->interface_bitmap) {
8388 			/*
8389 			 * oklass might be a generic type parameter but they have
8390 			 * interface_offsets set.
8391 			 */
8392  			gboolean result = mono_reflection_call_is_assignable_to (oklass, klass, &error);
8393 			if (!is_ok (&error)) {
8394 				mono_error_cleanup (&error);
8395 				return FALSE;
8396 			}
8397 			return result;
8398 		}
8399 		if (!oklass->interface_bitmap)
8400 			/* Happens with generic instances of not-yet created dynamic types */
8401 			return FALSE;
8402 		if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8403 			return TRUE;
8404 
8405 		if (klass->is_array_special_interface && oklass->rank == 1) {
8406 			if (mono_class_is_gtd (klass)) {
8407 				/* klass is an array special gtd like
8408 				 * IList`1<>, and oklass is X[] for some X.
8409 				 * Moreover we know that X isn't !0 (the gparam
8410 				 * of IList`1) because in that case we would
8411 				 * have returned TRUE for
8412 				 * MONO_CLASS_IMPLEMENTS_INTERFACE, above.
8413 				 */
8414 				return FALSE;
8415 			}
8416 			// FIXME: IEnumerator`1 should not be an array special interface.
8417 			// The correct fix is to make
8418 			// ((IEnumerable<U>) (new T[] {...})).GetEnumerator()
8419 			// return an IEnumerator<U> (like .NET does) instead of IEnumerator<T>
8420 			// and to stop marking IEnumerable`1 as an array_special_interface.
8421 			if (mono_class_get_generic_type_definition (klass) == mono_defaults.generic_ienumerator_class)
8422 				return FALSE;
8423 
8424 			//XXX we could offset this by having the cast target computed at JIT time
8425 			//XXX we could go even further and emit a wrapper that would do the extra type check
8426 			MonoClass *iface_klass = mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
8427 			MonoClass *obj_klass = oklass->cast_class; //This gets us the cast class of element type of the array
8428 
8429 			// If the target we're trying to cast to is a valuetype, we must account of weird valuetype equivalences such as IntEnum <> int or uint <> int
8430 			// We can't apply it for ref types as this would go wrong with arrays - IList<byte[]> would have byte tested
8431 			if (!mono_class_is_nullable (iface_klass)) {
8432 				if (iface_klass->valuetype)
8433 					iface_klass = iface_klass->cast_class;
8434 
8435 				//array covariant casts only operates on scalar to scalar
8436 				//This is so int[] can't be casted to IComparable<int>[]
8437 				if (!(obj_klass->valuetype && !iface_klass->valuetype) && mono_class_is_assignable_from (iface_klass, obj_klass))
8438 					return TRUE;
8439 			}
8440 		}
8441 
8442 		if (mono_class_has_variant_generic_params (klass)) {
8443 			int i;
8444 			mono_class_setup_interfaces (oklass, &error);
8445 			if (!mono_error_ok (&error)) {
8446 				mono_error_cleanup (&error);
8447 				return FALSE;
8448 			}
8449 
8450 			/*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8451 			for (i = 0; i < oklass->interface_offsets_count; ++i) {
8452 				MonoClass *iface = oklass->interfaces_packed [i];
8453 
8454 				if (mono_class_is_variant_compatible (klass, iface, FALSE))
8455 					return TRUE;
8456 			}
8457 		}
8458 		return FALSE;
8459 	} else if (klass->delegate) {
8460 		if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8461 			return TRUE;
8462 	}else if (klass->rank) {
8463 		MonoClass *eclass, *eoclass;
8464 
8465 		if (oklass->rank != klass->rank)
8466 			return FALSE;
8467 
8468 		/* vectors vs. one dimensional arrays */
8469 		if (oklass->byval_arg.type != klass->byval_arg.type)
8470 			return FALSE;
8471 
8472 		eclass = klass->cast_class;
8473 		eoclass = oklass->cast_class;
8474 
8475 		/*
8476 		 * a is b does not imply a[] is b[] when a is a valuetype, and
8477 		 * b is a reference type.
8478 		 */
8479 
8480 		if (eoclass->valuetype) {
8481 			if ((eclass == mono_defaults.enum_class) ||
8482 				(eclass == mono_defaults.enum_class->parent) ||
8483 				(eclass == mono_defaults.object_class))
8484 				return FALSE;
8485 		}
8486 
8487 		return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8488 	} else if (mono_class_is_nullable (klass)) {
8489 		if (mono_class_is_nullable (oklass))
8490 			return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8491 		else
8492 			return mono_class_is_assignable_from (klass->cast_class, oklass);
8493 	} else if (klass == mono_defaults.object_class)
8494 		return TRUE;
8495 
8496 	return mono_class_has_parent (oklass, klass);
8497 }
8498 
8499 /*Check if @oklass is variant compatible with @klass.*/
8500 static gboolean
mono_class_is_variant_compatible_slow(MonoClass * klass,MonoClass * oklass)8501 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8502 {
8503 	int j;
8504 	MonoType **klass_argv, **oklass_argv;
8505 	MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8506 	MonoGenericContainer *container = mono_class_get_generic_container (klass_gtd);
8507 
8508 	/*Viable candidates are instances of the same generic interface*/
8509 	if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8510 		return FALSE;
8511 
8512 	klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
8513 	oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
8514 
8515 	for (j = 0; j < container->type_argc; ++j) {
8516 		MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8517 		MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8518 
8519 		if (param1_class->valuetype != param2_class->valuetype)
8520 			return FALSE;
8521 
8522 		/*
8523 		 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8524 		 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8525 		 */
8526 		if (param1_class != param2_class) {
8527 			if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8528 				if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8529 					return FALSE;
8530 			} else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8531 				if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8532 					return FALSE;
8533 			} else
8534 				return FALSE;
8535 		}
8536 	}
8537 	return TRUE;
8538 }
8539 /*Check if @candidate implements the interface @target*/
8540 static gboolean
mono_class_implement_interface_slow(MonoClass * target,MonoClass * candidate)8541 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8542 {
8543 	MonoError error;
8544 	int i;
8545 	gboolean is_variant = mono_class_has_variant_generic_params (target);
8546 
8547 	if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8548 		if (mono_class_is_variant_compatible_slow (target, candidate))
8549 			return TRUE;
8550 	}
8551 
8552 	do {
8553 		if (candidate == target)
8554 			return TRUE;
8555 
8556 		/*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8557 		if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8558 			MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info_raw (candidate); /* FIXME use handles */
8559 			int j;
8560 			if (tb && tb->interfaces) {
8561 				for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8562 					MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8563 					MonoClass *iface_class;
8564 
8565 					/* we can't realize the type here since it can do pretty much anything. */
8566 					if (!iface->type)
8567 						continue;
8568 					iface_class = mono_class_from_mono_type (iface->type);
8569 					if (iface_class == target)
8570 						return TRUE;
8571 					if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8572 						return TRUE;
8573 					if (mono_class_implement_interface_slow (target, iface_class))
8574 						return TRUE;
8575 				}
8576 			}
8577 		} else {
8578 			/*setup_interfaces don't mono_class_init anything*/
8579 			/*FIXME this doesn't handle primitive type arrays.
8580 			ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8581 			A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8582 			*/
8583 			mono_class_setup_interfaces (candidate, &error);
8584 			if (!mono_error_ok (&error)) {
8585 				mono_error_cleanup (&error);
8586 				return FALSE;
8587 			}
8588 
8589 			for (i = 0; i < candidate->interface_count; ++i) {
8590 				if (candidate->interfaces [i] == target)
8591 					return TRUE;
8592 
8593 				if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8594 					return TRUE;
8595 
8596 				 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8597 					return TRUE;
8598 			}
8599 		}
8600 		candidate = candidate->parent;
8601 	} while (candidate);
8602 
8603 	return FALSE;
8604 }
8605 
8606 /*
8607  * Check if @oklass can be assigned to @klass.
8608  * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8609  */
8610 gboolean
mono_class_is_assignable_from_slow(MonoClass * target,MonoClass * candidate)8611 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8612 {
8613 	if (candidate == target)
8614 		return TRUE;
8615 	if (target == mono_defaults.object_class)
8616 		return TRUE;
8617 
8618 	if (mono_class_has_parent (candidate, target))
8619 		return TRUE;
8620 
8621 	/*If target is not an interface there is no need to check them.*/
8622 	if (MONO_CLASS_IS_INTERFACE (target))
8623 		return mono_class_implement_interface_slow (target, candidate);
8624 
8625  	if (target->delegate && mono_class_has_variant_generic_params (target))
8626 		return mono_class_is_variant_compatible (target, candidate, FALSE);
8627 
8628 	if (target->rank) {
8629 		MonoClass *eclass, *eoclass;
8630 
8631 		if (target->rank != candidate->rank)
8632 			return FALSE;
8633 
8634 		/* vectors vs. one dimensional arrays */
8635 		if (target->byval_arg.type != candidate->byval_arg.type)
8636 			return FALSE;
8637 
8638 		eclass = target->cast_class;
8639 		eoclass = candidate->cast_class;
8640 
8641 		/*
8642 		 * a is b does not imply a[] is b[] when a is a valuetype, and
8643 		 * b is a reference type.
8644 		 */
8645 
8646 		if (eoclass->valuetype) {
8647 			if ((eclass == mono_defaults.enum_class) ||
8648 				(eclass == mono_defaults.enum_class->parent) ||
8649 				(eclass == mono_defaults.object_class))
8650 				return FALSE;
8651 		}
8652 
8653 		return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8654 	}
8655 	/*FIXME properly handle nullables */
8656 	/*FIXME properly handle (M)VAR */
8657 	return FALSE;
8658 }
8659 
8660 /**
8661  * mono_class_get_cctor:
8662  * \param klass A MonoClass pointer
8663  *
8664  * \returns The static constructor of \p klass if it exists, NULL otherwise.
8665  */
8666 MonoMethod*
mono_class_get_cctor(MonoClass * klass)8667 mono_class_get_cctor (MonoClass *klass)
8668 {
8669 	MonoCachedClassInfo cached_info;
8670 
8671 	if (image_is_dynamic (klass->image)) {
8672 		/*
8673 		 * has_cctor is not set for these classes because mono_class_init () is
8674 		 * not run for them.
8675 		 */
8676 		return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8677 	}
8678 
8679 	mono_class_init (klass);
8680 
8681 	if (!klass->has_cctor)
8682 		return NULL;
8683 
8684 	if (mono_class_is_ginst (klass) && !klass->methods)
8685 		return mono_class_get_inflated_method (klass, mono_class_get_cctor (mono_class_get_generic_class (klass)->container_class));
8686 
8687 	if (mono_class_get_cached_class_info (klass, &cached_info)) {
8688 		MonoError error;
8689 		MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8690 		if (!mono_error_ok (&error))
8691 			g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8692 		return result;
8693 	}
8694 
8695 	return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8696 }
8697 
8698 /**
8699  * mono_class_get_finalizer:
8700  * \param klass: The MonoClass pointer
8701  *
8702  * \returns The finalizer method of \p klass if it exists, NULL otherwise.
8703  */
8704 MonoMethod*
mono_class_get_finalizer(MonoClass * klass)8705 mono_class_get_finalizer (MonoClass *klass)
8706 {
8707 	MonoCachedClassInfo cached_info;
8708 
8709 	if (!klass->inited)
8710 		mono_class_init (klass);
8711 	if (!mono_class_has_finalizer (klass))
8712 		return NULL;
8713 
8714 	if (mono_class_get_cached_class_info (klass, &cached_info)) {
8715 		MonoError error;
8716 		MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8717 		if (!mono_error_ok (&error))
8718 			g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8719 		return result;
8720 	}else {
8721 		mono_class_setup_vtable (klass);
8722 		return klass->vtable [finalize_slot];
8723 	}
8724 }
8725 
8726 /**
8727  * mono_class_needs_cctor_run:
8728  * \param klass the MonoClass pointer
8729  * \param caller a MonoMethod describing the caller
8730  *
8731  * Determines whenever the class has a static constructor and whenever it
8732  * needs to be called when executing CALLER.
8733  */
8734 gboolean
mono_class_needs_cctor_run(MonoClass * klass,MonoMethod * caller)8735 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8736 {
8737 	MonoMethod *method;
8738 
8739 	method = mono_class_get_cctor (klass);
8740 	if (method)
8741 		return (method == caller) ? FALSE : TRUE;
8742 	else
8743 		return FALSE;
8744 }
8745 
8746 /**
8747  * mono_class_array_element_size:
8748  * \param klass
8749  *
8750  * \returns The number of bytes an element of type \p klass uses when stored into an array.
8751  */
8752 gint32
mono_class_array_element_size(MonoClass * klass)8753 mono_class_array_element_size (MonoClass *klass)
8754 {
8755 	MonoType *type = &klass->byval_arg;
8756 
8757 handle_enum:
8758 	switch (type->type) {
8759 	case MONO_TYPE_I1:
8760 	case MONO_TYPE_U1:
8761 	case MONO_TYPE_BOOLEAN:
8762 		return 1;
8763 	case MONO_TYPE_I2:
8764 	case MONO_TYPE_U2:
8765 	case MONO_TYPE_CHAR:
8766 		return 2;
8767 	case MONO_TYPE_I4:
8768 	case MONO_TYPE_U4:
8769 	case MONO_TYPE_R4:
8770 		return 4;
8771 	case MONO_TYPE_I:
8772 	case MONO_TYPE_U:
8773 	case MONO_TYPE_PTR:
8774 	case MONO_TYPE_CLASS:
8775 	case MONO_TYPE_STRING:
8776 	case MONO_TYPE_OBJECT:
8777 	case MONO_TYPE_SZARRAY:
8778 	case MONO_TYPE_ARRAY:
8779 		return sizeof (gpointer);
8780 	case MONO_TYPE_I8:
8781 	case MONO_TYPE_U8:
8782 	case MONO_TYPE_R8:
8783 		return 8;
8784 	case MONO_TYPE_VALUETYPE:
8785 		if (type->data.klass->enumtype) {
8786 			type = mono_class_enum_basetype (type->data.klass);
8787 			klass = klass->element_class;
8788 			goto handle_enum;
8789 		}
8790 		return mono_class_instance_size (klass) - sizeof (MonoObject);
8791 	case MONO_TYPE_GENERICINST:
8792 		type = &type->data.generic_class->container_class->byval_arg;
8793 		goto handle_enum;
8794 	case MONO_TYPE_VAR:
8795 	case MONO_TYPE_MVAR: {
8796 		int align;
8797 
8798 		return mono_type_size (type, &align);
8799 	}
8800 	case MONO_TYPE_VOID:
8801 		return 0;
8802 
8803 	default:
8804 		g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8805 	}
8806 	return -1;
8807 }
8808 
8809 /**
8810  * mono_array_element_size:
8811  * \param ac pointer to a \c MonoArrayClass
8812  *
8813  * \returns The size of single array element.
8814  *
8815  * LOCKING: Acquires the loader lock.
8816  */
8817 gint32
mono_array_element_size(MonoClass * ac)8818 mono_array_element_size (MonoClass *ac)
8819 {
8820 	g_assert (ac->rank);
8821 	if (G_UNLIKELY (!ac->size_inited)) {
8822 		mono_class_setup_fields (ac);
8823 	}
8824 	return ac->sizes.element_size;
8825 }
8826 
8827 /**
8828  * mono_ldtoken:
8829  */
8830 gpointer
mono_ldtoken(MonoImage * image,guint32 token,MonoClass ** handle_class,MonoGenericContext * context)8831 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8832 	      MonoGenericContext *context)
8833 {
8834 	MonoError error;
8835 	gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8836 	g_assert (mono_error_ok (&error));
8837 	return res;
8838 }
8839 
8840 gpointer
mono_ldtoken_checked(MonoImage * image,guint32 token,MonoClass ** handle_class,MonoGenericContext * context,MonoError * error)8841 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8842 	      MonoGenericContext *context, MonoError *error)
8843 {
8844 	error_init (error);
8845 
8846 	if (image_is_dynamic (image)) {
8847 		MonoClass *tmp_handle_class;
8848 		gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context, error);
8849 
8850 		mono_error_assert_ok (error);
8851 		g_assert (tmp_handle_class);
8852 		if (handle_class)
8853 			*handle_class = tmp_handle_class;
8854 
8855 		if (tmp_handle_class == mono_defaults.typehandle_class)
8856 			return &((MonoClass*)obj)->byval_arg;
8857 		else
8858 			return obj;
8859 	}
8860 
8861 	switch (token & 0xff000000) {
8862 	case MONO_TOKEN_TYPE_DEF:
8863 	case MONO_TOKEN_TYPE_REF:
8864 	case MONO_TOKEN_TYPE_SPEC: {
8865 		MonoType *type;
8866 		if (handle_class)
8867 			*handle_class = mono_defaults.typehandle_class;
8868 		type = mono_type_get_checked (image, token, context, error);
8869 		if (!type)
8870 			return NULL;
8871 
8872 		mono_class_init (mono_class_from_mono_type (type));
8873 		/* We return a MonoType* as handle */
8874 		return type;
8875 	}
8876 	case MONO_TOKEN_FIELD_DEF: {
8877 		MonoClass *klass;
8878 		guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8879 		if (!type) {
8880 			mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8881 			return NULL;
8882 		}
8883 		if (handle_class)
8884 			*handle_class = mono_defaults.fieldhandle_class;
8885 		klass = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8886 		if (!klass)
8887 			return NULL;
8888 
8889 		mono_class_init (klass);
8890 		return mono_class_get_field (klass, token);
8891 	}
8892 	case MONO_TOKEN_METHOD_DEF:
8893 	case MONO_TOKEN_METHOD_SPEC: {
8894 		MonoMethod *meth;
8895 		meth = mono_get_method_checked (image, token, NULL, context, error);
8896 		if (handle_class)
8897 			*handle_class = mono_defaults.methodhandle_class;
8898 		if (!meth)
8899 			return NULL;
8900 
8901 		return meth;
8902 	}
8903 	case MONO_TOKEN_MEMBER_REF: {
8904 		guint32 cols [MONO_MEMBERREF_SIZE];
8905 		const char *sig;
8906 		mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8907 		sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8908 		mono_metadata_decode_blob_size (sig, &sig);
8909 		if (*sig == 0x6) { /* it's a field */
8910 			MonoClass *klass;
8911 			MonoClassField *field;
8912 			field = mono_field_from_token_checked (image, token, &klass, context, error);
8913 			if (handle_class)
8914 				*handle_class = mono_defaults.fieldhandle_class;
8915 			return field;
8916 		} else {
8917 			MonoMethod *meth;
8918 			meth = mono_get_method_checked (image, token, NULL, context, error);
8919 			if (handle_class)
8920 				*handle_class = mono_defaults.methodhandle_class;
8921 			return meth;
8922 		}
8923 	}
8924 	default:
8925 		mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8926 	}
8927 	return NULL;
8928 }
8929 
8930 gpointer
mono_lookup_dynamic_token(MonoImage * image,guint32 token,MonoGenericContext * context,MonoError * error)8931 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context, MonoError *error)
8932 {
8933 	MonoClass *handle_class;
8934 	error_init (error);
8935 	return mono_reflection_lookup_dynamic_token (image, token, TRUE, &handle_class, context, error);
8936 }
8937 
8938 gpointer
mono_lookup_dynamic_token_class(MonoImage * image,guint32 token,gboolean valid_token,MonoClass ** handle_class,MonoGenericContext * context,MonoError * error)8939 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
8940 {
8941 	return mono_reflection_lookup_dynamic_token (image, token, valid_token, handle_class, context, error);
8942 }
8943 
8944 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8945 
8946 void
mono_install_get_cached_class_info(MonoGetCachedClassInfo func)8947 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8948 {
8949 	get_cached_class_info = func;
8950 }
8951 
8952 static gboolean
mono_class_get_cached_class_info(MonoClass * klass,MonoCachedClassInfo * res)8953 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8954 {
8955 	if (!get_cached_class_info)
8956 		return FALSE;
8957 	else
8958 		return get_cached_class_info (klass, res);
8959 }
8960 
8961 void
mono_install_get_class_from_name(MonoGetClassFromName func)8962 mono_install_get_class_from_name (MonoGetClassFromName func)
8963 {
8964 	get_class_from_name = func;
8965 }
8966 
8967 /**
8968  * mono_class_get_image:
8969  *
8970  * Use this method to get the \c MonoImage* where this class came from.
8971  *
8972  * \returns The image where this class is defined.
8973  */
8974 MonoImage*
mono_class_get_image(MonoClass * klass)8975 mono_class_get_image (MonoClass *klass)
8976 {
8977 	return klass->image;
8978 }
8979 
8980 /**
8981  * mono_class_get_element_class:
8982  * \param klass the \c MonoClass to act on
8983  *
8984  * Use this function to get the element class of an array.
8985  *
8986  * \returns The element class of an array.
8987  */
8988 MonoClass*
mono_class_get_element_class(MonoClass * klass)8989 mono_class_get_element_class (MonoClass *klass)
8990 {
8991 	return klass->element_class;
8992 }
8993 
8994 /**
8995  * mono_class_is_valuetype:
8996  * \param klass the \c MonoClass to act on
8997  *
8998  * Use this method to determine if the provided \c MonoClass* represents a value type,
8999  * or a reference type.
9000  *
9001  * \returns TRUE if the \c MonoClass represents a \c ValueType, FALSE if it represents a reference type.
9002  */
9003 gboolean
mono_class_is_valuetype(MonoClass * klass)9004 mono_class_is_valuetype (MonoClass *klass)
9005 {
9006 	return klass->valuetype;
9007 }
9008 
9009 /**
9010  * mono_class_is_enum:
9011  * \param klass the \c MonoClass to act on
9012  *
9013  * Use this function to determine if the provided \c MonoClass* represents an enumeration.
9014  *
9015  * \returns TRUE if the \c MonoClass represents an enumeration.
9016  */
9017 gboolean
mono_class_is_enum(MonoClass * klass)9018 mono_class_is_enum (MonoClass *klass)
9019 {
9020 	return klass->enumtype;
9021 }
9022 
9023 /**
9024  * mono_class_enum_basetype:
9025  * \param klass the \c MonoClass to act on
9026  *
9027  * Use this function to get the underlying type for an enumeration value.
9028  *
9029  * \returns The underlying type representation for an enumeration.
9030  */
9031 MonoType*
mono_class_enum_basetype(MonoClass * klass)9032 mono_class_enum_basetype (MonoClass *klass)
9033 {
9034 	if (klass->element_class == klass)
9035 		/* SRE or broken types */
9036 		return NULL;
9037 	else
9038 		return &klass->element_class->byval_arg;
9039 }
9040 
9041 /**
9042  * mono_class_get_parent
9043  * \param klass the \c MonoClass to act on
9044  *
9045  * \returns The parent class for this class.
9046  */
9047 MonoClass*
mono_class_get_parent(MonoClass * klass)9048 mono_class_get_parent (MonoClass *klass)
9049 {
9050 	return klass->parent;
9051 }
9052 
9053 /**
9054  * mono_class_get_nesting_type:
9055  * \param klass the \c MonoClass to act on
9056  *
9057  * Use this function to obtain the class that the provided \c MonoClass* is nested on.
9058  *
9059  * If the return is NULL, this indicates that this class is not nested.
9060  *
9061  * \returns The container type where this type is nested or NULL if this type is not a nested type.
9062  */
9063 MonoClass*
mono_class_get_nesting_type(MonoClass * klass)9064 mono_class_get_nesting_type (MonoClass *klass)
9065 {
9066 	return klass->nested_in;
9067 }
9068 
9069 /**
9070  * mono_class_get_rank:
9071  * \param klass the MonoClass to act on
9072  *
9073  * \returns The rank for the array (the number of dimensions).
9074  */
9075 int
mono_class_get_rank(MonoClass * klass)9076 mono_class_get_rank (MonoClass *klass)
9077 {
9078 	return klass->rank;
9079 }
9080 
9081 /**
9082  * mono_class_get_name
9083  * \param klass the \c MonoClass to act on
9084  *
9085  * \returns The name of the class.
9086  */
9087 const char*
mono_class_get_name(MonoClass * klass)9088 mono_class_get_name (MonoClass *klass)
9089 {
9090 	return klass->name;
9091 }
9092 
9093 /**
9094  * mono_class_get_namespace:
9095  * \param klass the \c MonoClass to act on
9096  *
9097  * \returns The namespace of the class.
9098  */
9099 const char*
mono_class_get_namespace(MonoClass * klass)9100 mono_class_get_namespace (MonoClass *klass)
9101 {
9102 	return klass->name_space;
9103 }
9104 
9105 /**
9106  * mono_class_get_type:
9107  * \param klass the \c MonoClass to act on
9108  *
9109  * This method returns the internal \c MonoType representation for the class.
9110  *
9111  * \returns The \c MonoType from the class.
9112  */
9113 MonoType*
mono_class_get_type(MonoClass * klass)9114 mono_class_get_type (MonoClass *klass)
9115 {
9116 	return &klass->byval_arg;
9117 }
9118 
9119 /**
9120  * mono_class_get_type_token:
9121  * \param klass the \c MonoClass to act on
9122  *
9123  * This method returns type token for the class.
9124  *
9125  * \returns The type token for the class.
9126  */
9127 guint32
mono_class_get_type_token(MonoClass * klass)9128 mono_class_get_type_token (MonoClass *klass)
9129 {
9130   return klass->type_token;
9131 }
9132 
9133 /**
9134  * mono_class_get_byref_type:
9135  * \param klass the \c MonoClass to act on
9136  *
9137  *
9138  */
9139 MonoType*
mono_class_get_byref_type(MonoClass * klass)9140 mono_class_get_byref_type (MonoClass *klass)
9141 {
9142 	return &klass->this_arg;
9143 }
9144 
9145 /**
9146  * mono_class_num_fields:
9147  * \param klass the \c MonoClass to act on
9148  *
9149  * \returns The number of static and instance fields in the class.
9150  */
9151 int
mono_class_num_fields(MonoClass * klass)9152 mono_class_num_fields (MonoClass *klass)
9153 {
9154 	return mono_class_get_field_count (klass);
9155 }
9156 
9157 /**
9158  * mono_class_num_methods:
9159  * \param klass the \c MonoClass to act on
9160  *
9161  * \returns The number of methods in the class.
9162  */
9163 int
mono_class_num_methods(MonoClass * klass)9164 mono_class_num_methods (MonoClass *klass)
9165 {
9166 	return mono_class_get_method_count (klass);
9167 }
9168 
9169 /**
9170  * mono_class_num_properties
9171  * \param klass the \c MonoClass to act on
9172  *
9173  * \returns The number of properties in the class.
9174  */
9175 int
mono_class_num_properties(MonoClass * klass)9176 mono_class_num_properties (MonoClass *klass)
9177 {
9178 	mono_class_setup_properties (klass);
9179 
9180 	return mono_class_get_property_info (klass)->count;
9181 }
9182 
9183 /**
9184  * mono_class_num_events:
9185  * \param klass the \c MonoClass to act on
9186  *
9187  * \returns The number of events in the class.
9188  */
9189 int
mono_class_num_events(MonoClass * klass)9190 mono_class_num_events (MonoClass *klass)
9191 {
9192 	mono_class_setup_events (klass);
9193 
9194 	return mono_class_get_event_info (klass)->count;
9195 }
9196 
9197 /**
9198  * mono_class_get_fields:
9199  * \param klass the \c MonoClass to act on
9200  *
9201  * This routine is an iterator routine for retrieving the fields in a class.
9202  *
9203  * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
9204  * iterate over all of the elements.  When no more values are
9205  * available, the return value is NULL.
9206  *
9207  * \returns a \c MonoClassField* on each iteration, or NULL when no more fields are available.
9208  */
9209 MonoClassField*
mono_class_get_fields(MonoClass * klass,gpointer * iter)9210 mono_class_get_fields (MonoClass* klass, gpointer *iter)
9211 {
9212 	MonoClassField* field;
9213 	if (!iter)
9214 		return NULL;
9215 	if (!*iter) {
9216 		mono_class_setup_fields (klass);
9217 		if (mono_class_has_failure (klass))
9218 			return NULL;
9219 		/* start from the first */
9220 		if (mono_class_get_field_count (klass)) {
9221 			*iter = &klass->fields [0];
9222 			return &klass->fields [0];
9223 		} else {
9224 			/* no fields */
9225 			return NULL;
9226 		}
9227 	}
9228 	field = (MonoClassField *)*iter;
9229 	field++;
9230 	if (field < &klass->fields [mono_class_get_field_count (klass)]) {
9231 		*iter = field;
9232 		return field;
9233 	}
9234 	return NULL;
9235 }
9236 
9237 /**
9238  * mono_class_get_methods:
9239  * \param klass the \c MonoClass to act on
9240  *
9241  * This routine is an iterator routine for retrieving the fields in a class.
9242  *
9243  * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
9244  * iterate over all of the elements.  When no more values are
9245  * available, the return value is NULL.
9246  *
9247  * \returns a \c MonoMethod on each iteration or NULL when no more methods are available.
9248  */
9249 MonoMethod*
mono_class_get_methods(MonoClass * klass,gpointer * iter)9250 mono_class_get_methods (MonoClass* klass, gpointer *iter)
9251 {
9252 	MonoMethod** method;
9253 	if (!iter)
9254 		return NULL;
9255 	if (!*iter) {
9256 		mono_class_setup_methods (klass);
9257 
9258 		/*
9259 		 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9260 		 * FIXME we should better report this error to the caller
9261 		 */
9262 		if (!klass->methods)
9263 			return NULL;
9264 		/* start from the first */
9265 		if (mono_class_get_method_count (klass)) {
9266 			*iter = &klass->methods [0];
9267 			return klass->methods [0];
9268 		} else {
9269 			/* no method */
9270 			return NULL;
9271 		}
9272 	}
9273 	method = (MonoMethod **)*iter;
9274 	method++;
9275 	if (method < &klass->methods [mono_class_get_method_count (klass)]) {
9276 		*iter = method;
9277 		return *method;
9278 	}
9279 	return NULL;
9280 }
9281 
9282 /*
9283  * mono_class_get_virtual_methods:
9284  *
9285  *   Iterate over the virtual methods of KLASS.
9286  *
9287  * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
9288  */
9289 static MonoMethod*
mono_class_get_virtual_methods(MonoClass * klass,gpointer * iter)9290 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
9291 {
9292 	gboolean static_iter = FALSE;
9293 
9294 	if (!iter)
9295 		return NULL;
9296 
9297 	/*
9298 	 * If the lowest bit of the iterator is 1, this is an iterator for static metadata,
9299 	 * and the upper bits contain an index. Otherwise, the iterator is a pointer into
9300 	 * klass->methods.
9301 	 */
9302 	if ((gsize)(*iter) & 1)
9303 		static_iter = TRUE;
9304 	/* Use the static metadata only if klass->methods is not yet initialized */
9305 	if (!static_iter && !(klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)))
9306 		static_iter = TRUE;
9307 
9308 	if (!static_iter) {
9309 		MonoMethod** methodptr;
9310 
9311 		if (!*iter) {
9312 			mono_class_setup_methods (klass);
9313 			/*
9314 			 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9315 			 * FIXME we should better report this error to the caller
9316 			 */
9317 			if (!klass->methods)
9318 				return NULL;
9319 			/* start from the first */
9320 			methodptr = &klass->methods [0];
9321 		} else {
9322 			methodptr = (MonoMethod **)*iter;
9323 			methodptr++;
9324 		}
9325 		if (*iter)
9326 			g_assert ((guint64)(*iter) > 0x100);
9327 		int mcount = mono_class_get_method_count (klass);
9328 		while (methodptr < &klass->methods [mcount]) {
9329 			if (*methodptr && ((*methodptr)->flags & METHOD_ATTRIBUTE_VIRTUAL))
9330 				break;
9331 			methodptr ++;
9332 		}
9333 		if (methodptr < &klass->methods [mcount]) {
9334 			*iter = methodptr;
9335 			return *methodptr;
9336 		} else {
9337 			return NULL;
9338 		}
9339 	} else {
9340 		/* Search directly in metadata to avoid calling setup_methods () */
9341 		MonoMethod *res = NULL;
9342 		int i, start_index;
9343 
9344 		if (!*iter) {
9345 			start_index = 0;
9346 		} else {
9347 			start_index = GPOINTER_TO_UINT (*iter) >> 1;
9348 		}
9349 
9350 		int first_idx = mono_class_get_first_method_idx (klass);
9351 		int mcount = mono_class_get_method_count (klass);
9352 		for (i = start_index; i < mcount; ++i) {
9353 			guint32 flags;
9354 
9355 			/* first_idx points into the methodptr table */
9356 			flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, first_idx + i, MONO_METHOD_FLAGS);
9357 
9358 			if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9359 				break;
9360 		}
9361 
9362 		if (i < mcount) {
9363 			MonoError error;
9364 			res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (first_idx + i + 1), klass, NULL, &error);
9365 			mono_error_cleanup (&error); /* FIXME don't swallow the error */
9366 
9367 			/* Add 1 here so the if (*iter) check fails */
9368 			*iter  = GUINT_TO_POINTER (((i + 1) << 1) | 1);
9369 			return res;
9370 		} else {
9371 			return NULL;
9372 		}
9373 	}
9374 }
9375 
9376 /**
9377  * mono_class_get_properties:
9378  * \param klass the \c MonoClass to act on
9379  *
9380  * This routine is an iterator routine for retrieving the properties in a class.
9381  *
9382  * You must pass a gpointer that points to zero and is treated as an opaque handle to
9383  * iterate over all of the elements.  When no more values are
9384  * available, the return value is NULL.
9385  *
9386  * Returns: a \c MonoProperty* on each invocation, or NULL when no more are available.
9387  */
9388 MonoProperty*
mono_class_get_properties(MonoClass * klass,gpointer * iter)9389 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9390 {
9391 	MonoProperty* property;
9392 	if (!iter)
9393 		return NULL;
9394 	if (!*iter) {
9395 		mono_class_setup_properties (klass);
9396 		MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
9397 		/* start from the first */
9398 		if (info->count) {
9399 			*iter = &info->properties [0];
9400 			return (MonoProperty *)*iter;
9401 		} else {
9402 			/* no fields */
9403 			return NULL;
9404 		}
9405 	}
9406 	property = (MonoProperty *)*iter;
9407 	property++;
9408 	MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
9409 	if (property < &info->properties [info->count]) {
9410 		*iter = property;
9411 		return (MonoProperty *)*iter;
9412 	}
9413 	return NULL;
9414 }
9415 
9416 /**
9417  * mono_class_get_events:
9418  * \param klass the \c MonoClass to act on
9419  *
9420  * This routine is an iterator routine for retrieving the properties in a class.
9421  *
9422  * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
9423  * iterate over all of the elements.  When no more values are
9424  * available, the return value is NULL.
9425  *
9426  * \returns a \c MonoEvent* on each invocation, or NULL when no more are available.
9427  */
9428 MonoEvent*
mono_class_get_events(MonoClass * klass,gpointer * iter)9429 mono_class_get_events (MonoClass* klass, gpointer *iter)
9430 {
9431 	MonoEvent* event;
9432 	if (!iter)
9433 		return NULL;
9434 	if (!*iter) {
9435 		mono_class_setup_events (klass);
9436 		MonoClassEventInfo *info = mono_class_get_event_info (klass);
9437 		/* start from the first */
9438 		if (info->count) {
9439 			*iter = &info->events [0];
9440 			return (MonoEvent *)*iter;
9441 		} else {
9442 			/* no fields */
9443 			return NULL;
9444 		}
9445 	}
9446 	event = (MonoEvent *)*iter;
9447 	event++;
9448 	MonoClassEventInfo *info = mono_class_get_event_info (klass);
9449 	if (event < &info->events [info->count]) {
9450 		*iter = event;
9451 		return (MonoEvent *)*iter;
9452 	}
9453 	return NULL;
9454 }
9455 
9456 /**
9457  * mono_class_get_interfaces
9458  * \param klass the \c MonoClass to act on
9459  *
9460  * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9461  *
9462  * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
9463  * iterate over all of the elements.  When no more values are
9464  * available, the return value is NULL.
9465  *
9466  * \returns a \c MonoClass* on each invocation, or NULL when no more are available.
9467  */
9468 MonoClass*
mono_class_get_interfaces(MonoClass * klass,gpointer * iter)9469 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9470 {
9471 	MonoError error;
9472 	MonoClass** iface;
9473 	if (!iter)
9474 		return NULL;
9475 	if (!*iter) {
9476 		if (!klass->inited)
9477 			mono_class_init (klass);
9478 		if (!klass->interfaces_inited) {
9479 			mono_class_setup_interfaces (klass, &error);
9480 			if (!mono_error_ok (&error)) {
9481 				mono_error_cleanup (&error);
9482 				return NULL;
9483 			}
9484 		}
9485 		/* start from the first */
9486 		if (klass->interface_count) {
9487 			*iter = &klass->interfaces [0];
9488 			return klass->interfaces [0];
9489 		} else {
9490 			/* no interface */
9491 			return NULL;
9492 		}
9493 	}
9494 	iface = (MonoClass **)*iter;
9495 	iface++;
9496 	if (iface < &klass->interfaces [klass->interface_count]) {
9497 		*iter = iface;
9498 		return *iface;
9499 	}
9500 	return NULL;
9501 }
9502 
9503 static void
setup_nested_types(MonoClass * klass)9504 setup_nested_types (MonoClass *klass)
9505 {
9506 	MonoError error;
9507 	GList *classes, *nested_classes, *l;
9508 	int i;
9509 
9510 	if (klass->nested_classes_inited)
9511 		return;
9512 
9513 	if (!klass->type_token) {
9514 		mono_loader_lock ();
9515 		klass->nested_classes_inited = TRUE;
9516 		mono_loader_unlock ();
9517 		return;
9518 	}
9519 
9520 	i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9521 	classes = NULL;
9522 	while (i) {
9523 		MonoClass* nclass;
9524 		guint32 cols [MONO_NESTED_CLASS_SIZE];
9525 		mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9526 		nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9527 		if (!mono_error_ok (&error)) {
9528 			/*FIXME don't swallow the error message*/
9529 			mono_error_cleanup (&error);
9530 
9531 			i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9532 			continue;
9533 		}
9534 
9535 		classes = g_list_prepend (classes, nclass);
9536 
9537 		i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9538 	}
9539 
9540 	nested_classes = NULL;
9541 	for (l = classes; l; l = l->next)
9542 		nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9543 	g_list_free (classes);
9544 
9545 	mono_loader_lock ();
9546 	if (!klass->nested_classes_inited) {
9547 		mono_class_set_nested_classes_property (klass, nested_classes);
9548 		mono_memory_barrier ();
9549 		klass->nested_classes_inited = TRUE;
9550 	}
9551 	mono_loader_unlock ();
9552 }
9553 
9554 /**
9555  * mono_class_get_nested_types
9556  * \param klass the \c MonoClass to act on
9557  *
9558  * This routine is an iterator routine for retrieving the nested types of a class.
9559  * This works only if \p klass is non-generic, or a generic type definition.
9560  *
9561  * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
9562  * iterate over all of the elements.  When no more values are
9563  * available, the return value is NULL.
9564  *
9565  * \returns a \c Monoclass* on each invocation, or NULL when no more are available.
9566  */
9567 MonoClass*
mono_class_get_nested_types(MonoClass * klass,gpointer * iter)9568 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9569 {
9570 	GList *item;
9571 
9572 	if (!iter)
9573 		return NULL;
9574 	if (!klass->nested_classes_inited)
9575 		setup_nested_types (klass);
9576 
9577 	if (!*iter) {
9578 		GList *nested_classes = mono_class_get_nested_classes_property (klass);
9579 		/* start from the first */
9580 		if (nested_classes) {
9581 			*iter = nested_classes;
9582 			return (MonoClass *)nested_classes->data;
9583 		} else {
9584 			/* no nested types */
9585 			return NULL;
9586 		}
9587 	}
9588 	item = (GList *)*iter;
9589 	item = item->next;
9590 	if (item) {
9591 		*iter = item;
9592 		return (MonoClass *)item->data;
9593 	}
9594 	return NULL;
9595 }
9596 
9597 
9598 /**
9599  * mono_class_is_delegate
9600  * \param klass the \c MonoClass to act on
9601  *
9602  * \returns TRUE if the \c MonoClass represents a \c System.Delegate.
9603  */
9604 mono_bool
mono_class_is_delegate(MonoClass * klass)9605 mono_class_is_delegate (MonoClass *klass)
9606 {
9607 	return klass->delegate;
9608 }
9609 
9610 /**
9611  * mono_class_implements_interface
9612  * \param klass The MonoClass to act on
9613  * \param interface The interface to check if \p klass implements.
9614  *
9615  * \returns TRUE if \p klass implements \p interface.
9616  */
9617 mono_bool
mono_class_implements_interface(MonoClass * klass,MonoClass * iface)9618 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9619 {
9620 	return mono_class_is_assignable_from (iface, klass);
9621 }
9622 
9623 /**
9624  * mono_field_get_name:
9625  * \param field the \c MonoClassField to act on
9626  *
9627  * \returns The name of the field.
9628  */
9629 const char*
mono_field_get_name(MonoClassField * field)9630 mono_field_get_name (MonoClassField *field)
9631 {
9632 	return field->name;
9633 }
9634 
9635 /**
9636  * mono_field_get_type:
9637  * \param field the \c MonoClassField to act on
9638  * \returns \c MonoType of the field.
9639  */
9640 MonoType*
mono_field_get_type(MonoClassField * field)9641 mono_field_get_type (MonoClassField *field)
9642 {
9643 	MonoError error;
9644 	MonoType *type = mono_field_get_type_checked (field, &error);
9645 	if (!mono_error_ok (&error)) {
9646 		mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9647 		mono_error_cleanup (&error);
9648 	}
9649 	return type;
9650 }
9651 
9652 
9653 /**
9654  * mono_field_get_type_checked:
9655  * \param field the \c MonoClassField to act on
9656  * \param error used to return any error found while retrieving \p field type
9657  *
9658  * \returns \c MonoType of the field.
9659  */
9660 MonoType*
mono_field_get_type_checked(MonoClassField * field,MonoError * error)9661 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9662 {
9663 	error_init (error);
9664 	if (!field->type)
9665 		mono_field_resolve_type (field, error);
9666 	return field->type;
9667 }
9668 
9669 /**
9670  * mono_field_get_parent:
9671  * \param field the \c MonoClassField to act on
9672  *
9673  * \returns \c MonoClass where the field was defined.
9674  */
9675 MonoClass*
mono_field_get_parent(MonoClassField * field)9676 mono_field_get_parent (MonoClassField *field)
9677 {
9678 	return field->parent;
9679 }
9680 
9681 /**
9682  * mono_field_get_flags;
9683  * \param field the \c MonoClassField to act on
9684  *
9685  * The metadata flags for a field are encoded using the
9686  * \c FIELD_ATTRIBUTE_* constants.  See the \c tabledefs.h file for details.
9687  *
9688  * \returns The flags for the field.
9689  */
9690 guint32
mono_field_get_flags(MonoClassField * field)9691 mono_field_get_flags (MonoClassField *field)
9692 {
9693 	if (!field->type)
9694 		return mono_field_resolve_flags (field);
9695 	return field->type->attrs;
9696 }
9697 
9698 /**
9699  * mono_field_get_offset:
9700  * \param field the \c MonoClassField to act on
9701  *
9702  * \returns The field offset.
9703  */
9704 guint32
mono_field_get_offset(MonoClassField * field)9705 mono_field_get_offset (MonoClassField *field)
9706 {
9707 	return field->offset;
9708 }
9709 
9710 static const char *
mono_field_get_rva(MonoClassField * field)9711 mono_field_get_rva (MonoClassField *field)
9712 {
9713 	guint32 rva;
9714 	int field_index;
9715 	MonoClass *klass = field->parent;
9716 	MonoFieldDefaultValue *def_values;
9717 
9718 	g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9719 
9720 	def_values = mono_class_get_field_def_values (klass);
9721 	if (!def_values) {
9722 		def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * mono_class_get_field_count (klass));
9723 
9724 		mono_class_set_field_def_values (klass, def_values);
9725 	}
9726 
9727 	field_index = mono_field_get_index (field);
9728 
9729 	if (!def_values [field_index].data && !image_is_dynamic (klass->image)) {
9730 		int first_field_idx = mono_class_get_first_field_idx (klass);
9731 		mono_metadata_field_info (field->parent->image, first_field_idx + field_index, NULL, &rva, NULL);
9732 		if (!rva)
9733 			g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9734 		def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9735 	}
9736 
9737 	return def_values [field_index].data;
9738 }
9739 
9740 /**
9741  * mono_field_get_data:
9742  * \param field the \c MonoClassField to act on
9743  *
9744  * \returns A pointer to the metadata constant value or to the field
9745  * data if it has an RVA flag.
9746  */
9747 const char *
mono_field_get_data(MonoClassField * field)9748 mono_field_get_data (MonoClassField *field)
9749 {
9750 	if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9751 		MonoTypeEnum def_type;
9752 
9753 		return mono_class_get_field_default_value (field, &def_type);
9754 	} else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9755 		return mono_field_get_rva (field);
9756 	} else {
9757 		return NULL;
9758 	}
9759 }
9760 
9761 /**
9762  * mono_property_get_name:
9763  * \param prop the \c MonoProperty to act on
9764  * \returns The name of the property
9765  */
9766 const char*
mono_property_get_name(MonoProperty * prop)9767 mono_property_get_name (MonoProperty *prop)
9768 {
9769 	return prop->name;
9770 }
9771 
9772 /**
9773  * mono_property_get_set_method
9774  * \param prop the \c MonoProperty to act on.
9775  * \returns The setter method of the property, a \c MonoMethod.
9776  */
9777 MonoMethod*
mono_property_get_set_method(MonoProperty * prop)9778 mono_property_get_set_method (MonoProperty *prop)
9779 {
9780 	return prop->set;
9781 }
9782 
9783 /**
9784  * mono_property_get_get_method
9785  * \param prop the MonoProperty to act on.
9786  * \returns The getter method of the property (A \c MonoMethod)
9787  */
9788 MonoMethod*
mono_property_get_get_method(MonoProperty * prop)9789 mono_property_get_get_method (MonoProperty *prop)
9790 {
9791 	return prop->get;
9792 }
9793 
9794 /**
9795  * mono_property_get_parent:
9796  * \param prop the \c MonoProperty to act on.
9797  * \returns The \c MonoClass where the property was defined.
9798  */
9799 MonoClass*
mono_property_get_parent(MonoProperty * prop)9800 mono_property_get_parent (MonoProperty *prop)
9801 {
9802 	return prop->parent;
9803 }
9804 
9805 /**
9806  * mono_property_get_flags:
9807  * \param prop the \c MonoProperty to act on.
9808  *
9809  * The metadata flags for a property are encoded using the
9810  * \c PROPERTY_ATTRIBUTE_* constants.  See the \c tabledefs.h file for details.
9811  *
9812  * \returns The flags for the property.
9813  */
9814 guint32
mono_property_get_flags(MonoProperty * prop)9815 mono_property_get_flags (MonoProperty *prop)
9816 {
9817 	return prop->attrs;
9818 }
9819 
9820 /**
9821  * mono_event_get_name:
9822  * \param event the MonoEvent to act on
9823  * \returns The name of the event.
9824  */
9825 const char*
mono_event_get_name(MonoEvent * event)9826 mono_event_get_name (MonoEvent *event)
9827 {
9828 	return event->name;
9829 }
9830 
9831 /**
9832  * mono_event_get_add_method:
9833  * \param event The \c MonoEvent to act on.
9834  * \returns The \c add method for the event, a \c MonoMethod.
9835  */
9836 MonoMethod*
mono_event_get_add_method(MonoEvent * event)9837 mono_event_get_add_method (MonoEvent *event)
9838 {
9839 	return event->add;
9840 }
9841 
9842 /**
9843  * mono_event_get_remove_method:
9844  * \param event The \c MonoEvent to act on.
9845  * \returns The \c remove method for the event, a \c MonoMethod.
9846  */
9847 MonoMethod*
mono_event_get_remove_method(MonoEvent * event)9848 mono_event_get_remove_method (MonoEvent *event)
9849 {
9850 	return event->remove;
9851 }
9852 
9853 /**
9854  * mono_event_get_raise_method:
9855  * \param event The \c MonoEvent to act on.
9856  * \returns The \c raise method for the event, a \c MonoMethod.
9857  */
9858 MonoMethod*
mono_event_get_raise_method(MonoEvent * event)9859 mono_event_get_raise_method (MonoEvent *event)
9860 {
9861 	return event->raise;
9862 }
9863 
9864 /**
9865  * mono_event_get_parent:
9866  * \param event the MonoEvent to act on.
9867  * \returns The \c MonoClass where the event is defined.
9868  */
9869 MonoClass*
mono_event_get_parent(MonoEvent * event)9870 mono_event_get_parent (MonoEvent *event)
9871 {
9872 	return event->parent;
9873 }
9874 
9875 /**
9876  * mono_event_get_flags
9877  * \param event the \c MonoEvent to act on.
9878  *
9879  * The metadata flags for an event are encoded using the
9880  * \c EVENT_* constants.  See the \c tabledefs.h file for details.
9881  *
9882  * \returns The flags for the event.
9883  */
9884 guint32
mono_event_get_flags(MonoEvent * event)9885 mono_event_get_flags (MonoEvent *event)
9886 {
9887 	return event->attrs;
9888 }
9889 
9890 /**
9891  * mono_class_get_method_from_name:
9892  * \param klass where to look for the method
9893  * \param name name of the method
9894  * \param param_count number of parameters. -1 for any number.
9895  *
9896  * Obtains a \c MonoMethod with a given name and number of parameters.
9897  * It only works if there are no multiple signatures for any given method name.
9898  */
9899 MonoMethod *
mono_class_get_method_from_name(MonoClass * klass,const char * name,int param_count)9900 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9901 {
9902 	return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9903 }
9904 
9905 static MonoMethod*
find_method_in_metadata(MonoClass * klass,const char * name,int param_count,int flags)9906 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9907 {
9908 	MonoMethod *res = NULL;
9909 	int i;
9910 
9911 	/* Search directly in the metadata to avoid calling setup_methods () */
9912 	int first_idx = mono_class_get_first_method_idx (klass);
9913 	int mcount = mono_class_get_method_count (klass);
9914 	for (i = 0; i < mcount; ++i) {
9915 		MonoError error;
9916 		guint32 cols [MONO_METHOD_SIZE];
9917 		MonoMethod *method;
9918 		MonoMethodSignature *sig;
9919 
9920 		/* first_idx points into the methodptr table */
9921 		mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, first_idx + i, cols, MONO_METHOD_SIZE);
9922 
9923 		if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9924 			method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (first_idx + i + 1), klass, NULL, &error);
9925 			if (!method) {
9926 				mono_error_cleanup (&error); /* FIXME don't swallow the error */
9927 				continue;
9928 			}
9929 			if (param_count == -1) {
9930 				res = method;
9931 				break;
9932 			}
9933 			sig = mono_method_signature_checked (method, &error);
9934 			if (!sig) {
9935 				mono_error_cleanup (&error); /* FIXME don't swallow the error */
9936 				continue;
9937 			}
9938 			if (sig->param_count == param_count) {
9939 				res = method;
9940 				break;
9941 			}
9942 		}
9943 	}
9944 
9945 	return res;
9946 }
9947 
9948 /**
9949  * mono_class_get_method_from_name_flags:
9950  * \param klass where to look for the method
9951  * \param name_space name of the method
9952  * \param param_count number of parameters. -1 for any number.
9953  * \param flags flags which must be set in the method
9954  *
9955  * Obtains a \c MonoMethod with a given name and number of parameters.
9956  * It only works if there are no multiple signatures for any given method name.
9957  */
9958 MonoMethod *
mono_class_get_method_from_name_flags(MonoClass * klass,const char * name,int param_count,int flags)9959 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9960 {
9961 	MonoMethod *res = NULL;
9962 	int i;
9963 
9964 	mono_class_init (klass);
9965 
9966 	if (mono_class_is_ginst (klass) && !klass->methods) {
9967 		res = mono_class_get_method_from_name_flags (mono_class_get_generic_class (klass)->container_class, name, param_count, flags);
9968 		if (res) {
9969 			MonoError error;
9970 			res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9971 			if (!mono_error_ok (&error))
9972 				mono_error_cleanup (&error); /*FIXME don't swallow the error */
9973 		}
9974 		return res;
9975 	}
9976 
9977 	if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9978 		mono_class_setup_methods (klass);
9979 		/*
9980 		We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9981 		See mono/tests/array_load_exception.il
9982 		FIXME we should better report this error to the caller
9983 		 */
9984 		if (!klass->methods)
9985 			return NULL;
9986 		int mcount = mono_class_get_method_count (klass);
9987 		for (i = 0; i < mcount; ++i) {
9988 			MonoMethod *method = klass->methods [i];
9989 
9990 			if (method->name[0] == name [0] &&
9991 				!strcmp (name, method->name) &&
9992 				(param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9993 				((method->flags & flags) == flags)) {
9994 				res = method;
9995 				break;
9996 			}
9997 		}
9998 	}
9999 	else {
10000 	    res = find_method_in_metadata (klass, name, param_count, flags);
10001 	}
10002 
10003 	return res;
10004 }
10005 
10006 /**
10007  * mono_class_set_failure:
10008  * \param klass class in which the failure was detected
10009  * \param ex_type the kind of exception/error to be thrown (later)
10010  * \param ex_data exception data (specific to each type of exception/error)
10011  *
10012  * Keep a detected failure informations in the class for later processing.
10013  * Note that only the first failure is kept.
10014  *
10015  * LOCKING: Acquires the loader lock.
10016  */
10017 static gboolean
mono_class_set_failure(MonoClass * klass,MonoErrorBoxed * boxed_error)10018 mono_class_set_failure (MonoClass *klass, MonoErrorBoxed *boxed_error)
10019 {
10020 	g_assert (boxed_error != NULL);
10021 
10022 	if (mono_class_has_failure (klass))
10023 		return FALSE;
10024 
10025 	mono_loader_lock ();
10026 	klass->has_failure = 1;
10027 	mono_class_set_exception_data (klass, boxed_error);
10028 	mono_loader_unlock ();
10029 
10030 	return TRUE;
10031 }
10032 
10033 gboolean
mono_class_has_failure(const MonoClass * klass)10034 mono_class_has_failure (const MonoClass *klass)
10035 {
10036 	g_assert (klass != NULL);
10037 	return klass->has_failure != 0;
10038 }
10039 
10040 
10041 /**
10042  * mono_class_set_type_load_failure:
10043  * \param klass class in which the failure was detected
10044  * \param fmt \c printf -style error message string.
10045  *
10046  * Collect detected failure informaion in the class for later processing.
10047  * The error is stored as a MonoErrorBoxed as with mono_error_set_type_load_class()
10048  * Note that only the first failure is kept.
10049  *
10050  * LOCKING: Acquires the loader lock.
10051  *
10052  * \returns FALSE if a failure was already set on the class, or TRUE otherwise.
10053  */
10054 gboolean
mono_class_set_type_load_failure(MonoClass * klass,const char * fmt,...)10055 mono_class_set_type_load_failure (MonoClass *klass, const char * fmt, ...)
10056 {
10057 	MonoError prepare_error;
10058 	va_list args;
10059 
10060 	if (mono_class_has_failure (klass))
10061 		return FALSE;
10062 
10063 	error_init (&prepare_error);
10064 
10065 	va_start (args, fmt);
10066 	mono_error_vset_type_load_class (&prepare_error, klass, fmt, args);
10067 	va_end (args);
10068 
10069 	MonoErrorBoxed *box = mono_error_box (&prepare_error, klass->image);
10070 	mono_error_cleanup (&prepare_error);
10071 	return mono_class_set_failure (klass, box);
10072 }
10073 
10074 /**
10075  * mono_classes_init:
10076  *
10077  * Initialize the resources used by this module.
10078  * Known racy counters: `class_gparam_count`, `classes_size` and `inflated_methods_size`
10079  */
10080 MONO_NO_SANITIZE_THREAD
10081 void
mono_classes_init(void)10082 mono_classes_init (void)
10083 {
10084 	mono_os_mutex_init (&classes_mutex);
10085 
10086 	mono_native_tls_alloc (&setup_fields_tls_id, NULL);
10087 	mono_native_tls_alloc (&init_pending_tls_id, NULL);
10088 
10089 	mono_counters_register ("MonoClassDef count",
10090 							MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_def_count);
10091 	mono_counters_register ("MonoClassGtd count",
10092 							MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_gtd_count);
10093 	mono_counters_register ("MonoClassGenericInst count",
10094 							MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ginst_count);
10095 	mono_counters_register ("MonoClassGenericParam count",
10096 							MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_gparam_count);
10097 	mono_counters_register ("MonoClassArray count",
10098 							MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_array_count);
10099 	mono_counters_register ("MonoClassPointer count",
10100 							MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_pointer_count);
10101 	mono_counters_register ("Inflated methods size",
10102 							MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
10103 	mono_counters_register ("Inflated classes size",
10104 							MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
10105 	mono_counters_register ("MonoClass size",
10106 							MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
10107 }
10108 
10109 /**
10110  * mono_classes_cleanup:
10111  *
10112  * Free the resources used by this module.
10113  */
10114 void
mono_classes_cleanup(void)10115 mono_classes_cleanup (void)
10116 {
10117 	mono_native_tls_free (setup_fields_tls_id);
10118 	mono_native_tls_free (init_pending_tls_id);
10119 
10120 	if (global_interface_bitset)
10121 		mono_bitset_free (global_interface_bitset);
10122 	global_interface_bitset = NULL;
10123 	mono_os_mutex_destroy (&classes_mutex);
10124 }
10125 
10126 /**
10127  * mono_class_get_exception_for_failure:
10128  * \param klass class in which the failure was detected
10129  *
10130  * \returns a constructed MonoException than the caller can then throw
10131  * using mono_raise_exception - or NULL if no failure is present (or
10132  * doesn't result in an exception).
10133  */
10134 MonoException*
mono_class_get_exception_for_failure(MonoClass * klass)10135 mono_class_get_exception_for_failure (MonoClass *klass)
10136 {
10137 	if (!mono_class_has_failure (klass))
10138 		return NULL;
10139 	MonoError unboxed_error;
10140 	error_init (&unboxed_error);
10141 	mono_error_set_for_class_failure (&unboxed_error, klass);
10142 	return mono_error_convert_to_exception (&unboxed_error);
10143 }
10144 
10145 static gboolean
is_nesting_type(MonoClass * outer_klass,MonoClass * inner_klass)10146 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
10147  {
10148 	outer_klass = mono_class_get_generic_type_definition (outer_klass);
10149 	inner_klass = mono_class_get_generic_type_definition (inner_klass);
10150 	do {
10151 		if (outer_klass == inner_klass)
10152 			return TRUE;
10153 		inner_klass = inner_klass->nested_in;
10154 	} while (inner_klass);
10155 	return FALSE;
10156 }
10157 
10158 MonoClass *
mono_class_get_generic_type_definition(MonoClass * klass)10159 mono_class_get_generic_type_definition (MonoClass *klass)
10160 {
10161 	MonoGenericClass *gklass =  mono_class_try_get_generic_class (klass);
10162 	return gklass ? gklass->container_class : klass;
10163 }
10164 
10165 /*
10166  * Check if @klass is a subtype of @parent ignoring generic instantiations.
10167  *
10168  * Generic instantiations are ignored for all super types of @klass.
10169  *
10170  * Visibility checks ignoring generic instantiations.
10171  */
10172 gboolean
mono_class_has_parent_and_ignore_generics(MonoClass * klass,MonoClass * parent)10173 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
10174 {
10175 	int i;
10176 	klass = mono_class_get_generic_type_definition (klass);
10177 	parent = mono_class_get_generic_type_definition (parent);
10178 	mono_class_setup_supertypes (klass);
10179 
10180 	for (i = 0; i < klass->idepth; ++i) {
10181 		if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
10182 			return TRUE;
10183 	}
10184 	return FALSE;
10185 }
10186 /*
10187  * Subtype can only access parent members with family protection if the site object
10188  * is subclass of Subtype. For example:
10189  * class A { protected int x; }
10190  * class B : A {
10191  * 	void valid_access () {
10192  * 		B b;
10193  * 		b.x = 0;
10194  *  }
10195  *  void invalid_access () {
10196  *		A a;
10197  * 		a.x = 0;
10198  *  }
10199  * }
10200  * */
10201 static gboolean
is_valid_family_access(MonoClass * access_klass,MonoClass * member_klass,MonoClass * context_klass)10202 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
10203 {
10204 	if (MONO_CLASS_IS_INTERFACE (member_klass) && !MONO_CLASS_IS_INTERFACE (access_klass)) {
10205 		/* Can happen with default interface methods */
10206 		if (!mono_class_implements_interface (access_klass, member_klass))
10207 			return FALSE;
10208 	} else {
10209 		if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
10210 			return FALSE;
10211 	}
10212 
10213 	if (context_klass == NULL)
10214 		return TRUE;
10215 	/*if access_klass is not member_klass context_klass must be type compat*/
10216 	if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
10217 		return FALSE;
10218 	return TRUE;
10219 }
10220 
10221 static gboolean
can_access_internals(MonoAssembly * accessing,MonoAssembly * accessed)10222 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
10223 {
10224 	GSList *tmp;
10225 	if (accessing == accessed)
10226 		return TRUE;
10227 	if (!accessed || !accessing)
10228 		return FALSE;
10229 
10230 	/* extra safety under CoreCLR - the runtime does not verify the strongname signatures
10231 	 * anywhere so untrusted friends are not safe to access platform's code internals */
10232 	if (mono_security_core_clr_enabled ()) {
10233 		if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
10234 			return FALSE;
10235 	}
10236 
10237 	mono_assembly_load_friends (accessed);
10238 	for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
10239 		MonoAssemblyName *friend_ = (MonoAssemblyName *)tmp->data;
10240 		/* Be conservative with checks */
10241 		if (!friend_->name)
10242 			continue;
10243 		if (g_ascii_strcasecmp (accessing->aname.name, friend_->name))
10244 			continue;
10245 		if (friend_->public_key_token [0]) {
10246 			if (!accessing->aname.public_key_token [0])
10247 				continue;
10248 			if (!mono_public_tokens_are_equal (friend_->public_key_token, accessing->aname.public_key_token))
10249 				continue;
10250 		}
10251 		return TRUE;
10252 	}
10253 	return FALSE;
10254 }
10255 
10256 /*
10257  * If klass is a generic type or if it is derived from a generic type, return the
10258  * MonoClass of the generic definition
10259  * Returns NULL if not found
10260  */
10261 static MonoClass*
get_generic_definition_class(MonoClass * klass)10262 get_generic_definition_class (MonoClass *klass)
10263 {
10264 	while (klass) {
10265 		MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
10266 		if (gklass && gklass->container_class)
10267 			return gklass->container_class;
10268 		klass = klass->parent;
10269 	}
10270 	return NULL;
10271 }
10272 
10273 static gboolean
can_access_instantiation(MonoClass * access_klass,MonoGenericInst * ginst)10274 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
10275 {
10276 	int i;
10277 	for (i = 0; i < ginst->type_argc; ++i) {
10278 		MonoType *type = ginst->type_argv[i];
10279 		switch (type->type) {
10280 		case MONO_TYPE_SZARRAY:
10281 			if (!can_access_type (access_klass, type->data.klass))
10282 				return FALSE;
10283 			break;
10284 		case MONO_TYPE_ARRAY:
10285 			if (!can_access_type (access_klass, type->data.array->eklass))
10286 				return FALSE;
10287 			break;
10288 		case MONO_TYPE_PTR:
10289 			if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
10290 				return FALSE;
10291 			break;
10292 		case MONO_TYPE_CLASS:
10293 		case MONO_TYPE_VALUETYPE:
10294 		case MONO_TYPE_GENERICINST:
10295 			if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
10296 				return FALSE;
10297 		default:
10298 			break;
10299 		}
10300 	}
10301 	return TRUE;
10302 }
10303 
10304 static gboolean
can_access_type(MonoClass * access_klass,MonoClass * member_klass)10305 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
10306 {
10307 	int access_level;
10308 
10309 	if (access_klass == member_klass)
10310 		return TRUE;
10311 
10312 	if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10313 		return TRUE;
10314 
10315 	if (access_klass->element_class && !access_klass->enumtype)
10316 		access_klass = access_klass->element_class;
10317 
10318 	if (member_klass->element_class && !member_klass->enumtype)
10319 		member_klass = member_klass->element_class;
10320 
10321 	access_level = mono_class_get_flags (member_klass) & TYPE_ATTRIBUTE_VISIBILITY_MASK;
10322 
10323 	if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
10324 		return TRUE;
10325 
10326 	if (mono_class_is_ginst (member_klass) && !can_access_instantiation (access_klass, mono_class_get_generic_class (member_klass)->context.class_inst))
10327 		return FALSE;
10328 
10329 	if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
10330 		return TRUE;
10331 
10332 	/*Non nested type with nested visibility. We just fail it.*/
10333 	if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
10334 		return FALSE;
10335 
10336 	MonoClass *member_klass_nested_in = member_klass->nested_in;
10337 	switch (access_level) {
10338 	case TYPE_ATTRIBUTE_NOT_PUBLIC:
10339 		return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10340 
10341 	case TYPE_ATTRIBUTE_PUBLIC:
10342 		return TRUE;
10343 
10344 	case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10345 		return member_klass_nested_in && can_access_type (access_klass, member_klass_nested_in);
10346 
10347 	case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10348 		return is_nesting_type (member_klass, access_klass) && member_klass_nested_in && can_access_type (access_klass, member_klass_nested_in);
10349 
10350 	case TYPE_ATTRIBUTE_NESTED_FAMILY:
10351 		return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10352 
10353 	case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10354 		return can_access_internals (access_klass->image->assembly, member_klass->image->assembly) && member_klass_nested_in && can_access_type (access_klass, member_klass_nested_in);
10355 
10356 	case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10357 		return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10358 			mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10359 
10360 	case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10361 		return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10362 			mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10363 	}
10364 	return FALSE;
10365 }
10366 
10367 /* FIXME: check visibility of type, too */
10368 static gboolean
can_access_member(MonoClass * access_klass,MonoClass * member_klass,MonoClass * context_klass,int access_level)10369 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10370 {
10371 	MonoClass *member_generic_def;
10372 	if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10373 		return TRUE;
10374 
10375 	MonoGenericClass *access_gklass = mono_class_try_get_generic_class (access_klass);
10376 	if (((access_gklass && access_gklass->container_class) ||
10377 					mono_class_is_gtd (access_klass)) &&
10378 			(member_generic_def = get_generic_definition_class (member_klass))) {
10379 		MonoClass *access_container;
10380 
10381 		if (mono_class_is_gtd (access_klass))
10382 			access_container = access_klass;
10383 		else
10384 			access_container = access_gklass->container_class;
10385 
10386 		if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10387 			return TRUE;
10388 	}
10389 
10390 	/* Partition I 8.5.3.2 */
10391 	/* the access level values are the same for fields and methods */
10392 	switch (access_level) {
10393 	case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10394 		/* same compilation unit */
10395 		return access_klass->image == member_klass->image;
10396 	case FIELD_ATTRIBUTE_PRIVATE:
10397 		return access_klass == member_klass;
10398 	case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10399 		if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10400 		    can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10401 			return TRUE;
10402 		return FALSE;
10403 	case FIELD_ATTRIBUTE_ASSEMBLY:
10404 		return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10405 	case FIELD_ATTRIBUTE_FAMILY:
10406 		if (is_valid_family_access (access_klass, member_klass, context_klass))
10407 			return TRUE;
10408 		return FALSE;
10409 	case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10410 		if (is_valid_family_access (access_klass, member_klass, context_klass))
10411 			return TRUE;
10412 		return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10413 	case FIELD_ATTRIBUTE_PUBLIC:
10414 		return TRUE;
10415 	}
10416 	return FALSE;
10417 }
10418 
10419 /**
10420  * mono_method_can_access_field:
10421  * \param method Method that will attempt to access the field
10422  * \param field the field to access
10423  *
10424  * Used to determine if a method is allowed to access the specified field.
10425  *
10426  * \returns TRUE if the given \p method is allowed to access the \p field while following
10427  * the accessibility rules of the CLI.
10428  */
10429 gboolean
mono_method_can_access_field(MonoMethod * method,MonoClassField * field)10430 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10431 {
10432 	/* FIXME: check all overlapping fields */
10433 	int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10434 	if (!can) {
10435 		MonoClass *nested = method->klass->nested_in;
10436 		while (nested) {
10437 			can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10438 			if (can)
10439 				return TRUE;
10440 			nested = nested->nested_in;
10441 		}
10442 	}
10443 	return can;
10444 }
10445 
10446 /**
10447  * mono_method_can_access_method:
10448  * \param method Method that will attempt to access the other method
10449  * \param called the method that we want to probe for accessibility.
10450  *
10451  * Used to determine if the \p method is allowed to access the specified \p called method.
10452  *
10453  * \returns TRUE if the given \p method is allowed to invoke the \p called while following
10454  * the accessibility rules of the CLI.
10455  */
10456 gboolean
mono_method_can_access_method(MonoMethod * method,MonoMethod * called)10457 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10458 {
10459 	method = mono_method_get_method_definition (method);
10460 	called = mono_method_get_method_definition (called);
10461 	return mono_method_can_access_method_full (method, called, NULL);
10462 }
10463 
10464 /*
10465  * mono_method_can_access_method_full:
10466  * @method: The caller method
10467  * @called: The called method
10468  * @context_klass: The static type on stack of the owner @called object used
10469  *
10470  * This function must be used with instance calls, as they have more strict family accessibility.
10471  * It can be used with static methods, but context_klass should be NULL.
10472  *
10473  * Returns: TRUE if caller have proper visibility and acessibility to @called
10474  */
10475 gboolean
mono_method_can_access_method_full(MonoMethod * method,MonoMethod * called,MonoClass * context_klass)10476 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10477 {
10478 	/* Wrappers are except from access checks */
10479 	if (method->wrapper_type != MONO_WRAPPER_NONE || called->wrapper_type != MONO_WRAPPER_NONE)
10480 		return TRUE;
10481 
10482 	MonoClass *access_class = method->klass;
10483 	MonoClass *member_class = called->klass;
10484 	int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10485 	if (!can) {
10486 		MonoClass *nested = access_class->nested_in;
10487 		while (nested) {
10488 			can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10489 			if (can)
10490 				break;
10491 			nested = nested->nested_in;
10492 		}
10493 	}
10494 
10495 	if (!can)
10496 		return FALSE;
10497 
10498 	can = can_access_type (access_class, member_class);
10499 	if (!can) {
10500 		MonoClass *nested = access_class->nested_in;
10501 		while (nested) {
10502 			can = can_access_type (nested, member_class);
10503 			if (can)
10504 				break;
10505 			nested = nested->nested_in;
10506 		}
10507 	}
10508 
10509 	if (!can)
10510 		return FALSE;
10511 
10512 	if (called->is_inflated) {
10513 		MonoMethodInflated * infl = (MonoMethodInflated*)called;
10514 		if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10515 			return FALSE;
10516 	}
10517 
10518 	return TRUE;
10519 }
10520 
10521 
10522 /*
10523  * mono_method_can_access_field_full:
10524  * @method: The caller method
10525  * @field: The accessed field
10526  * @context_klass: The static type on stack of the owner @field object used
10527  *
10528  * This function must be used with instance fields, as they have more strict family accessibility.
10529  * It can be used with static fields, but context_klass should be NULL.
10530  *
10531  * Returns: TRUE if caller have proper visibility and acessibility to @field
10532  */
10533 gboolean
mono_method_can_access_field_full(MonoMethod * method,MonoClassField * field,MonoClass * context_klass)10534 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10535 {
10536 	MonoClass *access_class = method->klass;
10537 	MonoClass *member_class = field->parent;
10538 	/* FIXME: check all overlapping fields */
10539 	int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10540 	if (!can) {
10541 		MonoClass *nested = access_class->nested_in;
10542 		while (nested) {
10543 			can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10544 			if (can)
10545 				break;
10546 			nested = nested->nested_in;
10547 		}
10548 	}
10549 
10550 	if (!can)
10551 		return FALSE;
10552 
10553 	can = can_access_type (access_class, member_class);
10554 	if (!can) {
10555 		MonoClass *nested = access_class->nested_in;
10556 		while (nested) {
10557 			can = can_access_type (nested, member_class);
10558 			if (can)
10559 				break;
10560 			nested = nested->nested_in;
10561 		}
10562 	}
10563 
10564 	if (!can)
10565 		return FALSE;
10566 	return TRUE;
10567 }
10568 
10569 /*
10570  * mono_class_can_access_class:
10571  * @source_class: The source class
10572  * @target_class: The accessed class
10573  *
10574  * This function returns is @target_class is visible to @source_class
10575  *
10576  * Returns: TRUE if source have proper visibility and acessibility to target
10577  */
10578 gboolean
mono_class_can_access_class(MonoClass * source_class,MonoClass * target_class)10579 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10580 {
10581 	return can_access_type (source_class, target_class);
10582 }
10583 
10584 /**
10585  * mono_type_is_valid_enum_basetype:
10586  * \param type The MonoType to check
10587  * \returns TRUE if the type can be used as the basetype of an enum
10588  */
mono_type_is_valid_enum_basetype(MonoType * type)10589 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10590 	switch (type->type) {
10591 	case MONO_TYPE_I1:
10592 	case MONO_TYPE_U1:
10593 	case MONO_TYPE_BOOLEAN:
10594 	case MONO_TYPE_I2:
10595 	case MONO_TYPE_U2:
10596 	case MONO_TYPE_CHAR:
10597 	case MONO_TYPE_I4:
10598 	case MONO_TYPE_U4:
10599 	case MONO_TYPE_I8:
10600 	case MONO_TYPE_U8:
10601 	case MONO_TYPE_I:
10602 	case MONO_TYPE_U:
10603 		return TRUE;
10604 	default:
10605 		return FALSE;
10606 	}
10607 }
10608 
10609 /**
10610  * mono_class_is_valid_enum:
10611  * \param klass An enum class to be validated
10612  *
10613  * This method verify the required properties an enum should have.
10614  *
10615  * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10616  * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10617  * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10618  *
10619  * \returns TRUE if the informed enum class is valid
10620  */
10621 gboolean
mono_class_is_valid_enum(MonoClass * klass)10622 mono_class_is_valid_enum (MonoClass *klass)
10623 {
10624 	MonoClassField * field;
10625 	gpointer iter = NULL;
10626 	gboolean found_base_field = FALSE;
10627 
10628 	g_assert (klass->enumtype);
10629 	/* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10630 	if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10631 		return FALSE;
10632 	}
10633 
10634 	if (!mono_class_is_auto_layout (klass))
10635 		return FALSE;
10636 
10637 	while ((field = mono_class_get_fields (klass, &iter))) {
10638 		if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10639 			if (found_base_field)
10640 				return FALSE;
10641 			found_base_field = TRUE;
10642 			if (!mono_type_is_valid_enum_basetype (field->type))
10643 				return FALSE;
10644 		}
10645 	}
10646 
10647 	if (!found_base_field)
10648 		return FALSE;
10649 
10650 	if (mono_class_get_method_count (klass) > 0)
10651 		return FALSE;
10652 
10653 	return TRUE;
10654 }
10655 
10656 gboolean
mono_generic_class_is_generic_type_definition(MonoGenericClass * gklass)10657 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10658 {
10659 	return gklass->context.class_inst == mono_class_get_generic_container (gklass->container_class)->context.class_inst;
10660 }
10661 
10662 /*
10663  * mono_class_setup_interface_id:
10664  *
10665  * Initializes MonoClass::interface_id if required.
10666  *
10667  * LOCKING: Acquires the loader lock.
10668  */
10669 void
mono_class_setup_interface_id(MonoClass * klass)10670 mono_class_setup_interface_id (MonoClass *klass)
10671 {
10672 	g_assert (MONO_CLASS_IS_INTERFACE (klass));
10673 	mono_loader_lock ();
10674 	if (!klass->interface_id)
10675 		klass->interface_id = mono_get_unique_iid (klass);
10676 	mono_loader_unlock ();
10677 }
10678 
10679 /*
10680  * mono_class_setup_interfaces:
10681  *
10682  *   Initialize klass->interfaces/interfaces_count.
10683  * LOCKING: Acquires the loader lock.
10684  * This function can fail the type.
10685  */
10686 void
mono_class_setup_interfaces(MonoClass * klass,MonoError * error)10687 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10688 {
10689 	int i, interface_count;
10690 	MonoClass **interfaces;
10691 
10692 	error_init (error);
10693 
10694 	if (klass->interfaces_inited)
10695 		return;
10696 
10697 	if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10698 		MonoType *args [1];
10699 
10700 		/* IList and IReadOnlyList -> 2x if enum*/
10701 		interface_count = klass->element_class->enumtype ? 4 : 2;
10702 		interfaces = (MonoClass **)mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10703 
10704 		args [0] = &klass->element_class->byval_arg;
10705 		interfaces [0] = mono_class_bind_generic_parameters (
10706 			mono_defaults.generic_ilist_class, 1, args, FALSE);
10707 		interfaces [1] = mono_class_bind_generic_parameters (
10708 			   mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10709 		if (klass->element_class->enumtype) {
10710 			args [0] = mono_class_enum_basetype (klass->element_class);
10711 			interfaces [2] = mono_class_bind_generic_parameters (
10712 				mono_defaults.generic_ilist_class, 1, args, FALSE);
10713 			interfaces [3] = mono_class_bind_generic_parameters (
10714 				   mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10715 		}
10716 	} else if (mono_class_is_ginst (klass)) {
10717 		MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
10718 
10719 		mono_class_setup_interfaces (gklass, error);
10720 		if (!mono_error_ok (error)) {
10721 			mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10722 			return;
10723 		}
10724 
10725 		interface_count = gklass->interface_count;
10726 		interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10727 		for (i = 0; i < interface_count; i++) {
10728 			interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (mono_class_get_generic_class (klass)), error);
10729 			if (!mono_error_ok (error)) {
10730 				mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10731 				return;
10732 			}
10733 		}
10734 	} else {
10735 		interface_count = 0;
10736 		interfaces = NULL;
10737 	}
10738 
10739 	mono_loader_lock ();
10740 	if (!klass->interfaces_inited) {
10741 		klass->interface_count = interface_count;
10742 		klass->interfaces = interfaces;
10743 
10744 		mono_memory_barrier ();
10745 
10746 		klass->interfaces_inited = TRUE;
10747 	}
10748 	mono_loader_unlock ();
10749 }
10750 
10751 static void
mono_field_resolve_type(MonoClassField * field,MonoError * error)10752 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10753 {
10754 	MonoClass *klass = field->parent;
10755 	MonoImage *image = klass->image;
10756 	MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
10757 	MonoType *ftype;
10758 	int field_idx = field - klass->fields;
10759 
10760 	error_init (error);
10761 
10762 	if (gtd) {
10763 		MonoClassField *gfield = &gtd->fields [field_idx];
10764 		MonoType *gtype = mono_field_get_type_checked (gfield, error);
10765 		if (!mono_error_ok (error)) {
10766 			char *full_name = mono_type_get_full_name (gtd);
10767 			mono_class_set_type_load_failure (klass, "Could not load generic type of field '%s:%s' (%d) due to: %s", full_name, gfield->name, field_idx, mono_error_get_message (error));
10768 			g_free (full_name);
10769 		}
10770 
10771 		ftype = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (klass), error);
10772 		if (!mono_error_ok (error)) {
10773 			char *full_name = mono_type_get_full_name (klass);
10774 			mono_class_set_type_load_failure (klass, "Could not load instantiated type of field '%s:%s' (%d) due to: %s", full_name, field->name, field_idx, mono_error_get_message (error));
10775 			g_free (full_name);
10776 		}
10777 	} else {
10778 		const char *sig;
10779 		guint32 cols [MONO_FIELD_SIZE];
10780 		MonoGenericContainer *container = NULL;
10781 		int idx = mono_class_get_first_field_idx (klass) + field_idx;
10782 
10783 		/*FIXME, in theory we do not lazy load SRE fields*/
10784 		g_assert (!image_is_dynamic (image));
10785 
10786 		if (mono_class_is_gtd (klass)) {
10787 			container = mono_class_get_generic_container (klass);
10788 		} else if (gtd) {
10789 			container = mono_class_get_generic_container (gtd);
10790 			g_assert (container);
10791 		}
10792 
10793 		/* first_field_idx and idx points into the fieldptr table */
10794 		mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10795 
10796 		if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10797 			char *full_name = mono_type_get_full_name (klass);
10798 			mono_error_set_type_load_class (error, klass, "Could not verify field '%s:%s' signature", full_name, field->name);;
10799 			mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
10800 			g_free (full_name);
10801 			return;
10802 		}
10803 
10804 		sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10805 
10806 		mono_metadata_decode_value (sig, &sig);
10807 		/* FIELD signature == 0x06 */
10808 		g_assert (*sig == 0x06);
10809 
10810 		ftype = mono_metadata_parse_type_checked (image, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
10811 		if (!ftype) {
10812 			char *full_name = mono_type_get_full_name (klass);
10813 			mono_class_set_type_load_failure (klass, "Could not load type of field '%s:%s' (%d) due to: %s", full_name, field->name, field_idx, mono_error_get_message (error));
10814 			g_free (full_name);
10815 		}
10816 	}
10817 	mono_memory_barrier ();
10818 	field->type = ftype;
10819 }
10820 
10821 static guint32
mono_field_resolve_flags(MonoClassField * field)10822 mono_field_resolve_flags (MonoClassField *field)
10823 {
10824 	MonoClass *klass = field->parent;
10825 	MonoImage *image = klass->image;
10826 	MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
10827 	int field_idx = field - klass->fields;
10828 
10829 	if (gtd) {
10830 		MonoClassField *gfield = &gtd->fields [field_idx];
10831 		return mono_field_get_flags (gfield);
10832 	} else {
10833 		int idx = mono_class_get_first_field_idx (klass) + field_idx;
10834 
10835 		/*FIXME, in theory we do not lazy load SRE fields*/
10836 		g_assert (!image_is_dynamic (image));
10837 
10838 		return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10839 	}
10840 }
10841 
10842 /**
10843  * mono_class_get_fields_lazy:
10844  * \param klass the MonoClass to act on
10845  *
10846  * This routine is an iterator routine for retrieving the fields in a class.
10847  * Only minimal information about fields are loaded. Accessors must be used
10848  * for all MonoClassField returned.
10849  *
10850  * You must pass a gpointer that points to zero and is treated as an opaque handle to
10851  * iterate over all of the elements.  When no more values are
10852  * available, the return value is NULL.
10853  *
10854  * \returns a \c MonoClassField* on each iteration, or NULL when no more fields are available.
10855  */
10856 MonoClassField*
mono_class_get_fields_lazy(MonoClass * klass,gpointer * iter)10857 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10858 {
10859 	MonoClassField* field;
10860 	if (!iter)
10861 		return NULL;
10862 	if (!*iter) {
10863 		mono_class_setup_basic_field_info (klass);
10864 		if (!klass->fields)
10865 			return NULL;
10866 		/* start from the first */
10867 		if (mono_class_get_field_count (klass)) {
10868 			*iter = &klass->fields [0];
10869 			return (MonoClassField *)*iter;
10870 		} else {
10871 			/* no fields */
10872 			return NULL;
10873 		}
10874 	}
10875 	field = (MonoClassField *)*iter;
10876 	field++;
10877 	if (field < &klass->fields [mono_class_get_field_count (klass)]) {
10878 		*iter = field;
10879 		return (MonoClassField *)*iter;
10880 	}
10881 	return NULL;
10882 }
10883 
10884 char*
mono_class_full_name(MonoClass * klass)10885 mono_class_full_name (MonoClass *klass)
10886 {
10887 	return mono_type_full_name (&klass->byval_arg);
10888 }
10889 
10890 /* Declare all shared lazy type lookup functions */
10891 GENERATE_TRY_GET_CLASS_WITH_CACHE (safehandle, "System.Runtime.InteropServices", "SafeHandle")
10892 
10893 /**
10894  * mono_method_get_base_method:
10895  * \param method a method
10896  * \param definition if true, get the definition
10897  * \param error set on failure
10898  *
10899  * Given a virtual method associated with a subclass, return the corresponding
10900  * method from an ancestor.  If \p definition is FALSE, returns the method in the
10901  * superclass of the given method.  If \p definition is TRUE, return the method
10902  * in the ancestor class where it was first declared.  The type arguments will
10903  * be inflated in the ancestor classes.  If the method is not associated with a
10904  * class, or isn't virtual, returns the method itself.  On failure returns NULL
10905  * and sets \p error.
10906  */
10907 MonoMethod*
mono_method_get_base_method(MonoMethod * method,gboolean definition,MonoError * error)10908 mono_method_get_base_method (MonoMethod *method, gboolean definition, MonoError *error)
10909 {
10910 	MonoClass *klass, *parent;
10911 	MonoGenericContext *generic_inst = NULL;
10912 	MonoMethod *result = NULL;
10913 	int slot;
10914 
10915 	if (method->klass == NULL)
10916 		return method;
10917 
10918 	if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
10919 	    MONO_CLASS_IS_INTERFACE (method->klass) ||
10920 	    method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
10921 		return method;
10922 
10923 	slot = mono_method_get_vtable_slot (method);
10924 	if (slot == -1)
10925 		return method;
10926 
10927 	klass = method->klass;
10928 	if (mono_class_is_ginst (klass)) {
10929 		generic_inst = mono_class_get_context (klass);
10930 		klass = mono_class_get_generic_class (klass)->container_class;
10931 	}
10932 
10933 retry:
10934 	if (definition) {
10935 		/* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
10936 		for (parent = klass->parent; parent != NULL; parent = parent->parent) {
10937 			/* on entry, klass is either a plain old non-generic class and generic_inst == NULL
10938 			   or klass is the generic container class and generic_inst is the instantiation.
10939 
10940 			   when we go to the parent, if the parent is an open constructed type, we need to
10941 			   replace the type parameters by the definitions from the generic_inst, and then take it
10942 			   apart again into the klass and the generic_inst.
10943 
10944 			   For cases like this:
10945 			   class C<T> : B<T, int> {
10946 			       public override void Foo () { ... }
10947 			   }
10948 			   class B<U,V> : A<HashMap<U,V>> {
10949 			       public override void Foo () { ... }
10950 			   }
10951 			   class A<X> {
10952 			       public virtual void Foo () { ... }
10953 			   }
10954 
10955 			   if at each iteration the parent isn't open, we can skip inflating it.  if at some
10956 			   iteration the parent isn't generic (after possible inflation), we set generic_inst to
10957 			   NULL;
10958 			*/
10959 			MonoGenericContext *parent_inst = NULL;
10960 			if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
10961 				parent = mono_class_inflate_generic_class_checked (parent, generic_inst, error);
10962 				return_val_if_nok  (error, NULL);
10963 			}
10964 			if (mono_class_is_ginst (parent)) {
10965 				parent_inst = mono_class_get_context (parent);
10966 				parent = mono_class_get_generic_class (parent)->container_class;
10967 			}
10968 
10969 			mono_class_setup_vtable (parent);
10970 			if (parent->vtable_size <= slot)
10971 				break;
10972 			klass = parent;
10973 			generic_inst = parent_inst;
10974 		}
10975 	} else {
10976 		klass = klass->parent;
10977 		if (!klass)
10978 			return method;
10979 		if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
10980 			klass = mono_class_inflate_generic_class_checked (klass, generic_inst, error);
10981 			return_val_if_nok (error, NULL);
10982 
10983 			generic_inst = NULL;
10984 		}
10985 		if (mono_class_is_ginst (klass)) {
10986 			generic_inst = mono_class_get_context (klass);
10987 			klass = mono_class_get_generic_class (klass)->container_class;
10988 		}
10989 
10990 	}
10991 
10992 	if (generic_inst) {
10993 		klass = mono_class_inflate_generic_class_checked (klass, generic_inst, error);
10994 		return_val_if_nok (error, NULL);
10995 	}
10996 
10997 	if (klass == method->klass)
10998 		return method;
10999 
11000 	/*This is possible if definition == FALSE.
11001 	 * Do it here to be really sure we don't read invalid memory.
11002 	 */
11003 	if (slot >= klass->vtable_size)
11004 		return method;
11005 
11006 	mono_class_setup_vtable (klass);
11007 
11008 	result = klass->vtable [slot];
11009 	if (result == NULL) {
11010 		/* It is an abstract method */
11011 		gboolean found = FALSE;
11012 		gpointer iter = NULL;
11013 		while ((result = mono_class_get_methods (klass, &iter))) {
11014 			if (result->slot == slot) {
11015 				found = TRUE;
11016 				break;
11017 			}
11018 		}
11019 		/* found might be FALSE if we looked in an abstract class
11020 		 * that doesn't override an abstract method of its
11021 		 * parent:
11022 		 *   abstract class Base {
11023 		 *     public abstract void Foo ();
11024 		 *   }
11025 		 *   abstract class Derived : Base { }
11026 		 *   class Child : Derived {
11027 		 *     public override void Foo () { }
11028 		 *  }
11029 		 *
11030 		 *  if m was Child.Foo and we ask for the base method,
11031 		 *  then we get here with klass == Derived and found == FALSE
11032 		 */
11033 		/* but it shouldn't be the case that if we're looking
11034 		 * for the definition and didn't find a result; the
11035 		 * loop above should've taken us as far as we could
11036 		 * go! */
11037 		g_assert (!(definition && !found));
11038 		if (!found)
11039 			goto retry;
11040 	}
11041 
11042 	g_assert (result != NULL);
11043 	return result;
11044 }
11045 
11046 
11047 static gboolean
class_kind_may_contain_generic_instances(MonoTypeKind kind)11048 class_kind_may_contain_generic_instances (MonoTypeKind kind)
11049 {
11050 	/* classes of type generic inst may contain generic arguments from other images,
11051 	 * as well as arrays and pointers whose element types (recursively) may be a generic inst */
11052 	return (kind == MONO_CLASS_GINST || kind == MONO_CLASS_ARRAY || kind == MONO_CLASS_POINTER);
11053 }
11054