2 * sre.c: Routines for creating an image at runtime
3 * and related System.Reflection.Emit icalls
7 * Paolo Molaro (lupus@ximian.com)
9 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
10 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
11 * Copyright 2011 Rodrigo Kumpera
12 * Copyright 2016 Microsoft
14 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
18 #include "mono/metadata/assembly.h"
19 #include "mono/metadata/debug-helpers.h"
20 #include "mono/metadata/dynamic-image-internals.h"
21 #include "mono/metadata/dynamic-stream-internals.h"
22 #include "mono/metadata/exception.h"
23 #include "mono/metadata/gc-internals.h"
24 #include "mono/metadata/mono-ptr-array.h"
25 #include "mono/metadata/object-internals.h"
26 #include "mono/metadata/profiler-private.h"
27 #include "mono/metadata/reflection-internals.h"
28 #include "mono/metadata/reflection-cache.h"
29 #include "mono/metadata/sre-internals.h"
30 #include "mono/metadata/custom-attrs-internals.h"
31 #include "mono/metadata/security-manager.h"
32 #include "mono/metadata/security-core-clr.h"
33 #include "mono/metadata/tabledefs.h"
34 #include "mono/metadata/tokentype.h"
35 #include "mono/utils/checked-build.h"
36 #include "mono/utils/mono-digest.h"
38 static GENERATE_GET_CLASS_WITH_CACHE (marshal_as_attribute, System.Runtime.InteropServices, MarshalAsAttribute);
39 static GENERATE_GET_CLASS_WITH_CACHE (module_builder, System.Reflection.Emit, ModuleBuilder);
41 #ifndef DISABLE_REFLECTION_EMIT
42 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
43 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error);
44 static gboolean ensure_runtime_vtable (MonoClass *klass, MonoError *error);
45 static void reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb);
46 static gboolean reflection_setup_internal_class (MonoReflectionTypeBuilder *tb, MonoError *error);
47 static gboolean reflection_create_generic_class (MonoReflectionTypeBuilder *tb, MonoError *error);
50 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
53 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
54 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error);
55 static gboolean is_sre_array (MonoClass *klass);
56 static gboolean is_sre_byref (MonoClass *klass);
57 static gboolean is_sre_pointer (MonoClass *klass);
58 static gboolean is_sre_generic_instance (MonoClass *klass);
59 static gboolean is_sre_type_builder (MonoClass *klass);
60 static gboolean is_sre_method_builder (MonoClass *klass);
61 static gboolean is_sre_field_builder (MonoClass *klass);
62 static gboolean is_sre_gparam_builder (MonoClass *klass);
63 static gboolean is_sre_enum_builder (MonoClass *klass);
64 static gboolean is_sr_mono_method (MonoClass *klass);
65 static gboolean is_sr_mono_field (MonoClass *klass);
67 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
68 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
70 #define mono_type_array_get_and_resolve(array, index, error) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index), error)
72 static void mono_image_module_basic_init (MonoReflectionModuleBuilder *module);
75 mono_reflection_emit_init (void)
77 mono_dynamic_images_init ();
81 type_get_fully_qualified_name (MonoType *type)
83 MONO_REQ_GC_NEUTRAL_MODE;
85 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
89 type_get_qualified_name (MonoType *type, MonoAssembly *ass)
91 MONO_REQ_GC_UNSAFE_MODE;
96 klass = mono_class_from_mono_type (type);
98 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
99 ta = klass->image->assembly;
100 if (assembly_is_dynamic (ta) || (ta == ass)) {
101 if (mono_class_is_ginst (klass) || mono_class_is_gtd (klass))
102 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
103 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
105 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
108 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
111 #ifndef DISABLE_REFLECTION_EMIT
115 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
119 image_g_malloc (MonoImage *image, guint size)
121 MONO_REQ_GC_NEUTRAL_MODE;
124 return mono_image_alloc (image, size);
126 return g_malloc (size);
128 #endif /* !DISABLE_REFLECTION_EMIT */
133 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
137 mono_image_g_malloc0 (MonoImage *image, guint size)
139 MONO_REQ_GC_NEUTRAL_MODE;
142 return mono_image_alloc0 (image, size);
144 return g_malloc0 (size);
149 * @image: a MonoImage
152 * If @image is NULL, free @ptr, otherwise do nothing.
155 image_g_free (MonoImage *image, gpointer ptr)
161 #ifndef DISABLE_REFLECTION_EMIT
163 image_strdup (MonoImage *image, const char *s)
165 MONO_REQ_GC_NEUTRAL_MODE;
168 return mono_image_strdup (image, s);
174 #define image_g_new(image,struct_type, n_structs) \
175 ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
177 #define image_g_new0(image,struct_type, n_structs) \
178 ((struct_type *) mono_image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
182 alloc_table (MonoDynamicTable *table, guint nrows)
184 mono_dynimage_alloc_table (table, nrows);
188 string_heap_insert (MonoDynamicStream *sh, const char *str)
190 return mono_dynstream_insert_string (sh, str);
194 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
196 return mono_dynstream_add_data (stream, data, len);
200 * Despite the name, we handle also TypeSpec (with the above helper).
203 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
205 return mono_dynimage_encode_typedef_or_ref_full (assembly, type, TRUE);
209 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
210 * dest may be misaligned.
213 swap_with_size (char *dest, const char* val, int len, int nelem) {
214 MONO_REQ_GC_NEUTRAL_MODE;
215 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
218 for (elem = 0; elem < nelem; ++elem) {
244 g_assert_not_reached ();
250 memcpy (dest, val, len * nelem);
255 mono_reflection_method_count_clauses (MonoReflectionILGen *ilgen)
257 MONO_REQ_GC_UNSAFE_MODE;
259 guint32 num_clauses = 0;
262 MonoILExceptionInfo *ex_info;
263 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
264 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
265 if (ex_info->handlers)
266 num_clauses += mono_array_length (ex_info->handlers);
274 #ifndef DISABLE_REFLECTION_EMIT
275 static MonoExceptionClause*
276 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses, MonoError *error)
278 MONO_REQ_GC_UNSAFE_MODE;
280 mono_error_init (error);
282 MonoExceptionClause *clauses;
283 MonoExceptionClause *clause;
284 MonoILExceptionInfo *ex_info;
285 MonoILExceptionBlock *ex_block;
286 guint32 finally_start;
287 int i, j, clause_index;;
289 clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
292 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
293 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
294 finally_start = ex_info->start + ex_info->len;
295 if (!ex_info->handlers)
297 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
298 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
299 clause = &(clauses [clause_index]);
301 clause->flags = ex_block->type;
302 clause->try_offset = ex_info->start;
304 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
305 clause->try_len = finally_start - ex_info->start;
307 clause->try_len = ex_info->len;
308 clause->handler_offset = ex_block->start;
309 clause->handler_len = ex_block->len;
310 if (ex_block->extype) {
311 MonoType *extype = mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype, error);
313 if (!is_ok (error)) {
314 image_g_free (image, clauses);
317 clause->data.catch_class = mono_class_from_mono_type (extype);
319 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
320 clause->data.filter_offset = ex_block->filter_offset;
322 clause->data.filter_offset = 0;
324 finally_start = ex_block->start + ex_block->len;
332 #endif /* !DISABLE_REFLECTION_EMIT */
334 #ifndef DISABLE_REFLECTION_EMIT
336 * LOCKING: Acquires the loader lock.
339 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
341 MONO_REQ_GC_UNSAFE_MODE;
343 MonoCustomAttrInfo *ainfo, *tmp;
345 if (!cattrs || !mono_array_length (cattrs))
348 ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
351 tmp = (MonoCustomAttrInfo *)mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
353 mono_custom_attrs_free (tmp);
354 mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
355 mono_loader_unlock ();
361 mono_reflection_resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
363 MONO_REQ_GC_UNSAFE_MODE;
365 MonoDynamicTable *table;
368 guint32 cols [MONO_ASSEMBLY_SIZE];
372 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
375 if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
376 table = &assembly->tables [MONO_TABLE_MODULEREF];
377 token = table->next_idx ++;
379 alloc_table (table, table->rows);
380 values = table->values + token * MONO_MODULEREF_SIZE;
381 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
383 token <<= MONO_RESOLUTION_SCOPE_BITS;
384 token |= MONO_RESOLUTION_SCOPE_MODULEREF;
385 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
390 if (assembly_is_dynamic (image->assembly))
392 memset (cols, 0, sizeof (cols));
394 /* image->assembly->image is the manifest module */
395 image = image->assembly->image;
396 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
399 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
400 token = table->next_idx ++;
402 alloc_table (table, table->rows);
403 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
404 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
405 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
406 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
407 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
408 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
409 values [MONO_ASSEMBLYREF_FLAGS] = 0;
410 values [MONO_ASSEMBLYREF_CULTURE] = 0;
411 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
413 if (strcmp ("", image->assembly->aname.culture)) {
414 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
415 image->assembly->aname.culture);
418 if ((pubkey = mono_image_get_public_key (image, &publen))) {
421 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
422 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
424 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
426 token <<= MONO_RESOLUTION_SCOPE_BITS;
427 token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
428 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
432 #ifndef DISABLE_REFLECTION_EMIT
434 mono_reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error)
436 MONO_REQ_GC_UNSAFE_MODE;
438 mono_error_init (error);
439 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
441 rmb->ilgen = mb->ilgen;
442 rmb->rtype = (MonoReflectionType*)mb->rtype;
443 return_val_if_nok (error, FALSE);
444 rmb->parameters = mb->parameters;
445 rmb->generic_params = mb->generic_params;
446 rmb->generic_container = mb->generic_container;
447 rmb->opt_types = NULL;
448 rmb->pinfo = mb->pinfo;
449 rmb->attrs = mb->attrs;
450 rmb->iattrs = mb->iattrs;
451 rmb->call_conv = mb->call_conv;
452 rmb->code = mb->code;
453 rmb->type = mb->type;
454 rmb->name = mb->name;
455 rmb->table_idx = &mb->table_idx;
456 rmb->init_locals = mb->init_locals;
457 rmb->skip_visibility = FALSE;
458 rmb->return_modreq = mb->return_modreq;
459 rmb->return_modopt = mb->return_modopt;
460 rmb->param_modreq = mb->param_modreq;
461 rmb->param_modopt = mb->param_modopt;
462 rmb->permissions = mb->permissions;
463 rmb->mhandle = mb->mhandle;
468 rmb->charset = mb->charset;
469 rmb->extra_flags = mb->extra_flags;
470 rmb->native_cc = mb->native_cc;
471 rmb->dllentry = mb->dllentry;
479 mono_reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error)
481 MONO_REQ_GC_UNSAFE_MODE;
483 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
485 mono_error_init (error);
487 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
489 rmb->ilgen = mb->ilgen;
490 rmb->rtype = mono_type_get_object_checked (mono_domain_get (), &mono_defaults.void_class->byval_arg, error);
491 return_val_if_nok (error, FALSE);
492 rmb->parameters = mb->parameters;
493 rmb->generic_params = NULL;
494 rmb->generic_container = NULL;
495 rmb->opt_types = NULL;
496 rmb->pinfo = mb->pinfo;
497 rmb->attrs = mb->attrs;
498 rmb->iattrs = mb->iattrs;
499 rmb->call_conv = mb->call_conv;
501 rmb->type = mb->type;
502 rmb->name = mono_string_new (mono_domain_get (), name);
503 rmb->table_idx = &mb->table_idx;
504 rmb->init_locals = mb->init_locals;
505 rmb->skip_visibility = FALSE;
506 rmb->return_modreq = NULL;
507 rmb->return_modopt = NULL;
508 rmb->param_modreq = mb->param_modreq;
509 rmb->param_modopt = mb->param_modopt;
510 rmb->permissions = mb->permissions;
511 rmb->mhandle = mb->mhandle;
519 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
521 MONO_REQ_GC_UNSAFE_MODE;
523 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
525 rmb->ilgen = mb->ilgen;
526 rmb->rtype = mb->rtype;
527 rmb->parameters = mb->parameters;
528 rmb->generic_params = NULL;
529 rmb->generic_container = NULL;
530 rmb->opt_types = NULL;
532 rmb->attrs = mb->attrs;
534 rmb->call_conv = mb->call_conv;
536 rmb->type = (MonoObject *) mb->owner;
537 rmb->name = mb->name;
538 rmb->table_idx = NULL;
539 rmb->init_locals = mb->init_locals;
540 rmb->skip_visibility = mb->skip_visibility;
541 rmb->return_modreq = NULL;
542 rmb->return_modopt = NULL;
543 rmb->param_modreq = NULL;
544 rmb->param_modopt = NULL;
545 rmb->permissions = NULL;
546 rmb->mhandle = mb->mhandle;
550 #else /* DISABLE_REFLECTION_EMIT */
552 mono_reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error) {
553 g_assert_not_reached ();
557 mono_reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error)
559 g_assert_not_reached ();
562 #endif /* DISABLE_REFLECTION_EMIT */
564 #ifndef DISABLE_REFLECTION_EMIT
566 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
568 MONO_REQ_GC_NEUTRAL_MODE;
570 MonoDynamicTable *table;
572 guint32 token, pclass;
574 switch (parent & MONO_TYPEDEFORREF_MASK) {
575 case MONO_TYPEDEFORREF_TYPEREF:
576 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
578 case MONO_TYPEDEFORREF_TYPESPEC:
579 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
581 case MONO_TYPEDEFORREF_TYPEDEF:
582 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
585 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
588 /* extract the index */
589 parent >>= MONO_TYPEDEFORREF_BITS;
591 table = &assembly->tables [MONO_TABLE_MEMBERREF];
593 if (assembly->save) {
594 alloc_table (table, table->rows + 1);
595 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
596 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
597 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
598 values [MONO_MEMBERREF_SIGNATURE] = sig;
601 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
608 * Insert a memberef row into the metadata: the token that point to the memberref
609 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
610 * mono_image_get_fieldref_token()).
611 * The sig param is an index to an already built signature.
614 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
616 MONO_REQ_GC_NEUTRAL_MODE;
618 guint32 parent = mono_image_typedef_or_ref (assembly, type);
619 return mono_image_add_memberef_row (assembly, parent, name, sig);
624 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
626 MONO_REQ_GC_NEUTRAL_MODE;
629 MonoMethodSignature *sig;
631 create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
633 if (create_typespec) {
634 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
639 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
640 if (token && !create_typespec)
643 g_assert (!method->is_inflated);
646 * A methodref signature can't contain an unmanaged calling convention.
648 sig = mono_metadata_signature_dup (mono_method_signature (method));
649 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
650 sig->call_convention = MONO_CALL_DEFAULT;
651 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
652 method->name, mono_dynimage_encode_method_signature (assembly, sig));
654 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
657 if (create_typespec) {
658 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
659 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
660 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
662 if (assembly->save) {
665 alloc_table (table, table->rows + 1);
666 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
667 values [MONO_METHODSPEC_METHOD] = token;
668 values [MONO_METHODSPEC_SIGNATURE] = mono_dynimage_encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
671 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
673 /*methodspec and memberef tokens are diferent, */
674 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
681 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
682 const gchar *name, guint32 sig)
684 MonoDynamicTable *table;
688 table = &assembly->tables [MONO_TABLE_MEMBERREF];
690 if (assembly->save) {
691 alloc_table (table, table->rows + 1);
692 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
693 values [MONO_MEMBERREF_CLASS] = original;
694 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
695 values [MONO_MEMBERREF_SIGNATURE] = sig;
698 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
707 is_field_on_inst (MonoClassField *field)
709 return mono_class_is_ginst (field->parent) && mono_class_get_generic_class (field->parent)->is_dynamic;
712 #ifndef DISABLE_REFLECTION_EMIT
714 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
720 g_assert (field->parent);
722 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
726 if (mono_class_is_ginst (field->parent) && mono_class_get_generic_class (field->parent)->container_class && mono_class_get_generic_class (field->parent)->container_class->fields) {
727 int index = field - field->parent->fields;
728 type = mono_field_get_type (&mono_class_get_generic_class (field->parent)->container_class->fields [index]);
730 type = mono_field_get_type (field);
732 token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
733 mono_field_get_name (field),
734 mono_dynimage_encode_fieldref_signature (assembly, field->parent->image, type));
735 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
740 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
742 MonoDynamicTable *table;
744 guint32 token, mtoken = 0, sig;
745 MonoMethodInflated *imethod;
746 MonoMethod *declaring;
748 table = &assembly->tables [MONO_TABLE_METHODSPEC];
750 g_assert (method->is_inflated);
751 imethod = (MonoMethodInflated *) method;
752 declaring = imethod->declaring;
754 sig = mono_dynimage_encode_method_signature (assembly, mono_method_signature (declaring));
755 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
757 if (!mono_method_signature (declaring)->generic_param_count)
760 switch (mono_metadata_token_table (mtoken)) {
761 case MONO_TABLE_MEMBERREF:
762 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
764 case MONO_TABLE_METHOD:
765 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
768 g_assert_not_reached ();
771 sig = mono_dynimage_encode_generic_method_sig (assembly, mono_method_get_context (method));
773 if (assembly->save) {
774 alloc_table (table, table->rows + 1);
775 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
776 values [MONO_METHODSPEC_METHOD] = mtoken;
777 values [MONO_METHODSPEC_SIGNATURE] = sig;
780 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
787 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
789 MonoMethodInflated *imethod;
792 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
796 g_assert (method->is_inflated);
797 imethod = (MonoMethodInflated *) method;
799 if (mono_method_signature (imethod->declaring)->generic_param_count) {
800 token = method_encode_methodspec (assembly, method);
802 guint32 sig = mono_dynimage_encode_method_signature (
803 assembly, mono_method_signature (imethod->declaring));
804 token = mono_image_get_memberref_token (
805 assembly, &method->klass->byval_arg, method->name, sig);
808 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
813 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
815 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
818 sig = mono_dynimage_encode_method_signature (assembly, mono_method_signature (imethod->declaring));
819 token = mono_image_get_memberref_token (
820 assembly, &m->klass->byval_arg, m->name, sig);
826 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error)
829 MonoDynamicTable *table;
832 mono_error_init (error);
834 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
835 idx = table->next_idx ++;
837 alloc_table (table, table->rows);
838 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
840 values [MONO_STAND_ALONE_SIGNATURE] =
841 mono_dynimage_encode_reflection_sighelper (assembly, helper, error);
842 return_val_if_nok (error, 0);
848 reflection_cc_to_file (int call_conv) {
849 switch (call_conv & 0x3) {
851 case 1: return MONO_CALL_DEFAULT;
852 case 2: return MONO_CALL_VARARG;
854 g_assert_not_reached ();
858 #endif /* !DISABLE_REFLECTION_EMIT */
860 struct _ArrayMethod {
862 MonoMethodSignature *sig;
868 mono_sre_array_method_free (ArrayMethod *am)
875 #ifndef DISABLE_REFLECTION_EMIT
877 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m, MonoError *error)
882 MonoMethodSignature *sig;
883 ArrayMethod *am = NULL;
886 mono_error_init (error);
888 nparams = mono_array_length (m->parameters);
889 sig = (MonoMethodSignature *)g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
891 sig->sentinelpos = -1;
892 sig->call_convention = reflection_cc_to_file (m->call_conv);
893 sig->param_count = nparams;
895 sig->ret = mono_reflection_type_get_handle (m->ret, error);
899 sig->ret = &mono_defaults.void_class->byval_arg;
901 mtype = mono_reflection_type_get_handle (m->parent, error);
905 for (i = 0; i < nparams; ++i) {
906 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i, error);
911 name = mono_string_to_utf8_checked (m->name, error);
914 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
915 am = (ArrayMethod *)tmp->data;
916 if (strcmp (name, am->name) == 0 &&
917 mono_metadata_type_equal (am->parent, mtype) &&
918 mono_metadata_signature_equal (am->sig, sig)) {
921 m->table_idx = am->token & 0xffffff;
925 am = g_new0 (ArrayMethod, 1);
929 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
930 mono_dynimage_encode_method_signature (assembly, sig));
931 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
932 m->table_idx = am->token & 0xffffff;
943 #ifndef DISABLE_REFLECTION_EMIT
946 * mono_image_insert_string:
947 * @module: module builder object
950 * Insert @str into the user string stream of @module.
953 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
955 MonoDynamicImage *assembly;
960 if (!module->dynamic_image)
961 mono_image_module_basic_init (module);
963 assembly = module->dynamic_image;
965 if (assembly->save) {
966 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
967 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
968 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
970 char *swapped = g_malloc (2 * mono_string_length (str));
971 const char *p = (const char*)mono_string_chars (str);
973 swap_with_size (swapped, p, 2, mono_string_length (str));
974 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
978 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
980 mono_image_add_stream_data (&assembly->us, "", 1);
982 idx = assembly->us.index ++;
985 mono_dynamic_image_register_token (assembly, MONO_TOKEN_STRING | idx, (MonoObject*)str);
987 return MONO_TOKEN_STRING | idx;
991 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
995 MonoMethodSignature *sig;
997 mono_error_init (error);
999 klass = obj->vtable->klass;
1000 if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
1001 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
1002 MonoMethodSignature *old;
1003 guint32 sig_token, parent;
1006 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
1008 nargs = mono_array_length (opt_param_types);
1009 old = mono_method_signature (method);
1010 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
1012 sig->hasthis = old->hasthis;
1013 sig->explicit_this = old->explicit_this;
1014 sig->call_convention = old->call_convention;
1015 sig->generic_param_count = old->generic_param_count;
1016 sig->param_count = old->param_count + nargs;
1017 sig->sentinelpos = old->param_count;
1018 sig->ret = old->ret;
1020 for (i = 0; i < old->param_count; i++)
1021 sig->params [i] = old->params [i];
1023 for (i = 0; i < nargs; i++) {
1024 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
1025 sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt, error);
1026 if (!is_ok (error)) goto fail;
1029 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
1030 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
1031 parent >>= MONO_TYPEDEFORREF_BITS;
1033 parent <<= MONO_MEMBERREF_PARENT_BITS;
1034 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
1036 sig_token = mono_dynimage_encode_method_signature (assembly, sig);
1037 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
1038 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
1039 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
1040 ReflectionMethodBuilder rmb;
1041 guint32 parent, sig_token;
1042 int nopt_args, nparams, ngparams, i;
1044 if (!mono_reflection_methodbuilder_from_method_builder (&rmb, mb, error))
1047 rmb.opt_types = opt_param_types;
1048 nopt_args = mono_array_length (opt_param_types);
1050 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
1051 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
1052 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
1054 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
1055 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
1056 sig->call_convention = rmb.call_conv;
1057 sig->generic_param_count = ngparams;
1058 sig->param_count = nparams + nopt_args;
1059 sig->sentinelpos = nparams;
1060 sig->ret = mono_reflection_type_get_handle (rmb.rtype, error);
1061 if (!is_ok (error)) goto fail;
1063 for (i = 0; i < nparams; i++) {
1064 MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
1065 sig->params [i] = mono_reflection_type_get_handle (rt, error);
1066 if (!is_ok (error)) goto fail;
1069 for (i = 0; i < nopt_args; i++) {
1070 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
1071 sig->params [nparams + i] = mono_reflection_type_get_handle (rt, error);
1072 if (!is_ok (error)) goto fail;
1075 // FIXME: This doesn't work, we don't use 'sig' for anything
1076 // The token fixup doesn't work either
1077 g_assert_not_reached ();
1079 sig_token = mono_dynimage_encode_method_builder_signature (assembly, &rmb, error);
1083 parent = mono_image_create_token (assembly, obj, TRUE, TRUE, error);
1084 if (!mono_error_ok (error))
1086 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
1088 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
1089 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
1091 char *name = mono_string_to_utf8_checked (rmb.name, error);
1092 if (!is_ok (error)) goto fail;
1093 token = mono_image_get_varargs_method_token (
1094 assembly, parent, name, sig_token);
1097 g_error ("requested method token for %s\n", klass->name);
1100 g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
1101 mono_dynamic_image_register_token (assembly, token, obj);
1104 g_assert (!mono_error_ok (error));
1109 * mono_image_create_token:
1110 * @assembly: a dynamic assembly
1112 * @register_token: Whenever to register the token in the assembly->tokens hash.
1114 * Get a token to insert in the IL code stream for the given MemberInfo.
1115 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
1116 * the table_idx-es were recomputed, so registering the token would overwrite an existing
1120 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
1121 gboolean create_open_instance, gboolean register_token,
1127 mono_error_init (error);
1129 klass = obj->vtable->klass;
1131 /* Check for user defined reflection objects */
1132 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
1133 if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0)) {
1134 mono_error_set_not_supported (error, "User defined subclasses of System.Type are not yet supported");
1138 if (strcmp (klass->name, "RuntimeType") == 0) {
1139 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
1140 return_val_if_nok (error, 0);
1141 MonoClass *mc = mono_class_from_mono_type (type);
1142 token = mono_metadata_token_from_dor (
1143 mono_dynimage_encode_typedef_or_ref_full (assembly, type, !mono_class_is_gtd (mc) || create_open_instance));
1144 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
1145 strcmp (klass->name, "MonoMethod") == 0) {
1146 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
1147 if (m->method->is_inflated) {
1148 if (create_open_instance)
1149 token = mono_image_get_methodspec_token (assembly, m->method);
1151 token = mono_image_get_inflated_method_token (assembly, m->method);
1152 } else if ((m->method->klass->image == &assembly->image) &&
1153 !mono_class_is_ginst (m->method->klass)) {
1154 static guint32 method_table_idx = 0xffffff;
1155 if (m->method->klass->wastypebuilder) {
1156 /* we use the same token as the one that was assigned
1157 * to the Methodbuilder.
1158 * FIXME: do the equivalent for Fields.
1160 token = m->method->token;
1163 * Each token should have a unique index, but the indexes are
1164 * assigned by managed code, so we don't know about them. An
1165 * easy solution is to count backwards...
1167 method_table_idx --;
1168 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
1171 token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
1173 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
1174 } else if (strcmp (klass->name, "MonoField") == 0) {
1175 MonoReflectionField *f = (MonoReflectionField *)obj;
1176 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
1177 static guint32 field_table_idx = 0xffffff;
1179 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
1181 token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
1183 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
1184 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
1185 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
1186 token = mono_image_get_array_token (assembly, m, error);
1187 return_val_if_nok (error, 0);
1188 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
1189 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
1190 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s, error);
1191 return_val_if_nok (error, 0);
1192 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
1193 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
1194 return_val_if_nok (error, 0);
1195 token = mono_metadata_token_from_dor (
1196 mono_image_typedef_or_ref (assembly, type));
1198 g_error ("requested token for %s\n", klass->name);
1202 mono_image_register_token (assembly, token, obj);
1210 #ifndef DISABLE_REFLECTION_EMIT
1213 * mono_reflection_dynimage_basic_init:
1214 * @assembly: an assembly builder object
1216 * Create the MonoImage that represents the assembly builder and setup some
1217 * of the helper hash table and the basic metadata streams.
1220 mono_reflection_dynimage_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
1223 MonoDynamicAssembly *assembly;
1224 MonoDynamicImage *image;
1225 MonoDomain *domain = mono_object_domain (assemblyb);
1227 if (assemblyb->dynamic_assembly)
1231 /* assembly->assembly.image might be GC allocated */
1232 assembly = assemblyb->dynamic_assembly = (MonoDynamicAssembly *)GC_MALLOC (sizeof (MonoDynamicAssembly));
1234 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
1237 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
1239 assembly->assembly.ref_count = 1;
1240 assembly->assembly.dynamic = TRUE;
1241 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
1242 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
1243 assembly->assembly.basedir = mono_string_to_utf8_checked (assemblyb->dir, &error);
1244 if (mono_error_set_pending_exception (&error))
1246 if (assemblyb->culture) {
1247 assembly->assembly.aname.culture = mono_string_to_utf8_checked (assemblyb->culture, &error);
1248 if (mono_error_set_pending_exception (&error))
1251 assembly->assembly.aname.culture = g_strdup ("");
1253 if (assemblyb->version) {
1254 char *vstr = mono_string_to_utf8_checked (assemblyb->version, &error);
1255 if (mono_error_set_pending_exception (&error))
1257 char **version = g_strsplit (vstr, ".", 4);
1258 char **parts = version;
1259 assembly->assembly.aname.major = atoi (*parts++);
1260 assembly->assembly.aname.minor = atoi (*parts++);
1261 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
1262 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
1264 g_strfreev (version);
1267 assembly->assembly.aname.major = 0;
1268 assembly->assembly.aname.minor = 0;
1269 assembly->assembly.aname.build = 0;
1270 assembly->assembly.aname.revision = 0;
1273 assembly->run = assemblyb->access != 2;
1274 assembly->save = assemblyb->access != 1;
1275 assembly->domain = domain;
1277 char *assembly_name = mono_string_to_utf8_checked (assemblyb->name, &error);
1278 if (mono_error_set_pending_exception (&error))
1280 image = mono_dynamic_image_create (assembly, assembly_name, g_strdup ("RefEmit_YouForgotToDefineAModule"));
1281 image->initial_image = TRUE;
1282 assembly->assembly.aname.name = image->image.name;
1283 assembly->assembly.image = &image->image;
1284 if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
1285 /* -1 to correct for the trailing NULL byte */
1286 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
1287 g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
1289 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);
1292 mono_domain_assemblies_lock (domain);
1293 domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
1294 mono_domain_assemblies_unlock (domain);
1296 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
1298 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
1300 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
1303 #endif /* !DISABLE_REFLECTION_EMIT */
1305 #ifndef DISABLE_REFLECTION_EMIT
1307 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
1309 return CACHE_OBJECT (MonoReflectionAssembly *, assembly, &res->object, NULL);
1313 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
1315 return CACHE_OBJECT (MonoReflectionModuleBuilder *, module, &res->module.obj, NULL);
1319 image_module_basic_init (MonoReflectionModuleBuilder *moduleb, MonoError *error)
1321 MonoDynamicImage *image = moduleb->dynamic_image;
1322 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
1323 mono_error_init (error);
1326 MonoImage **new_modules;
1328 char *name, *fqname;
1330 * FIXME: we already created an image in mono_reflection_dynimage_basic_init (), but
1331 * we don't know which module it belongs to, since that is only
1332 * determined at assembly save time.
1334 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
1335 name = mono_string_to_utf8_checked (ab->name, error);
1336 return_val_if_nok (error, FALSE);
1337 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, error);
1338 if (!is_ok (error)) {
1342 image = mono_dynamic_image_create (ab->dynamic_assembly, name, fqname);
1344 moduleb->module.image = &image->image;
1345 moduleb->dynamic_image = image;
1346 register_module (mono_object_domain (moduleb), moduleb, image);
1348 /* register the module with the assembly */
1349 ass = ab->dynamic_assembly->assembly.image;
1350 module_count = ass->module_count;
1351 new_modules = g_new0 (MonoImage *, module_count + 1);
1354 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
1355 new_modules [module_count] = &image->image;
1356 mono_image_addref (&image->image);
1358 g_free (ass->modules);
1359 ass->modules = new_modules;
1360 ass->module_count ++;
1366 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
1369 (void) image_module_basic_init (moduleb, &error);
1370 mono_error_set_pending_exception (&error);
1376 is_corlib_type (MonoClass *klass)
1378 return klass->image == mono_defaults.corlib;
1381 #define check_corlib_type_cached(_class, _namespace, _name) do { \
1382 static MonoClass *cached_class; \
1384 return cached_class == _class; \
1385 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
1386 cached_class = _class; \
1394 #ifndef DISABLE_REFLECTION_EMIT
1396 is_sre_array (MonoClass *klass)
1398 check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
1402 is_sre_byref (MonoClass *klass)
1404 check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
1408 is_sre_pointer (MonoClass *klass)
1410 check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
1414 is_sre_generic_instance (MonoClass *klass)
1416 check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilderInstantiation");
1420 is_sre_type_builder (MonoClass *klass)
1422 check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
1426 is_sre_method_builder (MonoClass *klass)
1428 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
1432 mono_is_sre_ctor_builder (MonoClass *klass)
1434 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
1438 is_sre_field_builder (MonoClass *klass)
1440 check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
1444 is_sre_gparam_builder (MonoClass *klass)
1446 check_corlib_type_cached (klass, "System.Reflection.Emit", "GenericTypeParameterBuilder");
1450 is_sre_enum_builder (MonoClass *klass)
1452 check_corlib_type_cached (klass, "System.Reflection.Emit", "EnumBuilder");
1456 mono_is_sre_method_on_tb_inst (MonoClass *klass)
1458 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
1462 mono_is_sre_ctor_on_tb_inst (MonoClass *klass)
1464 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
1467 static MonoReflectionType*
1468 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error)
1470 static MonoMethod *method_get_underlying_system_type = NULL;
1471 MonoReflectionType *rt;
1472 MonoMethod *usertype_method;
1474 mono_error_init (error);
1476 if (!method_get_underlying_system_type)
1477 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
1479 usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
1481 rt = (MonoReflectionType *) mono_runtime_invoke_checked (usertype_method, t, NULL, error);
1487 mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
1490 mono_error_init (error);
1497 if (mono_reflection_is_usertype (ref)) {
1498 ref = mono_reflection_type_get_underlying_system_type (ref, error);
1499 if (ref == NULL || mono_reflection_is_usertype (ref) || !is_ok (error))
1505 klass = mono_object_class (ref);
1507 if (is_sre_array (klass)) {
1509 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
1510 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type, error);
1511 return_val_if_nok (error, NULL);
1513 if (sre_array->rank == 0) //single dimentional array
1514 res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
1516 res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
1517 sre_array->type.type = res;
1519 } else if (is_sre_byref (klass)) {
1521 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
1522 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type, error);
1523 return_val_if_nok (error, NULL);
1525 res = &mono_class_from_mono_type (base)->this_arg;
1526 sre_byref->type.type = res;
1528 } else if (is_sre_pointer (klass)) {
1530 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
1531 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type, error);
1532 return_val_if_nok (error, NULL);
1534 res = &mono_ptr_class_get (base)->byval_arg;
1535 sre_pointer->type.type = res;
1537 } else if (is_sre_generic_instance (klass)) {
1538 MonoType *res, **types;
1539 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
1542 count = mono_array_length (gclass->type_arguments);
1543 types = g_new0 (MonoType*, count);
1544 for (i = 0; i < count; ++i) {
1545 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (gclass->type_arguments, gpointer, i);
1546 types [i] = mono_reflection_type_get_handle (t, error);
1547 if (!types[i] || !is_ok (error)) {
1552 /* Need to resolve the generic_type in order for it to create its generic context. */
1553 MonoType *gtd = mono_reflection_type_get_handle (gclass->generic_type, error);
1554 if (!is_ok (error)) {
1558 MonoClass *gtd_klass = mono_class_from_mono_type (gtd);
1559 if (is_sre_type_builder (mono_object_class (gclass->generic_type))) {
1560 reflection_create_generic_class ((MonoReflectionTypeBuilder*)gclass->generic_type, error);
1561 if (!is_ok (error)) {
1566 g_assert (count == 0 || mono_class_is_gtd (gtd_klass));
1567 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types, error);
1570 gclass->type.type = res;
1572 } else if (is_sre_gparam_builder (klass)) {
1573 MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)ref;
1574 MonoGenericParamFull *param;
1578 image = &gparam->tbuilder->module->dynamic_image->image;
1580 param = mono_image_new0 (image, MonoGenericParamFull, 1);
1582 param->info.name = mono_string_to_utf8_image (image, gparam->name, error);
1583 mono_error_assert_ok (error);
1584 param->param.num = gparam->index;
1586 if (gparam->mbuilder) {
1587 if (!gparam->mbuilder->generic_container) {
1588 gparam->mbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (image, sizeof (MonoGenericContainer));
1589 gparam->mbuilder->generic_container->is_method = TRUE;
1591 * Cannot set owner.method, since the MonoMethod is not created yet.
1592 * Set the image field instead, so type_in_image () works.
1594 gparam->mbuilder->generic_container->is_anonymous = TRUE;
1595 gparam->mbuilder->generic_container->owner.image = image;
1597 param->param.owner = gparam->mbuilder->generic_container;
1598 } else if (gparam->tbuilder) {
1599 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)(gparam->tbuilder), error);
1600 mono_error_assert_ok (error);
1601 MonoClass *owner = mono_class_from_mono_type (type);
1602 g_assert (mono_class_is_gtd (owner));
1603 param->param.owner = mono_class_get_generic_container (owner);
1606 pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
1608 gparam->type.type = &pklass->byval_arg;
1610 mono_class_set_ref_info (pklass, gparam);
1611 mono_image_append_class_to_reflection_info_set (pklass);
1613 return &pklass->byval_arg;
1614 } else if (is_sre_enum_builder (klass)) {
1615 MonoReflectionEnumBuilder *ebuilder = (MonoReflectionEnumBuilder *)ref;
1617 return mono_reflection_type_get_handle ((MonoReflectionType*)ebuilder->tb, error);
1618 } else if (is_sre_type_builder (klass)) {
1619 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)ref;
1621 /* This happens when a finished type references an unfinished one. Have to create the minimal type */
1622 reflection_setup_internal_class (tb, error);
1623 mono_error_assert_ok (error);
1624 g_assert (ref->type);
1628 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
1633 * LOCKING: Assumes the loader lock is held.
1635 static MonoMethodSignature*
1636 parameters_to_signature (MonoImage *image, MonoArray *parameters, MonoError *error) {
1637 MonoMethodSignature *sig;
1640 mono_error_init (error);
1642 count = parameters? mono_array_length (parameters): 0;
1644 sig = (MonoMethodSignature *)mono_image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
1645 sig->param_count = count;
1646 sig->sentinelpos = -1; /* FIXME */
1647 for (i = 0; i < count; ++i) {
1648 sig->params [i] = mono_type_array_get_and_resolve (parameters, i, error);
1649 if (!is_ok (error)) {
1650 image_g_free (image, sig);
1658 * LOCKING: Assumes the loader lock is held.
1660 static MonoMethodSignature*
1661 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor, MonoError *error) {
1662 MonoMethodSignature *sig;
1664 mono_error_init (error);
1666 sig = parameters_to_signature (image, ctor->parameters, error);
1667 return_val_if_nok (error, NULL);
1668 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
1669 sig->ret = &mono_defaults.void_class->byval_arg;
1674 * LOCKING: Assumes the loader lock is held.
1676 static MonoMethodSignature*
1677 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method, MonoError *error) {
1678 MonoMethodSignature *sig;
1680 mono_error_init (error);
1682 sig = parameters_to_signature (image, method->parameters, error);
1683 return_val_if_nok (error, NULL);
1684 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
1685 if (method->rtype) {
1686 sig->ret = mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype, error);
1687 if (!is_ok (error)) {
1688 image_g_free (image, sig);
1692 sig->ret = &mono_defaults.void_class->byval_arg;
1694 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
1698 static MonoMethodSignature*
1699 dynamic_method_to_signature (MonoReflectionDynamicMethod *method, MonoError *error) {
1700 MonoMethodSignature *sig;
1702 mono_error_init (error);
1704 sig = parameters_to_signature (NULL, method->parameters, error);
1705 return_val_if_nok (error, NULL);
1706 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
1707 if (method->rtype) {
1708 sig->ret = mono_reflection_type_get_handle (method->rtype, error);
1709 if (!is_ok (error)) {
1714 sig->ret = &mono_defaults.void_class->byval_arg;
1716 sig->generic_param_count = 0;
1721 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type, MonoError *error)
1723 mono_error_init (error);
1724 MonoClass *klass = mono_object_class (prop);
1725 if (strcmp (klass->name, "PropertyBuilder") == 0) {
1726 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
1727 *name = mono_string_to_utf8_checked (pb->name, error);
1728 return_if_nok (error);
1729 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type, error);
1731 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
1732 *name = g_strdup (p->property->name);
1733 if (p->property->get)
1734 *type = mono_method_signature (p->property->get)->ret;
1736 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
1741 get_field_name_and_type (MonoObject *field, char **name, MonoType **type, MonoError *error)
1743 mono_error_init (error);
1744 MonoClass *klass = mono_object_class (field);
1745 if (strcmp (klass->name, "FieldBuilder") == 0) {
1746 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
1747 *name = mono_string_to_utf8_checked (fb->name, error);
1748 return_if_nok (error);
1749 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
1751 MonoReflectionField *f = (MonoReflectionField *)field;
1752 *name = g_strdup (mono_field_get_name (f->field));
1753 *type = f->field->type;
1757 #else /* DISABLE_REFLECTION_EMIT */
1760 is_sre_type_builder (MonoClass *klass)
1766 is_sre_generic_instance (MonoClass *klass)
1772 mono_is_sre_ctor_builder (MonoClass *klass)
1778 mono_is_sre_method_on_tb_inst (MonoClass *klass)
1784 mono_is_sre_ctor_on_tb_inst (MonoClass *klass)
1789 #endif /* !DISABLE_REFLECTION_EMIT */
1793 is_sr_mono_field (MonoClass *klass)
1795 check_corlib_type_cached (klass, "System.Reflection", "MonoField");
1799 mono_is_sr_mono_property (MonoClass *klass)
1801 check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
1805 is_sr_mono_method (MonoClass *klass)
1807 check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
1811 mono_is_sr_mono_cmethod (MonoClass *klass)
1813 check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
1817 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
1819 return is_sr_mono_method (klass) || mono_is_sr_mono_cmethod (klass);
1823 mono_is_sre_type_builder (MonoClass *klass)
1825 return is_sre_type_builder (klass);
1829 mono_is_sre_generic_instance (MonoClass *klass)
1831 return is_sre_generic_instance (klass);
1837 * encode_cattr_value:
1838 * Encode a value in a custom attribute stream of bytes.
1839 * The value to encode is either supplied as an object in argument val
1840 * (valuetypes are boxed), or as a pointer to the data in the
1842 * @type represents the type of the value
1843 * @buffer is the start of the buffer
1844 * @p the current position in the buffer
1845 * @buflen contains the size of the buffer and is used to return the new buffer size
1846 * if this needs to be realloced.
1847 * @retbuffer and @retp return the start and the position of the buffer
1848 * @error set on error.
1851 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval, MonoError *error)
1853 MonoTypeEnum simple_type;
1855 mono_error_init (error);
1856 if ((p-buffer) + 10 >= *buflen) {
1859 newbuf = (char *)g_realloc (buffer, *buflen);
1860 p = newbuf + (p-buffer);
1864 argval = ((char*)arg + sizeof (MonoObject));
1865 simple_type = type->type;
1867 switch (simple_type) {
1868 case MONO_TYPE_BOOLEAN:
1873 case MONO_TYPE_CHAR:
1876 swap_with_size (p, argval, 2, 1);
1882 swap_with_size (p, argval, 4, 1);
1886 swap_with_size (p, argval, 8, 1);
1891 swap_with_size (p, argval, 8, 1);
1894 case MONO_TYPE_VALUETYPE:
1895 if (type->data.klass->enumtype) {
1896 simple_type = mono_class_enum_basetype (type->data.klass)->type;
1899 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
1902 case MONO_TYPE_STRING: {
1909 str = mono_string_to_utf8_checked ((MonoString*)arg, error);
1910 return_if_nok (error);
1911 slen = strlen (str);
1912 if ((p-buffer) + 10 + slen >= *buflen) {
1916 newbuf = (char *)g_realloc (buffer, *buflen);
1917 p = newbuf + (p-buffer);
1920 mono_metadata_encode_value (slen, p, &p);
1921 memcpy (p, str, slen);
1926 case MONO_TYPE_CLASS: {
1935 arg_type = mono_reflection_type_get_handle ((MonoReflectionType*)arg, error);
1936 return_if_nok (error);
1938 str = type_get_qualified_name (arg_type, NULL);
1939 slen = strlen (str);
1940 if ((p-buffer) + 10 + slen >= *buflen) {
1944 newbuf = (char *)g_realloc (buffer, *buflen);
1945 p = newbuf + (p-buffer);
1948 mono_metadata_encode_value (slen, p, &p);
1949 memcpy (p, str, slen);
1954 case MONO_TYPE_SZARRAY: {
1956 MonoClass *eclass, *arg_eclass;
1959 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
1962 len = mono_array_length ((MonoArray*)arg);
1964 *p++ = (len >> 8) & 0xff;
1965 *p++ = (len >> 16) & 0xff;
1966 *p++ = (len >> 24) & 0xff;
1968 *retbuffer = buffer;
1969 eclass = type->data.klass;
1970 arg_eclass = mono_object_class (arg)->element_class;
1973 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
1974 eclass = mono_defaults.object_class;
1976 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
1977 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
1978 int elsize = mono_class_array_element_size (arg_eclass);
1979 for (i = 0; i < len; ++i) {
1980 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr, error);
1981 return_if_nok (error);
1984 } else if (eclass->valuetype && arg_eclass->valuetype) {
1985 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
1986 int elsize = mono_class_array_element_size (eclass);
1987 for (i = 0; i < len; ++i) {
1988 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr, error);
1989 return_if_nok (error);
1993 for (i = 0; i < len; ++i) {
1994 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL, error);
1995 return_if_nok (error);
2000 case MONO_TYPE_OBJECT: {
2006 * The parameter type is 'object' but the type of the actual
2007 * argument is not. So we have to add type information to the blob
2008 * too. This is completely undocumented in the spec.
2012 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
2017 klass = mono_object_class (arg);
2019 if (mono_object_isinst_checked (arg, mono_defaults.systemtype_class, error)) {
2023 return_if_nok (error);
2026 if (klass->enumtype) {
2028 } else if (klass == mono_defaults.string_class) {
2029 simple_type = MONO_TYPE_STRING;
2032 } else if (klass->rank == 1) {
2034 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
2035 /* See Partition II, Appendix B3 */
2038 *p++ = klass->element_class->byval_arg.type;
2039 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL, error);
2040 return_if_nok (error);
2042 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
2043 *p++ = simple_type = klass->byval_arg.type;
2046 g_error ("unhandled type in custom attr");
2048 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
2049 slen = strlen (str);
2050 if ((p-buffer) + 10 + slen >= *buflen) {
2054 newbuf = (char *)g_realloc (buffer, *buflen);
2055 p = newbuf + (p-buffer);
2058 mono_metadata_encode_value (slen, p, &p);
2059 memcpy (p, str, slen);
2062 simple_type = mono_class_enum_basetype (klass)->type;
2066 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
2069 *retbuffer = buffer;
2073 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
2075 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
2076 char *str = type_get_qualified_name (type, NULL);
2077 int slen = strlen (str);
2081 * This seems to be optional...
2084 mono_metadata_encode_value (slen, p, &p);
2085 memcpy (p, str, slen);
2088 } else if (type->type == MONO_TYPE_OBJECT) {
2090 } else if (type->type == MONO_TYPE_CLASS) {
2091 /* it should be a type: encode_cattr_value () has the check */
2094 mono_metadata_encode_value (type->type, p, &p);
2095 if (type->type == MONO_TYPE_SZARRAY)
2096 /* See the examples in Partition VI, Annex B */
2097 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
2103 #ifndef DISABLE_REFLECTION_EMIT
2105 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value, MonoError *error)
2109 mono_error_init (error);
2111 /* Preallocate a large enough buffer */
2112 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
2113 char *str = type_get_qualified_name (type, NULL);
2116 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
2117 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
2123 len += strlen (name);
2125 if ((p-buffer) + 20 + len >= *buflen) {
2129 newbuf = (char *)g_realloc (buffer, *buflen);
2130 p = newbuf + (p-buffer);
2134 encode_field_or_prop_type (type, p, &p);
2136 len = strlen (name);
2137 mono_metadata_encode_value (len, p, &p);
2138 memcpy (p, name, len);
2140 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL, error);
2141 return_if_nok (error);
2143 *retbuffer = buffer;
2147 * mono_reflection_get_custom_attrs_blob:
2148 * @ctor: custom attribute constructor
2149 * @ctorArgs: arguments o the constructor
2155 * Creates the blob of data that needs to be saved in the metadata and that represents
2156 * the custom attributed described by @ctor, @ctorArgs etc.
2157 * Returns: a Byte array representing the blob of data.
2160 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
2163 MonoArray *result = mono_reflection_get_custom_attrs_blob_checked (assembly, ctor, ctorArgs, properties, propValues, fields, fieldValues, &error);
2164 mono_error_cleanup (&error);
2169 * mono_reflection_get_custom_attrs_blob_checked:
2170 * @ctor: custom attribute constructor
2171 * @ctorArgs: arguments o the constructor
2176 * @error: set on error
2178 * Creates the blob of data that needs to be saved in the metadata and that represents
2179 * the custom attributed described by @ctor, @ctorArgs etc.
2180 * Returns: a Byte array representing the blob of data. On failure returns NULL and sets @error.
2183 mono_reflection_get_custom_attrs_blob_checked (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues, MonoError *error)
2185 MonoArray *result = NULL;
2186 MonoMethodSignature *sig;
2191 mono_error_init (error);
2193 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
2194 /* sig is freed later so allocate it in the heap */
2195 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor, error);
2196 if (!is_ok (error)) {
2201 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
2204 g_assert (mono_array_length (ctorArgs) == sig->param_count);
2206 p = buffer = (char *)g_malloc (buflen);
2207 /* write the prolog */
2210 for (i = 0; i < sig->param_count; ++i) {
2211 arg = mono_array_get (ctorArgs, MonoObject*, i);
2212 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL, error);
2213 if (!is_ok (error)) goto leave;
2217 i += mono_array_length (properties);
2219 i += mono_array_length (fields);
2221 *p++ = (i >> 8) & 0xff;
2224 for (i = 0; i < mono_array_length (properties); ++i) {
2228 prop = (MonoObject *)mono_array_get (properties, gpointer, i);
2229 get_prop_name_and_type (prop, &pname, &ptype, error);
2230 if (!is_ok (error)) goto leave;
2231 *p++ = 0x54; /* PROPERTY signature */
2232 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i), error);
2234 if (!is_ok (error)) goto leave;
2240 for (i = 0; i < mono_array_length (fields); ++i) {
2244 field = (MonoObject *)mono_array_get (fields, gpointer, i);
2245 get_field_name_and_type (field, &fname, &ftype, error);
2246 if (!is_ok (error)) goto leave;
2247 *p++ = 0x53; /* FIELD signature */
2248 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i), error);
2250 if (!is_ok (error)) goto leave;
2254 g_assert (p - buffer <= buflen);
2255 buflen = p - buffer;
2256 result = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, buflen, error);
2259 p = mono_array_addr (result, char, 0);
2260 memcpy (p, buffer, buflen);
2263 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
2269 * reflection_setup_internal_class:
2270 * @tb: a TypeBuilder object
2271 * @error: set on error
2273 * Creates a MonoClass that represents the TypeBuilder.
2274 * This is a trick that lets us simplify a lot of reflection code
2275 * (and will allow us to support Build and Run assemblies easier).
2277 * Returns TRUE on success. On failure, returns FALSE and sets @error.
2280 reflection_setup_internal_class (MonoReflectionTypeBuilder *tb, MonoError *error)
2282 MonoClass *klass, *parent;
2284 mono_error_init (error);
2286 mono_loader_lock ();
2289 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
2290 if (!is_ok (error)) {
2291 mono_loader_unlock ();
2294 /* check so we can compile corlib correctly */
2295 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
2296 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
2297 parent = parent_type->data.klass;
2299 parent = mono_class_from_mono_type (parent_type);
2305 /* the type has already being created: it means we just have to change the parent */
2306 if (tb->type.type) {
2307 klass = mono_class_from_mono_type (tb->type.type);
2308 klass->parent = NULL;
2309 /* fool mono_class_setup_parent */
2310 klass->supertypes = NULL;
2311 mono_class_setup_parent (klass, parent);
2312 mono_class_setup_mono_type (klass);
2313 mono_loader_unlock ();
2318 * The size calculation here warrants some explaining.
2319 * reflection_setup_internal_class is called too early, well before we know whether the type will be a GTD or DEF,
2320 * meaning we need to alloc enough space to morth a def into a gtd.
2322 klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, MAX (sizeof (MonoClassDef), sizeof (MonoClassGtd)));
2323 klass->class_kind = MONO_CLASS_DEF;
2325 klass->image = &tb->module->dynamic_image->image;
2327 klass->inited = 1; /* we lie to the runtime */
2328 klass->name = mono_string_to_utf8_image (klass->image, tb->name, error);
2331 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, error);
2334 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
2335 mono_class_set_flags (klass, tb->attrs);
2337 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
2339 klass->element_class = klass;
2341 if (mono_class_get_ref_info (klass) == NULL) {
2342 mono_class_set_ref_info (klass, tb);
2344 /* Put into cache so mono_class_get_checked () will find it.
2345 Skip nested types as those should not be available on the global scope. */
2346 if (!tb->nesting_type)
2347 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
2350 We must register all types as we cannot rely on the name_cache hashtable since we find the class
2351 by performing a mono_class_get which does the full resolution.
2353 Working around this semantics would require us to write a lot of code for no clear advantage.
2355 mono_image_append_class_to_reflection_info_set (klass);
2357 g_assert (mono_class_get_ref_info (klass) == tb);
2360 mono_dynamic_image_register_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
2362 if (parent != NULL) {
2363 mono_class_setup_parent (klass, parent);
2364 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
2365 const char *old_n = klass->name;
2366 /* trick to get relative numbering right when compiling corlib */
2367 klass->name = "BuildingObject";
2368 mono_class_setup_parent (klass, mono_defaults.object_class);
2369 klass->name = old_n;
2372 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
2373 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
2374 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
2375 klass->instance_size = sizeof (MonoObject);
2376 klass->size_inited = 1;
2377 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
2380 mono_class_setup_mono_type (klass);
2382 mono_class_setup_supertypes (klass);
2385 * FIXME: handle interfaces.
2388 tb->type.type = &klass->byval_arg;
2390 if (tb->nesting_type) {
2391 reflection_setup_internal_class ((MonoReflectionTypeBuilder*)tb->nesting_type, error);
2392 g_assert (tb->nesting_type->type);
2393 MonoType *nesting_type = mono_reflection_type_get_handle (tb->nesting_type, error);
2394 if (!is_ok (error)) goto failure;
2395 klass->nested_in = mono_class_from_mono_type (nesting_type);
2398 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
2400 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
2402 mono_loader_unlock ();
2406 mono_loader_unlock ();
2411 * reflection_create_generic_class:
2412 * @tb: a TypeBuilder object
2413 * @error: set on error
2415 * Creates the generic class after all generic parameters have been added.
2416 * On success returns TRUE, on failure returns FALSE and sets @error.
2419 reflection_create_generic_class (MonoReflectionTypeBuilder *tb, MonoError *error)
2424 mono_error_init (error);
2426 reflection_setup_internal_class (tb, error);
2427 return_val_if_nok (error, FALSE);
2429 klass = mono_class_from_mono_type (tb->type.type);
2431 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
2436 if (mono_class_try_get_generic_container (klass) != NULL)
2437 return TRUE; /* already setup */
2439 MonoGenericContainer *generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
2441 generic_container->owner.klass = klass;
2442 generic_container->type_argc = count;
2443 generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
2445 klass->class_kind = MONO_CLASS_GTD;
2446 mono_class_set_generic_container (klass, generic_container);
2449 for (i = 0; i < count; i++) {
2450 MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)mono_array_get (tb->generic_params, gpointer, i);
2451 MonoType *param_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, error);
2452 return_val_if_nok (error, FALSE);
2453 MonoGenericParamFull *param = (MonoGenericParamFull *) param_type->data.generic_param;
2454 generic_container->type_params [i] = *param;
2455 /*Make sure we are a diferent type instance */
2456 generic_container->type_params [i].param.owner = generic_container;
2457 generic_container->type_params [i].info.pklass = NULL;
2458 generic_container->type_params [i].info.flags = gparam->attrs;
2460 g_assert (generic_container->type_params [i].param.owner);
2463 generic_container->context.class_inst = mono_get_shared_generic_inst (generic_container);
2467 static MonoMarshalSpec*
2468 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
2469 MonoReflectionMarshal *minfo, MonoError *error)
2471 MonoMarshalSpec *res;
2473 mono_error_init (error);
2475 res = image_g_new0 (image, MonoMarshalSpec, 1);
2476 res->native = (MonoMarshalNative)minfo->type;
2478 switch (minfo->type) {
2479 case MONO_NATIVE_LPARRAY:
2480 res->data.array_data.elem_type = (MonoMarshalNative)minfo->eltype;
2481 if (minfo->has_size) {
2482 res->data.array_data.param_num = minfo->param_num;
2483 res->data.array_data.num_elem = minfo->count;
2484 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
2487 res->data.array_data.param_num = -1;
2488 res->data.array_data.num_elem = -1;
2489 res->data.array_data.elem_mult = -1;
2493 case MONO_NATIVE_BYVALTSTR:
2494 case MONO_NATIVE_BYVALARRAY:
2495 res->data.array_data.num_elem = minfo->count;
2498 case MONO_NATIVE_CUSTOM:
2499 if (minfo->marshaltyperef) {
2500 MonoType *marshaltyperef = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, error);
2501 if (!is_ok (error)) {
2502 image_g_free (image, res);
2505 res->data.custom_data.custom_name =
2506 type_get_fully_qualified_name (marshaltyperef);
2508 if (minfo->mcookie) {
2509 res->data.custom_data.cookie = mono_string_to_utf8_checked (minfo->mcookie, error);
2510 if (!is_ok (error)) {
2511 image_g_free (image, res);
2523 #endif /* !DISABLE_REFLECTION_EMIT */
2525 MonoReflectionMarshalAsAttribute*
2526 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
2527 MonoMarshalSpec *spec, MonoError *error)
2529 MonoReflectionType *rt;
2530 MonoReflectionMarshalAsAttribute *minfo;
2533 mono_error_init (error);
2535 minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new_checked (domain, mono_class_get_marshal_as_attribute_class (), error);
2538 minfo->utype = spec->native;
2540 switch (minfo->utype) {
2541 case MONO_NATIVE_LPARRAY:
2542 minfo->array_subtype = spec->data.array_data.elem_type;
2543 minfo->size_const = spec->data.array_data.num_elem;
2544 if (spec->data.array_data.param_num != -1)
2545 minfo->size_param_index = spec->data.array_data.param_num;
2548 case MONO_NATIVE_BYVALTSTR:
2549 case MONO_NATIVE_BYVALARRAY:
2550 minfo->size_const = spec->data.array_data.num_elem;
2553 case MONO_NATIVE_CUSTOM:
2554 if (spec->data.custom_data.custom_name) {
2555 mtype = mono_reflection_type_from_name_checked (spec->data.custom_data.custom_name, klass->image, error);
2556 return_val_if_nok (error, NULL);
2559 rt = mono_type_get_object_checked (domain, mtype, error);
2563 MONO_OBJECT_SETREF (minfo, marshal_type_ref, rt);
2566 MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
2568 if (spec->data.custom_data.cookie)
2569 MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
2579 #ifndef DISABLE_REFLECTION_EMIT
2581 reflection_methodbuilder_to_mono_method (MonoClass *klass,
2582 ReflectionMethodBuilder *rmb,
2583 MonoMethodSignature *sig,
2587 MonoMethodWrapper *wrapperm;
2588 MonoMarshalSpec **specs;
2589 MonoReflectionMethodAux *method_aux;
2594 mono_error_init (error);
2596 * Methods created using a MethodBuilder should have their memory allocated
2597 * inside the image mempool, while dynamic methods should have their memory
2600 dynamic = rmb->refs != NULL;
2601 image = dynamic ? NULL : klass->image;
2604 g_assert (!mono_class_is_ginst (klass));
2606 mono_loader_lock ();
2608 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
2609 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
2610 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
2612 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
2614 wrapperm = (MonoMethodWrapper*)m;
2616 m->dynamic = dynamic;
2618 m->flags = rmb->attrs;
2619 m->iflags = rmb->iattrs;
2620 m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
2623 m->sre_method = TRUE;
2624 m->skip_visibility = rmb->skip_visibility;
2626 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
2628 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
2629 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
2632 m->signature->pinvoke = 1;
2633 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
2634 m->signature->pinvoke = 1;
2636 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
2638 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, error) : image_strdup (image, m->name);
2639 mono_error_assert_ok (error);
2640 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, error);
2641 mono_error_assert_ok (error);
2643 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
2645 if (image_is_dynamic (klass->image))
2646 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
2648 mono_loader_unlock ();
2651 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
2652 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
2653 MonoMethodHeader *header;
2655 gint32 max_stack, i;
2656 gint32 num_locals = 0;
2657 gint32 num_clauses = 0;
2661 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
2662 code_size = rmb->ilgen->code_len;
2663 max_stack = rmb->ilgen->max_stack;
2664 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
2665 if (rmb->ilgen->ex_handlers)
2666 num_clauses = mono_reflection_method_count_clauses (rmb->ilgen);
2669 code = mono_array_addr (rmb->code, guint8, 0);
2670 code_size = mono_array_length (rmb->code);
2671 /* we probably need to run a verifier on the code... */
2681 header = (MonoMethodHeader *)mono_image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
2682 header->code_size = code_size;
2683 header->code = (const unsigned char *)image_g_malloc (image, code_size);
2684 memcpy ((char*)header->code, code, code_size);
2685 header->max_stack = max_stack;
2686 header->init_locals = rmb->init_locals;
2687 header->num_locals = num_locals;
2689 for (i = 0; i < num_locals; ++i) {
2690 MonoReflectionLocalBuilder *lb =
2691 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
2693 header->locals [i] = image_g_new0 (image, MonoType, 1);
2694 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)lb->type, error);
2695 mono_error_assert_ok (error);
2696 memcpy (header->locals [i], type, MONO_SIZEOF_TYPE);
2699 header->num_clauses = num_clauses;
2701 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
2702 rmb->ilgen, num_clauses, error);
2703 mono_error_assert_ok (error);
2706 wrapperm->header = header;
2709 if (rmb->generic_params) {
2710 int count = mono_array_length (rmb->generic_params);
2711 MonoGenericContainer *container;
2713 container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
2714 container->is_method = TRUE;
2715 container->is_anonymous = FALSE;
2716 container->type_argc = count;
2717 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
2718 container->owner.method = m;
2720 m->is_generic = TRUE;
2721 mono_method_set_generic_container (m, container);
2723 for (i = 0; i < count; i++) {
2724 MonoReflectionGenericParam *gp =
2725 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
2726 MonoType *gp_type = mono_reflection_type_get_handle ((MonoReflectionType*)gp, error);
2727 mono_error_assert_ok (error);
2728 MonoGenericParamFull *param = (MonoGenericParamFull *) gp_type->data.generic_param;
2729 container->type_params [i] = *param;
2730 container->type_params [i].param.owner = container;
2732 gp->type.type->data.generic_param = (MonoGenericParam*)&container->type_params [i];
2734 MonoClass *gklass = mono_class_from_mono_type (gp_type);
2735 gklass->wastypebuilder = TRUE;
2739 * The method signature might have pointers to generic parameters that belong to other methods.
2740 * This is a valid SRE case, but the resulting method signature must be encoded using the proper
2741 * generic parameters.
2743 for (i = 0; i < m->signature->param_count; ++i) {
2744 MonoType *t = m->signature->params [i];
2745 if (t->type == MONO_TYPE_MVAR) {
2746 MonoGenericParam *gparam = t->data.generic_param;
2747 if (gparam->num < count) {
2748 m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
2749 m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
2755 if (mono_class_is_gtd (klass)) {
2756 container->parent = mono_class_get_generic_container (klass);
2757 container->context.class_inst = mono_class_get_generic_container (klass)->context.class_inst;
2759 container->context.method_inst = mono_get_shared_generic_inst (container);
2763 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
2767 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
2769 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
2770 data [0] = GUINT_TO_POINTER (rmb->nrefs);
2771 for (i = 0; i < rmb->nrefs; ++i)
2772 data [i + 1] = rmb->refs [i];
2777 /* Parameter info */
2780 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
2781 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
2782 for (i = 0; i <= m->signature->param_count; ++i) {
2783 MonoReflectionParamBuilder *pb;
2784 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
2785 if ((i > 0) && (pb->attrs)) {
2786 /* Make a copy since it might point to a shared type structure */
2787 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
2788 m->signature->params [i - 1]->attrs = pb->attrs;
2791 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
2792 MonoDynamicImage *assembly;
2794 MonoTypeEnum def_type;
2798 if (!method_aux->param_defaults) {
2799 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
2800 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
2802 assembly = (MonoDynamicImage*)klass->image;
2803 idx = mono_dynimage_encode_constant (assembly, pb->def_value, &def_type);
2804 /* Copy the data from the blob since it might get realloc-ed */
2805 p = assembly->blob.data + idx;
2806 len = mono_metadata_decode_blob_size (p, &p2);
2808 method_aux->param_defaults [i] = (uint8_t *)image_g_malloc (image, len);
2809 method_aux->param_default_types [i] = def_type;
2810 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
2814 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, error);
2815 mono_error_assert_ok (error);
2818 if (!method_aux->param_cattr)
2819 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
2820 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
2826 /* Parameter marshalling */
2829 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
2830 MonoReflectionParamBuilder *pb;
2831 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
2832 if (pb->marshal_info) {
2834 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
2835 specs [pb->position] =
2836 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info, error);
2837 if (!is_ok (error)) {
2838 mono_loader_unlock ();
2839 image_g_free (image, specs);
2840 /* FIXME: if image is NULL, this leaks all the other stuff we alloc'd in this function */
2846 if (specs != NULL) {
2848 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
2849 method_aux->param_marshall = specs;
2852 if (image_is_dynamic (klass->image) && method_aux)
2853 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
2855 mono_loader_unlock ();
2861 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb, MonoError *error)
2863 ReflectionMethodBuilder rmb;
2864 MonoMethodSignature *sig;
2866 mono_loader_lock ();
2868 if (!mono_reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
2871 g_assert (klass->image != NULL);
2872 sig = ctor_builder_to_signature (klass->image, mb, error);
2873 mono_loader_unlock ();
2874 return_val_if_nok (error, NULL);
2876 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
2877 return_val_if_nok (error, NULL);
2878 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
2880 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
2881 /* ilgen is no longer needed */
2889 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb, MonoError *error)
2891 ReflectionMethodBuilder rmb;
2892 MonoMethodSignature *sig;
2894 mono_error_init (error);
2896 mono_loader_lock ();
2898 if (!mono_reflection_methodbuilder_from_method_builder (&rmb, mb, error))
2901 g_assert (klass->image != NULL);
2902 sig = method_builder_to_signature (klass->image, mb, error);
2903 mono_loader_unlock ();
2904 return_val_if_nok (error, NULL);
2906 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
2907 return_val_if_nok (error, NULL);
2908 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
2910 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save)
2911 /* ilgen is no longer needed */
2917 #ifndef DISABLE_REFLECTION_EMIT
2920 * fix_partial_generic_class:
2921 * @klass: a generic instantiation MonoClass
2922 * @error: set on error
2924 * Assumes that the generic container of @klass has its vtable
2925 * initialized, and updates the parent class, interfaces, methods and
2926 * fields of @klass by inflating the types using the generic context.
2928 * On success returns TRUE, on failure returns FALSE and sets @error.
2932 fix_partial_generic_class (MonoClass *klass, MonoError *error)
2934 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2937 mono_error_init (error);
2939 if (klass->wastypebuilder)
2942 if (klass->parent != gklass->parent) {
2943 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &mono_class_get_generic_class (klass)->context, error);
2944 if (mono_error_ok (error)) {
2945 MonoClass *parent = mono_class_from_mono_type (parent_type);
2946 mono_metadata_free_type (parent_type);
2947 if (parent != klass->parent) {
2948 /*fool mono_class_setup_parent*/
2949 klass->supertypes = NULL;
2950 mono_class_setup_parent (klass, parent);
2953 if (gklass->wastypebuilder)
2954 klass->wastypebuilder = TRUE;
2959 if (!mono_class_get_generic_class (klass)->need_sync)
2962 int mcount = mono_class_get_method_count (klass);
2963 int gmcount = mono_class_get_method_count (gklass);
2964 if (mcount != gmcount) {
2965 mono_class_set_method_count (klass, gmcount);
2966 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (gmcount + 1));
2968 for (i = 0; i < gmcount; i++) {
2969 klass->methods [i] = mono_class_inflate_generic_method_full_checked (
2970 gklass->methods [i], klass, mono_class_get_context (klass), error);
2971 mono_error_assert_ok (error);
2975 if (klass->interface_count && klass->interface_count != gklass->interface_count) {
2976 klass->interface_count = gklass->interface_count;
2977 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
2978 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
2980 for (i = 0; i < gklass->interface_count; ++i) {
2981 MonoType *iface_type = mono_class_inflate_generic_type_checked (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass), error);
2982 return_val_if_nok (error, FALSE);
2984 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
2985 mono_metadata_free_type (iface_type);
2987 if (!ensure_runtime_vtable (klass->interfaces [i], error))
2990 klass->interfaces_inited = 1;
2993 int fcount = mono_class_get_field_count (klass);
2994 int gfcount = mono_class_get_field_count (gklass);
2995 if (fcount != gfcount) {
2996 mono_class_set_field_count (klass, gfcount);
2997 klass->fields = image_g_new0 (klass->image, MonoClassField, gfcount);
2999 for (i = 0; i < gfcount; i++) {
3000 klass->fields [i] = gklass->fields [i];
3001 klass->fields [i].parent = klass;
3002 klass->fields [i].type = mono_class_inflate_generic_type_checked (gklass->fields [i].type, mono_class_get_context (klass), error);
3003 return_val_if_nok (error, FALSE);
3007 /*We can only finish with this klass once it's parent has as well*/
3008 if (gklass->wastypebuilder)
3009 klass->wastypebuilder = TRUE;
3014 * ensure_generic_class_runtime_vtable:
3015 * @klass a generic class
3016 * @error set on error
3018 * Ensures that the generic container of @klass has a vtable and
3019 * returns TRUE on success. On error returns FALSE and sets @error.
3022 ensure_generic_class_runtime_vtable (MonoClass *klass, MonoError *error)
3024 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
3026 mono_error_init (error);
3028 if (!ensure_runtime_vtable (gklass, error))
3031 return fix_partial_generic_class (klass, error);
3035 * ensure_runtime_vtable:
3037 * @error set on error
3039 * Ensures that @klass has a vtable and returns TRUE on success. On
3040 * error returns FALSE and sets @error.
3043 ensure_runtime_vtable (MonoClass *klass, MonoError *error)
3045 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
3048 mono_error_init (error);
3050 if (!image_is_dynamic (klass->image) || (!tb && !mono_class_is_ginst (klass)) || klass->wastypebuilder)
3053 if (!ensure_runtime_vtable (klass->parent, error))
3057 num = tb->ctors? mono_array_length (tb->ctors): 0;
3058 num += tb->num_methods;
3059 mono_class_set_method_count (klass, num);
3060 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
3061 num = tb->ctors? mono_array_length (tb->ctors): 0;
3062 for (i = 0; i < num; ++i) {
3063 MonoMethod *ctor = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), error);
3066 klass->methods [i] = ctor;
3068 num = tb->num_methods;
3070 for (i = 0; i < num; ++i) {
3071 MonoMethod *meth = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), error);
3074 klass->methods [j++] = meth;
3077 if (tb->interfaces) {
3078 klass->interface_count = mono_array_length (tb->interfaces);
3079 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
3080 for (i = 0; i < klass->interface_count; ++i) {
3081 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i, error);
3082 return_val_if_nok (error, FALSE);
3083 klass->interfaces [i] = mono_class_from_mono_type (iface);
3084 if (!ensure_runtime_vtable (klass->interfaces [i], error))
3087 klass->interfaces_inited = 1;
3089 } else if (mono_class_is_ginst (klass)){
3090 if (!ensure_generic_class_runtime_vtable (klass, error)) {
3091 mono_class_set_type_load_failure (klass, "Could not initialize vtable for generic class due to: %s", mono_error_get_message (error));
3096 if (mono_class_is_interface (klass) && !mono_class_is_ginst (klass)) {
3098 int mcount = mono_class_get_method_count (klass);
3099 for (i = 0; i < mcount; ++i) {
3100 MonoMethod *im = klass->methods [i];
3101 if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
3102 im->slot = slot_num++;
3105 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
3106 mono_class_setup_interface_offsets (klass);
3107 mono_class_setup_interface_id (klass);
3111 * The generic vtable is needed even if image->run is not set since some
3112 * runtime code like ves_icall_Type_GetMethodsByName depends on
3113 * method->slot being defined.
3117 * tb->methods could not be freed since it is used for determining
3118 * overrides during dynamic vtable construction.
3125 mono_reflection_method_get_handle (MonoObject *method, MonoError *error)
3127 mono_error_init (error);
3128 MonoClass *klass = mono_object_class (method);
3129 if (is_sr_mono_method (klass)) {
3130 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
3131 return sr_method->method;
3133 if (is_sre_method_builder (klass)) {
3134 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
3137 if (mono_is_sre_method_on_tb_inst (klass)) {
3138 MonoClass *handle_class;
3140 MonoMethod *result = mono_reflection_resolve_object (NULL, method, &handle_class, NULL, error);
3141 return_val_if_nok (error, NULL);
3146 g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
3151 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides, MonoError *error)
3153 MonoReflectionTypeBuilder *tb;
3155 MonoReflectionMethod *m;
3157 mono_error_init (error);
3161 g_assert (image_is_dynamic (klass->image));
3163 if (!mono_class_get_ref_info (klass))
3166 g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
3168 tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
3172 for (i = 0; i < tb->num_methods; ++i) {
3173 MonoReflectionMethodBuilder *mb =
3174 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3175 if (mb->override_methods)
3176 onum += mono_array_length (mb->override_methods);
3181 *overrides = g_new0 (MonoMethod*, onum * 2);
3184 for (i = 0; i < tb->num_methods; ++i) {
3185 MonoReflectionMethodBuilder *mb =
3186 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3187 if (mb->override_methods) {
3188 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
3189 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
3191 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m, error);
3192 return_if_nok (error);
3193 (*overrides) [onum * 2 + 1] = mb->mhandle;
3195 g_assert (mb->mhandle);
3203 *num_overrides = onum;
3206 /* This initializes the same data as mono_class_setup_fields () */
3208 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
3210 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
3211 MonoReflectionFieldBuilder *fb;
3212 MonoClassField *field;
3213 MonoFieldDefaultValue *def_values;
3214 MonoImage *image = klass->image;
3216 int i, instance_size, packing_size = 0;
3219 if (klass->parent) {
3220 if (!klass->parent->size_inited)
3221 mono_class_init (klass->parent);
3222 instance_size = klass->parent->instance_size;
3224 instance_size = sizeof (MonoObject);
3227 int fcount = tb->num_fields;
3228 mono_class_set_field_count (klass, fcount);
3230 mono_error_init (error);
3232 if (tb->class_size) {
3233 packing_size = tb->packing_size;
3234 instance_size += tb->class_size;
3237 klass->fields = image_g_new0 (image, MonoClassField, fcount);
3238 def_values = image_g_new0 (image, MonoFieldDefaultValue, fcount);
3239 mono_class_set_field_def_values (klass, def_values);
3241 This is, guess what, a hack.
3242 The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
3243 On the static path no field class is resolved, only types are built. This is the right thing to do
3245 Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
3247 klass->size_inited = 1;
3249 for (i = 0; i < fcount; ++i) {
3250 MonoArray *rva_data;
3251 fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
3252 field = &klass->fields [i];
3253 field->parent = klass;
3254 field->name = mono_string_to_utf8_image (image, fb->name, error);
3255 if (!mono_error_ok (error))
3258 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
3259 return_if_nok (error);
3260 field->type = mono_metadata_type_dup (klass->image, type);
3261 field->type->attrs = fb->attrs;
3263 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
3264 return_if_nok (error);
3267 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
3268 char *base = mono_array_addr (rva_data, char, 0);
3269 size_t size = mono_array_length (rva_data);
3270 char *data = (char *)mono_image_alloc (klass->image, size);
3271 memcpy (data, base, size);
3272 def_values [i].data = data;
3274 if (fb->offset != -1)
3275 field->offset = fb->offset;
3277 mono_save_custom_attrs (klass->image, field, fb->cattrs);
3279 if (fb->def_value) {
3280 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
3281 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
3282 idx = mono_dynimage_encode_constant (assembly, fb->def_value, &def_values [i].def_type);
3283 /* Copy the data from the blob since it might get realloc-ed */
3284 p = assembly->blob.data + idx;
3285 len = mono_metadata_decode_blob_size (p, &p2);
3287 def_values [i].data = (const char *)mono_image_alloc (image, len);
3288 memcpy ((gpointer)def_values [i].data, p, len);
3292 mono_class_layout_fields (klass, instance_size, packing_size, TRUE);
3296 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
3298 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
3299 MonoReflectionPropertyBuilder *pb;
3300 MonoImage *image = klass->image;
3301 MonoProperty *properties;
3302 MonoClassPropertyInfo *info;
3305 mono_error_init (error);
3307 info = mono_class_get_property_info (klass);
3309 info = mono_class_alloc0 (klass, sizeof (MonoClassPropertyInfo));
3310 mono_class_set_property_info (klass, info);
3313 info->count = tb->properties ? mono_array_length (tb->properties) : 0;
3316 properties = image_g_new0 (image, MonoProperty, info->count);
3317 info->properties = properties;
3318 for (i = 0; i < info->count; ++i) {
3319 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3320 properties [i].parent = klass;
3321 properties [i].attrs = pb->attrs;
3322 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
3323 if (!mono_error_ok (error))
3326 properties [i].get = pb->get_method->mhandle;
3328 properties [i].set = pb->set_method->mhandle;
3330 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
3331 if (pb->def_value) {
3334 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
3335 if (!info->def_values)
3336 info->def_values = image_g_new0 (image, MonoFieldDefaultValue, info->count);
3337 properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
3338 idx = mono_dynimage_encode_constant (assembly, pb->def_value, &info->def_values [i].def_type);
3339 /* Copy the data from the blob since it might get realloc-ed */
3340 p = assembly->blob.data + idx;
3341 len = mono_metadata_decode_blob_size (p, &p2);
3343 info->def_values [i].data = (const char *)mono_image_alloc (image, len);
3344 memcpy ((gpointer)info->def_values [i].data, p, len);
3350 typebuilder_setup_events (MonoClass *klass, MonoError *error)
3352 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
3353 MonoReflectionEventBuilder *eb;
3354 MonoImage *image = klass->image;
3356 MonoClassEventInfo *info;
3359 mono_error_init (error);
3361 info = mono_class_alloc0 (klass, sizeof (MonoClassEventInfo));
3362 mono_class_set_event_info (klass, info);
3364 info->count = tb->events ? mono_array_length (tb->events) : 0;
3367 events = image_g_new0 (image, MonoEvent, info->count);
3368 info->events = events;
3369 for (i = 0; i < info->count; ++i) {
3370 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3371 events [i].parent = klass;
3372 events [i].attrs = eb->attrs;
3373 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
3374 if (!mono_error_ok (error))
3377 events [i].add = eb->add_method->mhandle;
3378 if (eb->remove_method)
3379 events [i].remove = eb->remove_method->mhandle;
3380 if (eb->raise_method)
3381 events [i].raise = eb->raise_method->mhandle;
3383 #ifndef MONO_SMALL_CONFIG
3384 if (eb->other_methods) {
3386 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
3387 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
3388 MonoReflectionMethodBuilder *mb =
3389 mono_array_get (eb->other_methods,
3390 MonoReflectionMethodBuilder*, j);
3391 events [i].other [j] = mb->mhandle;
3395 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
3399 struct remove_instantiations_user_data
3406 remove_instantiations_of_and_ensure_contents (gpointer key,
3410 struct remove_instantiations_user_data *data = (struct remove_instantiations_user_data*)user_data;
3411 MonoType *type = (MonoType*)key;
3412 MonoClass *klass = data->klass;
3413 gboolean already_failed = !is_ok (data->error);
3415 MonoError *error = already_failed ? &lerror : data->error;
3417 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
3418 MonoClass *inst_klass = mono_class_from_mono_type (type);
3419 //Ensure it's safe to use it.
3420 if (!fix_partial_generic_class (inst_klass, error)) {
3421 mono_class_set_type_load_failure (inst_klass, "Could not initialized generic type instance due to: %s", mono_error_get_message (error));
3422 // Marked the class with failure, but since some other instantiation already failed,
3423 // just report that one, and swallow the error from this one.
3425 mono_error_cleanup (error);
3433 ves_icall_TypeBuilder_create_runtime_class (MonoReflectionTypeBuilder *tb)
3438 MonoReflectionType* res;
3441 mono_error_init (&error);
3443 reflection_create_generic_class (tb, &error);
3444 mono_error_assert_ok (&error);
3446 domain = mono_object_domain (tb);
3447 klass = mono_class_from_mono_type (tb->type.type);
3449 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
3452 * we need to lock the domain because the lock will be taken inside
3453 * So, we need to keep the locking order correct.
3455 mono_loader_lock ();
3456 mono_domain_lock (domain);
3457 if (klass->wastypebuilder) {
3458 mono_domain_unlock (domain);
3459 mono_loader_unlock ();
3461 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
3462 mono_error_set_pending_exception (&error);
3467 * Fields to set in klass:
3468 * the various flags: delegate/unicode/contextbound etc.
3470 mono_class_set_flags (klass, tb->attrs);
3471 klass->has_cctor = 1;
3473 mono_class_setup_parent (klass, klass->parent);
3474 /* fool mono_class_setup_supertypes */
3475 klass->supertypes = NULL;
3476 mono_class_setup_supertypes (klass);
3477 mono_class_setup_mono_type (klass);
3479 /* enums are done right away */
3480 if (!klass->enumtype)
3481 if (!ensure_runtime_vtable (klass, &error))
3485 GList *nested = NULL;
3486 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3487 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3489 if (!subtb->type.type) {
3490 reflection_setup_internal_class (subtb, &error);
3491 mono_error_assert_ok (&error);
3494 MonoType *subtype = mono_reflection_type_get_handle ((MonoReflectionType*)subtb, &error);
3495 if (!is_ok (&error)) goto failure;
3496 nested = g_list_prepend_image (klass->image, nested, mono_class_from_mono_type (subtype));
3498 mono_class_set_nested_classes_property (klass, nested);
3501 klass->nested_classes_inited = TRUE;
3503 typebuilder_setup_fields (klass, &error);
3504 if (!mono_error_ok (&error))
3506 typebuilder_setup_properties (klass, &error);
3507 if (!mono_error_ok (&error))
3510 typebuilder_setup_events (klass, &error);
3511 if (!mono_error_ok (&error))
3514 klass->wastypebuilder = TRUE;
3516 if (tb->generic_params) {
3517 for (i = 0; i < mono_array_length (tb->generic_params); i++) {
3518 MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)mono_array_get (tb->generic_params, gpointer, i);
3519 MonoType *param_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, &error);
3520 MonoClass *gklass = mono_class_from_mono_type (param_type);
3522 gklass->wastypebuilder = TRUE;
3527 * If we are a generic TypeBuilder, there might be instantiations in the type cache
3528 * which have type System.Reflection.MonoGenericClass, but after the type is created,
3529 * we want to return normal System.MonoType objects, so clear these out from the cache.
3531 * Together with this we must ensure the contents of all instances to match the created type.
3533 if (domain->type_hash && mono_class_is_gtd (klass)) {
3534 struct remove_instantiations_user_data data;
3536 data.error = &error;
3537 mono_error_assert_ok (&error);
3538 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, &data);
3539 if (!is_ok (&error))
3543 mono_domain_unlock (domain);
3544 mono_loader_unlock ();
3546 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
3547 mono_class_set_type_load_failure (klass, "Not a valid enumeration");
3548 mono_error_set_type_load_class (&error, klass, "Not a valid enumeration");
3549 goto failure_unlocked;
3552 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
3553 if (!is_ok (&error))
3554 goto failure_unlocked;
3556 g_assert (res != (MonoReflectionType*)tb);
3561 mono_class_set_type_load_failure (klass, "TypeBuilder could not create runtime class due to: %s", mono_error_get_message (&error));
3562 klass->wastypebuilder = TRUE;
3563 mono_domain_unlock (domain);
3564 mono_loader_unlock ();
3566 mono_error_set_pending_exception (&error);
3573 } DynamicMethodReleaseData;
3576 * The runtime automatically clean up those after finalization.
3578 static MonoReferenceQueue *dynamic_method_queue;
3581 free_dynamic_method (void *dynamic_method)
3583 DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
3584 MonoDomain *domain = data->domain;
3585 MonoMethod *method = data->handle;
3588 mono_domain_lock (domain);
3589 dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
3590 g_hash_table_remove (domain->method_to_dyn_method, method);
3591 mono_domain_unlock (domain);
3592 g_assert (dis_link);
3593 mono_gchandle_free (dis_link);
3595 mono_runtime_free_method (domain, method);
3600 reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb, MonoError *error)
3602 MonoReferenceQueue *queue;
3604 DynamicMethodReleaseData *release_data;
3605 ReflectionMethodBuilder rmb;
3606 MonoMethodSignature *sig;
3612 mono_error_init (error);
3614 if (mono_runtime_is_shutting_down ()) {
3615 mono_error_set_generic_error (error, "System", "InvalidOperationException", "");
3619 if (!(queue = dynamic_method_queue)) {
3620 mono_loader_lock ();
3621 if (!(queue = dynamic_method_queue))
3622 queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
3623 mono_loader_unlock ();
3626 sig = dynamic_method_to_signature (mb, error);
3627 return_val_if_nok (error, FALSE);
3629 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
3632 * Resolve references.
3635 * Every second entry in the refs array is reserved for storing handle_class,
3636 * which is needed by the ldtoken implementation in the JIT.
3638 rmb.nrefs = mb->nrefs;
3639 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
3640 for (i = 0; i < mb->nrefs; i += 2) {
3641 MonoClass *handle_class;
3643 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
3645 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
3646 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
3648 * The referenced DynamicMethod should already be created by the managed
3649 * code, except in the case of circular references. In that case, we store
3650 * method in the refs array, and fix it up later when the referenced
3651 * DynamicMethod is created.
3653 if (method->mhandle) {
3654 ref = method->mhandle;
3656 /* FIXME: GC object stored in unmanaged memory */
3659 /* FIXME: GC object stored in unmanaged memory */
3660 method->referenced_by = g_slist_append (method->referenced_by, mb);
3662 handle_class = mono_defaults.methodhandle_class;
3664 MonoException *ex = NULL;
3665 ref = mono_reflection_resolve_object (mb->module->image, obj, &handle_class, NULL, error);
3666 if (!is_ok (error)) {
3671 ex = mono_get_exception_type_load (NULL, NULL);
3672 else if (mono_security_core_clr_enabled ())
3673 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
3677 mono_error_set_exception_instance (error, ex);
3682 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
3683 rmb.refs [i + 1] = handle_class;
3687 MonoType *owner_type = mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner, error);
3688 if (!is_ok (error)) {
3692 klass = mono_class_from_mono_type (owner_type);
3694 klass = mono_defaults.object_class;
3697 mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
3699 return_val_if_nok (error, FALSE);
3701 release_data = g_new (DynamicMethodReleaseData, 1);
3702 release_data->handle = handle;
3703 release_data->domain = mono_object_get_domain ((MonoObject*)mb);
3704 if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
3705 g_free (release_data);
3707 /* Fix up refs entries pointing at us */
3708 for (l = mb->referenced_by; l; l = l->next) {
3709 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
3710 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
3713 g_assert (method->mhandle);
3715 data = (gpointer*)wrapper->method_data;
3716 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
3717 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
3718 data [i + 1] = mb->mhandle;
3721 g_slist_free (mb->referenced_by);
3723 /* ilgen is no longer needed */
3726 domain = mono_domain_get ();
3727 mono_domain_lock (domain);
3728 if (!domain->method_to_dyn_method)
3729 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
3730 g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
3731 mono_domain_unlock (domain);
3737 ves_icall_DynamicMethod_create_dynamic_method (MonoReflectionDynamicMethod *mb)
3740 (void) reflection_create_dynamic_method (mb, &error);
3741 mono_error_set_pending_exception (&error);
3744 #endif /* DISABLE_REFLECTION_EMIT */
3746 MonoMethodSignature *
3747 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
3749 MonoMethodSignature *sig;
3750 g_assert (image_is_dynamic (image));
3752 mono_error_init (error);
3754 sig = (MonoMethodSignature *)g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
3758 return mono_method_signature_checked (method, error);
3761 #ifndef DISABLE_REFLECTION_EMIT
3764 * ensure_complete_type:
3766 * Ensure that KLASS is completed if it is a dynamic type, or references
3770 ensure_complete_type (MonoClass *klass, MonoError *error)
3772 mono_error_init (error);
3774 if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
3775 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
3777 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
3778 return_if_nok (error);
3780 // Asserting here could break a lot of code
3781 //g_assert (klass->wastypebuilder);
3784 if (mono_class_is_ginst (klass)) {
3785 MonoGenericInst *inst = mono_class_get_generic_class (klass)->context.class_inst;
3788 for (i = 0; i < inst->type_argc; ++i) {
3789 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]), error);
3790 return_if_nok (error);
3796 mono_reflection_resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
3798 MonoClass *oklass = obj->vtable->klass;
3799 gpointer result = NULL;
3801 mono_error_init (error);
3803 if (strcmp (oklass->name, "String") == 0) {
3804 result = mono_string_intern_checked ((MonoString*)obj, error);
3805 return_val_if_nok (error, NULL);
3806 *handle_class = mono_defaults.string_class;
3808 } else if (strcmp (oklass->name, "RuntimeType") == 0) {
3809 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
3810 return_val_if_nok (error, NULL);
3811 MonoClass *mc = mono_class_from_mono_type (type);
3812 if (!mono_class_init (mc)) {
3813 mono_error_set_for_class_failure (error, mc);
3818 MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, error);
3819 return_val_if_nok (error, NULL);
3821 result = mono_class_from_mono_type (inflated);
3822 mono_metadata_free_type (inflated);
3824 result = mono_class_from_mono_type (type);
3826 *handle_class = mono_defaults.typehandle_class;
3828 } else if (strcmp (oklass->name, "MonoMethod") == 0 ||
3829 strcmp (oklass->name, "MonoCMethod") == 0) {
3830 result = ((MonoReflectionMethod*)obj)->method;
3832 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
3833 mono_error_assert_ok (error);
3835 *handle_class = mono_defaults.methodhandle_class;
3837 } else if (strcmp (oklass->name, "MonoField") == 0) {
3838 MonoClassField *field = ((MonoReflectionField*)obj)->field;
3840 ensure_complete_type (field->parent, error);
3841 return_val_if_nok (error, NULL);
3844 MonoType *inflated = mono_class_inflate_generic_type_checked (&field->parent->byval_arg, context, error);
3845 return_val_if_nok (error, NULL);
3847 MonoClass *klass = mono_class_from_mono_type (inflated);
3848 MonoClassField *inflated_field;
3849 gpointer iter = NULL;
3850 mono_metadata_free_type (inflated);
3851 while ((inflated_field = mono_class_get_fields (klass, &iter))) {
3852 if (!strcmp (field->name, inflated_field->name))
3855 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
3856 result = inflated_field;
3860 *handle_class = mono_defaults.fieldhandle_class;
3862 } else if (strcmp (oklass->name, "TypeBuilder") == 0) {
3863 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
3864 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
3865 return_val_if_nok (error, NULL);
3868 klass = type->data.klass;
3869 if (klass->wastypebuilder) {
3870 /* Already created */
3874 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
3875 return_val_if_nok (error, NULL);
3876 result = type->data.klass;
3879 *handle_class = mono_defaults.typehandle_class;
3880 } else if (strcmp (oklass->name, "SignatureHelper") == 0) {
3881 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
3882 MonoMethodSignature *sig;
3885 if (helper->arguments)
3886 nargs = mono_array_length (helper->arguments);
3890 sig = mono_metadata_signature_alloc (image, nargs);
3891 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
3892 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
3894 if (helper->unmanaged_call_conv) { /* unmanaged */
3895 sig->call_convention = helper->unmanaged_call_conv - 1;
3896 sig->pinvoke = TRUE;
3897 } else if (helper->call_conv & 0x02) {
3898 sig->call_convention = MONO_CALL_VARARG;
3900 sig->call_convention = MONO_CALL_DEFAULT;
3903 sig->param_count = nargs;
3904 /* TODO: Copy type ? */
3905 sig->ret = helper->return_type->type;
3906 for (i = 0; i < nargs; ++i) {
3907 sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i, error);
3908 if (!is_ok (error)) {
3909 image_g_free (image, sig);
3915 *handle_class = NULL;
3916 } else if (strcmp (oklass->name, "DynamicMethod") == 0) {
3917 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
3918 /* Already created by the managed code */
3919 g_assert (method->mhandle);
3920 result = method->mhandle;
3921 *handle_class = mono_defaults.methodhandle_class;
3922 } else if (strcmp (oklass->name, "MonoArrayMethod") == 0) {
3923 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
3930 mtype = mono_reflection_type_get_handle (m->parent, error);
3931 return_val_if_nok (error, NULL);
3932 klass = mono_class_from_mono_type (mtype);
3934 /* Find the method */
3936 name = mono_string_to_utf8_checked (m->name, error);
3937 return_val_if_nok (error, NULL);
3939 while ((method = mono_class_get_methods (klass, &iter))) {
3940 if (!strcmp (method->name, name))
3947 // FIXME: Check parameters/return value etc. match
3950 *handle_class = mono_defaults.methodhandle_class;
3951 } else if (is_sre_method_builder (oklass) ||
3952 mono_is_sre_ctor_builder (oklass) ||
3953 is_sre_field_builder (oklass) ||
3954 is_sre_gparam_builder (oklass) ||
3955 is_sre_generic_instance (oklass) ||
3956 is_sre_array (oklass) ||
3957 is_sre_byref (oklass) ||
3958 is_sre_pointer (oklass) ||
3959 !strcmp (oklass->name, "FieldOnTypeBuilderInst") ||
3960 !strcmp (oklass->name, "MethodOnTypeBuilderInst") ||
3961 !strcmp (oklass->name, "ConstructorOnTypeBuilderInst")) {
3962 static MonoMethod *resolve_method;
3963 if (!resolve_method) {
3964 MonoMethod *m = mono_class_get_method_from_name_flags (mono_class_get_module_builder_class (), "RuntimeResolve", 1, 0);
3966 mono_memory_barrier ();
3971 obj = mono_runtime_invoke_checked (resolve_method, NULL, args, error);
3972 mono_error_assert_ok (error);
3974 return mono_reflection_resolve_object (image, obj, handle_class, context, error);
3976 g_print ("%s\n", obj->vtable->klass->name);
3977 g_assert_not_reached ();
3982 #else /* DISABLE_REFLECTION_EMIT */
3985 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
3987 g_assert_not_reached ();
3992 mono_reflection_dynimage_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
3994 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
3998 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
4000 g_assert_not_reached ();
4004 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4006 g_assert_not_reached ();
4011 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
4013 g_assert_not_reached ();
4018 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
4019 gboolean create_open_instance, gboolean register_token, MonoError *error)
4021 g_assert_not_reached ();
4026 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides, MonoError *error)
4028 mono_error_init (error);
4034 ves_icall_TypeBuilder_create_runtime_class (MonoReflectionTypeBuilder *tb)
4036 g_assert_not_reached ();
4041 ves_icall_DynamicMethod_create_dynamic_method (MonoReflectionDynamicMethod *mb)
4046 mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
4048 mono_error_init (error);
4054 #endif /* DISABLE_REFLECTION_EMIT */
4057 mono_sre_generic_param_table_entry_free (GenericParamTableEntry *entry)
4059 mono_gc_deregister_root ((char*) &entry->gparam);
4064 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
4066 MONO_CHECK_ARG_NULL (obj, 0);
4069 gint32 result = mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE, &error);
4070 mono_error_set_pending_exception (&error);
4075 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
4076 MonoReflectionMethod *method,
4077 MonoArray *opt_param_types)
4079 MONO_CHECK_ARG_NULL (method, 0);
4082 gint32 result = mono_image_create_method_token (
4083 mb->dynamic_image, (MonoObject *) method, opt_param_types, &error);
4084 mono_error_set_pending_exception (&error);
4089 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
4092 mono_image_create_pefile (mb, file, &error);
4093 mono_error_set_pending_exception (&error);
4097 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
4100 mono_image_build_metadata (mb, &error);
4101 mono_error_set_pending_exception (&error);
4105 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
4107 mono_image_register_token (mb->dynamic_image, token, obj);
4111 ves_icall_ModuleBuilder_GetRegisteredToken (MonoReflectionModuleBuilder *mb, guint32 token)
4115 mono_loader_lock ();
4116 obj = (MonoObject *)mono_g_hash_table_lookup (mb->dynamic_image->tokens, GUINT_TO_POINTER (token));
4117 mono_loader_unlock ();
4122 #ifndef DISABLE_REFLECTION_EMIT
4124 ves_icall_CustomAttributeBuilder_GetBlob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
4127 MonoArray *result = mono_reflection_get_custom_attrs_blob_checked (assembly, ctor, ctorArgs, properties, propValues, fields, fieldValues, &error);
4128 mono_error_set_pending_exception (&error);
4134 ves_icall_AssemblyBuilder_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4136 mono_reflection_dynimage_basic_init (assemblyb);
4140 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
4141 MonoReflectionType *t)
4143 enumtype->type = t->type;
4147 ves_icall_ModuleBuilder_basic_init (MonoReflectionModuleBuilder *moduleb)
4149 mono_image_module_basic_init (moduleb);
4153 ves_icall_ModuleBuilder_getUSIndex (MonoReflectionModuleBuilder *module, MonoString *str)
4155 return mono_image_insert_string (module, str);
4159 ves_icall_ModuleBuilder_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
4161 MonoDynamicImage *image = moduleb->dynamic_image;
4163 g_assert (type->type);
4164 image->wrappers_type = mono_class_from_mono_type (type->type);