[sre] Add MonoDynamicImageTokCollision arg to mono_dynamic_image_register_token
[mono-project.git] / mono / metadata / sre.c
blobeda0cf400756e1bbb0283f4df6d054865a4aa768
1 /**
2 * \file
3 * Routines for creating an image at runtime
4 * and related System.Reflection.Emit icalls
5 *
6 *
7 * Author:
8 * Paolo Molaro (lupus@ximian.com)
10 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
11 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
12 * Copyright 2011 Rodrigo Kumpera
13 * Copyright 2016 Microsoft
15 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
17 #include <config.h>
18 #include <glib.h>
19 #include "mono/metadata/assembly.h"
20 #include "mono/metadata/debug-helpers.h"
21 #include "mono/metadata/dynamic-image-internals.h"
22 #include "mono/metadata/dynamic-stream-internals.h"
23 #include "mono/metadata/exception.h"
24 #include "mono/metadata/gc-internals.h"
25 #include "mono/metadata/mono-ptr-array.h"
26 #include "mono/metadata/object-internals.h"
27 #include "mono/metadata/profiler-private.h"
28 #include "mono/metadata/reflection-internals.h"
29 #include "mono/metadata/reflection-cache.h"
30 #include "mono/metadata/sre-internals.h"
31 #include "mono/metadata/custom-attrs-internals.h"
32 #include "mono/metadata/security-manager.h"
33 #include "mono/metadata/security-core-clr.h"
34 #include "mono/metadata/tabledefs.h"
35 #include "mono/metadata/tokentype.h"
36 #include "mono/utils/checked-build.h"
37 #include "mono/utils/mono-digest.h"
38 #include "mono/utils/w32api.h"
40 static GENERATE_GET_CLASS_WITH_CACHE (marshal_as_attribute, "System.Runtime.InteropServices", "MarshalAsAttribute");
41 static GENERATE_GET_CLASS_WITH_CACHE (module_builder, "System.Reflection.Emit", "ModuleBuilder");
43 static char* string_to_utf8_image_raw (MonoImage *image, MonoString *s, MonoError *error);
45 #ifndef DISABLE_REFLECTION_EMIT
46 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelperHandle helper, MonoError *error);
47 static gboolean ensure_runtime_vtable (MonoClass *klass, MonoError *error);
48 static void reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb);
49 static gboolean reflection_setup_internal_class (MonoReflectionTypeBuilderHandle tb, MonoError *error);
50 static gboolean reflection_init_generic_class (MonoReflectionTypeBuilderHandle tb, MonoError *error);
51 static gboolean reflection_setup_class_hierarchy (GHashTable *unparented, MonoError *error);
54 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
55 #endif
57 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
58 static MonoReflectionTypeHandle mono_reflection_type_get_underlying_system_type (MonoReflectionTypeHandle t, MonoError *error);
59 static gboolean is_sre_array (MonoClass *klass);
60 static gboolean is_sre_byref (MonoClass *klass);
61 static gboolean is_sre_pointer (MonoClass *klass);
62 static gboolean is_sre_generic_instance (MonoClass *klass);
63 static gboolean is_sre_type_builder (MonoClass *klass);
64 static gboolean is_sre_method_builder (MonoClass *klass);
65 static gboolean is_sre_field_builder (MonoClass *klass);
66 static gboolean is_sre_gparam_builder (MonoClass *klass);
67 static gboolean is_sre_enum_builder (MonoClass *klass);
68 static gboolean is_sr_mono_method (MonoClass *klass);
69 static gboolean is_sr_mono_field (MonoClass *klass);
71 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
72 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
73 static guint32 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObjectHandle obj, MonoArrayHandle opt_param_types, MonoError *error);
76 #ifndef DISABLE_REFLECTION_EMIT
77 static MonoType* mono_type_array_get_and_resolve_raw (MonoArray* array, int idx, MonoError* error);
78 #endif
80 static gboolean mono_image_module_basic_init (MonoReflectionModuleBuilderHandle module, MonoError *error);
82 void
83 mono_reflection_emit_init (void)
85 mono_dynamic_images_init ();
88 char*
89 string_to_utf8_image_raw (MonoImage *image, MonoString *s_raw, MonoError *error)
91 /* FIXME all callers to string_to_utf8_image_raw should use handles */
92 HANDLE_FUNCTION_ENTER ();
93 char* result = NULL;
94 error_init (error);
95 MONO_HANDLE_DCL (MonoString, s);
96 result = mono_string_to_utf8_image (image, s, error);
97 HANDLE_FUNCTION_RETURN_VAL (result);
100 static char*
101 type_get_fully_qualified_name (MonoType *type)
103 MONO_REQ_GC_NEUTRAL_MODE;
105 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
108 static char*
109 type_get_qualified_name (MonoType *type, MonoAssembly *ass)
111 MONO_REQ_GC_UNSAFE_MODE;
113 MonoClass *klass;
114 MonoAssembly *ta;
116 klass = mono_class_from_mono_type (type);
117 if (!klass)
118 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
119 ta = klass->image->assembly;
120 if (assembly_is_dynamic (ta) || (ta == ass)) {
121 if (mono_class_is_ginst (klass) || mono_class_is_gtd (klass))
122 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
123 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
124 else
125 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
128 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
131 #ifndef DISABLE_REFLECTION_EMIT
133 * mp_g_alloc:
135 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
136 * from the C heap.
138 static gpointer
139 image_g_malloc (MonoImage *image, guint size)
141 MONO_REQ_GC_NEUTRAL_MODE;
143 if (image)
144 return mono_image_alloc (image, size);
145 else
146 return g_malloc (size);
148 #endif /* !DISABLE_REFLECTION_EMIT */
151 * image_g_alloc0:
153 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
154 * from the C heap.
156 gpointer
157 mono_image_g_malloc0 (MonoImage *image, guint size)
159 MONO_REQ_GC_NEUTRAL_MODE;
161 if (image)
162 return mono_image_alloc0 (image, size);
163 else
164 return g_malloc0 (size);
168 * image_g_free:
169 * @image: a MonoImage
170 * @ptr: pointer
172 * If @image is NULL, free @ptr, otherwise do nothing.
174 static void
175 image_g_free (MonoImage *image, gpointer ptr)
177 if (image == NULL)
178 g_free (ptr);
181 #ifndef DISABLE_REFLECTION_EMIT
182 static char*
183 image_strdup (MonoImage *image, const char *s)
185 MONO_REQ_GC_NEUTRAL_MODE;
187 if (image)
188 return mono_image_strdup (image, s);
189 else
190 return g_strdup (s);
192 #endif
194 #define image_g_new(image,struct_type, n_structs) \
195 ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
197 #define image_g_new0(image,struct_type, n_structs) \
198 ((struct_type *) mono_image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
201 static void
202 alloc_table (MonoDynamicTable *table, guint nrows)
204 mono_dynimage_alloc_table (table, nrows);
207 static guint32
208 string_heap_insert (MonoDynamicStream *sh, const char *str)
210 return mono_dynstream_insert_string (sh, str);
213 static guint32
214 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
216 return mono_dynstream_add_data (stream, data, len);
220 * Despite the name, we handle also TypeSpec (with the above helper).
222 static guint32
223 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
225 return mono_dynimage_encode_typedef_or_ref_full (assembly, type, TRUE);
229 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
230 * dest may be misaligned.
232 static void
233 swap_with_size (char *dest, const char* val, int len, int nelem) {
234 MONO_REQ_GC_NEUTRAL_MODE;
235 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
236 int elem;
238 for (elem = 0; elem < nelem; ++elem) {
239 switch (len) {
240 case 1:
241 *dest = *val;
242 break;
243 case 2:
244 dest [0] = val [1];
245 dest [1] = val [0];
246 break;
247 case 4:
248 dest [0] = val [3];
249 dest [1] = val [2];
250 dest [2] = val [1];
251 dest [3] = val [0];
252 break;
253 case 8:
254 dest [0] = val [7];
255 dest [1] = val [6];
256 dest [2] = val [5];
257 dest [3] = val [4];
258 dest [4] = val [3];
259 dest [5] = val [2];
260 dest [6] = val [1];
261 dest [7] = val [0];
262 break;
263 default:
264 g_assert_not_reached ();
266 dest += len;
267 val += len;
269 #else
270 memcpy (dest, val, len * nelem);
271 #endif
274 guint32
275 mono_reflection_method_count_clauses (MonoReflectionILGen *ilgen)
277 MONO_REQ_GC_UNSAFE_MODE;
279 guint32 num_clauses = 0;
280 int i;
282 MonoILExceptionInfo *ex_info;
283 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
284 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
285 if (ex_info->handlers)
286 num_clauses += mono_array_length (ex_info->handlers);
287 else
288 num_clauses++;
291 return num_clauses;
294 #ifndef DISABLE_REFLECTION_EMIT
295 static MonoExceptionClause*
296 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses, MonoError *error)
298 MONO_REQ_GC_UNSAFE_MODE;
300 error_init (error);
302 MonoExceptionClause *clauses;
303 MonoExceptionClause *clause;
304 MonoILExceptionInfo *ex_info;
305 MonoILExceptionBlock *ex_block;
306 guint32 finally_start;
307 int i, j, clause_index;;
309 clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
311 clause_index = 0;
312 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
313 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
314 finally_start = ex_info->start + ex_info->len;
315 if (!ex_info->handlers)
316 continue;
317 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
318 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
319 clause = &(clauses [clause_index]);
321 clause->flags = ex_block->type;
322 clause->try_offset = ex_info->start;
324 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
325 clause->try_len = finally_start - ex_info->start;
326 else
327 clause->try_len = ex_info->len;
328 clause->handler_offset = ex_block->start;
329 clause->handler_len = ex_block->len;
330 if (ex_block->extype) {
331 MonoType *extype = mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype, error);
333 if (!is_ok (error)) {
334 image_g_free (image, clauses);
335 return NULL;
337 clause->data.catch_class = mono_class_from_mono_type (extype);
338 } else {
339 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
340 clause->data.filter_offset = ex_block->filter_offset;
341 else
342 clause->data.filter_offset = 0;
344 finally_start = ex_block->start + ex_block->len;
346 clause_index ++;
350 return clauses;
352 #endif /* !DISABLE_REFLECTION_EMIT */
354 #ifndef DISABLE_REFLECTION_EMIT
356 * LOCKING: Acquires the loader lock.
358 static void
359 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
361 MONO_REQ_GC_UNSAFE_MODE;
363 MonoCustomAttrInfo *ainfo, *tmp;
365 if (!cattrs || !mono_array_length (cattrs))
366 return;
368 ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
370 mono_loader_lock ();
371 tmp = (MonoCustomAttrInfo *)mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
372 if (tmp)
373 mono_custom_attrs_free (tmp);
374 mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
375 mono_loader_unlock ();
378 #endif
380 guint32
381 mono_reflection_resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
383 MONO_REQ_GC_UNSAFE_MODE;
385 MonoDynamicTable *table;
386 guint32 token;
387 guint32 *values;
388 guint32 cols [MONO_ASSEMBLY_SIZE];
389 const char *pubkey;
390 guint32 publen;
392 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
393 return token;
395 if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
396 table = &assembly->tables [MONO_TABLE_MODULEREF];
397 token = table->next_idx ++;
398 table->rows ++;
399 alloc_table (table, table->rows);
400 values = table->values + token * MONO_MODULEREF_SIZE;
401 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
403 token <<= MONO_RESOLUTION_SCOPE_BITS;
404 token |= MONO_RESOLUTION_SCOPE_MODULEREF;
405 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
407 return token;
410 if (assembly_is_dynamic (image->assembly))
411 /* FIXME: */
412 memset (cols, 0, sizeof (cols));
413 else {
414 /* image->assembly->image is the manifest module */
415 image = image->assembly->image;
416 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
419 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
420 token = table->next_idx ++;
421 table->rows ++;
422 alloc_table (table, table->rows);
423 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
424 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
425 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
426 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
427 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
428 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
429 values [MONO_ASSEMBLYREF_FLAGS] = 0;
430 values [MONO_ASSEMBLYREF_CULTURE] = 0;
431 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
433 if (strcmp ("", image->assembly->aname.culture)) {
434 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
435 image->assembly->aname.culture);
438 if ((pubkey = mono_image_get_public_key (image, &publen))) {
439 guchar pubtoken [9];
440 pubtoken [0] = 8;
441 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
442 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
443 } else {
444 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
446 token <<= MONO_RESOLUTION_SCOPE_BITS;
447 token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
448 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
449 return token;
452 #ifndef DISABLE_REFLECTION_EMIT
453 gboolean
454 mono_reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error)
456 MONO_REQ_GC_UNSAFE_MODE;
458 error_init (error);
459 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
461 rmb->ilgen = mb->ilgen;
462 rmb->rtype = (MonoReflectionType*)mb->rtype;
463 return_val_if_nok (error, FALSE);
464 rmb->parameters = mb->parameters;
465 rmb->generic_params = mb->generic_params;
466 rmb->generic_container = mb->generic_container;
467 rmb->opt_types = NULL;
468 rmb->pinfo = mb->pinfo;
469 rmb->attrs = mb->attrs;
470 rmb->iattrs = mb->iattrs;
471 rmb->call_conv = mb->call_conv;
472 rmb->code = mb->code;
473 rmb->type = mb->type;
474 rmb->name = mb->name;
475 rmb->table_idx = &mb->table_idx;
476 rmb->init_locals = mb->init_locals;
477 rmb->skip_visibility = FALSE;
478 rmb->return_modreq = mb->return_modreq;
479 rmb->return_modopt = mb->return_modopt;
480 rmb->param_modreq = mb->param_modreq;
481 rmb->param_modopt = mb->param_modopt;
482 rmb->permissions = mb->permissions;
483 rmb->mhandle = mb->mhandle;
484 rmb->nrefs = 0;
485 rmb->refs = NULL;
487 if (mb->dll) {
488 rmb->charset = mb->charset;
489 rmb->extra_flags = mb->extra_flags;
490 rmb->native_cc = mb->native_cc;
491 rmb->dllentry = mb->dllentry;
492 rmb->dll = mb->dll;
495 return TRUE;
498 gboolean
499 mono_reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error)
501 MONO_REQ_GC_UNSAFE_MODE;
503 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
505 error_init (error);
507 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
509 rmb->ilgen = mb->ilgen;
510 rmb->rtype = mono_type_get_object_checked (mono_domain_get (), &mono_defaults.void_class->byval_arg, error);
511 return_val_if_nok (error, FALSE);
512 rmb->parameters = mb->parameters;
513 rmb->generic_params = NULL;
514 rmb->generic_container = NULL;
515 rmb->opt_types = NULL;
516 rmb->pinfo = mb->pinfo;
517 rmb->attrs = mb->attrs;
518 rmb->iattrs = mb->iattrs;
519 rmb->call_conv = mb->call_conv;
520 rmb->code = NULL;
521 rmb->type = mb->type;
522 rmb->name = mono_string_new_checked (mono_domain_get (), name, error);
523 return_val_if_nok (error, FALSE);
524 rmb->table_idx = &mb->table_idx;
525 rmb->init_locals = mb->init_locals;
526 rmb->skip_visibility = FALSE;
527 rmb->return_modreq = NULL;
528 rmb->return_modopt = NULL;
529 rmb->param_modreq = mb->param_modreq;
530 rmb->param_modopt = mb->param_modopt;
531 rmb->permissions = mb->permissions;
532 rmb->mhandle = mb->mhandle;
533 rmb->nrefs = 0;
534 rmb->refs = NULL;
536 return TRUE;
539 static void
540 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
542 MONO_REQ_GC_UNSAFE_MODE;
544 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
546 rmb->ilgen = mb->ilgen;
547 rmb->rtype = mb->rtype;
548 rmb->parameters = mb->parameters;
549 rmb->generic_params = NULL;
550 rmb->generic_container = NULL;
551 rmb->opt_types = NULL;
552 rmb->pinfo = NULL;
553 rmb->attrs = mb->attrs;
554 rmb->iattrs = 0;
555 rmb->call_conv = mb->call_conv;
556 rmb->code = NULL;
557 rmb->type = (MonoObject *) mb->owner;
558 rmb->name = mb->name;
559 rmb->table_idx = NULL;
560 rmb->init_locals = mb->init_locals;
561 rmb->skip_visibility = mb->skip_visibility;
562 rmb->return_modreq = NULL;
563 rmb->return_modopt = NULL;
564 rmb->param_modreq = NULL;
565 rmb->param_modopt = NULL;
566 rmb->permissions = NULL;
567 rmb->mhandle = mb->mhandle;
568 rmb->nrefs = 0;
569 rmb->refs = NULL;
571 #else /* DISABLE_REFLECTION_EMIT */
572 gboolean
573 mono_reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error) {
574 g_assert_not_reached ();
575 return FALSE;
577 gboolean
578 mono_reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error)
580 g_assert_not_reached ();
581 return FALSE;
583 #endif /* DISABLE_REFLECTION_EMIT */
585 #ifndef DISABLE_REFLECTION_EMIT
586 static guint32
587 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
589 MONO_REQ_GC_NEUTRAL_MODE;
591 MonoDynamicTable *table;
592 guint32 *values;
593 guint32 token, pclass;
595 switch (parent & MONO_TYPEDEFORREF_MASK) {
596 case MONO_TYPEDEFORREF_TYPEREF:
597 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
598 break;
599 case MONO_TYPEDEFORREF_TYPESPEC:
600 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
601 break;
602 case MONO_TYPEDEFORREF_TYPEDEF:
603 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
604 break;
605 default:
606 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
607 return 0;
609 /* extract the index */
610 parent >>= MONO_TYPEDEFORREF_BITS;
612 table = &assembly->tables [MONO_TABLE_MEMBERREF];
614 if (assembly->save) {
615 alloc_table (table, table->rows + 1);
616 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
617 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
618 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
619 values [MONO_MEMBERREF_SIGNATURE] = sig;
622 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
623 table->next_idx ++;
625 return token;
629 * Insert a memberef row into the metadata: the token that point to the memberref
630 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
631 * mono_image_get_fieldref_token()).
632 * The sig param is an index to an already built signature.
634 static guint32
635 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
637 MONO_REQ_GC_NEUTRAL_MODE;
639 guint32 parent = mono_image_typedef_or_ref (assembly, type);
640 return mono_image_add_memberef_row (assembly, parent, name, sig);
644 guint32
645 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
647 MONO_REQ_GC_NEUTRAL_MODE;
649 guint32 token;
650 MonoMethodSignature *sig;
652 create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
654 if (create_typespec) {
655 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
656 if (token)
657 return token;
660 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
661 if (token && !create_typespec)
662 return token;
664 g_assert (!method->is_inflated);
665 if (!token) {
667 * A methodref signature can't contain an unmanaged calling convention.
669 sig = mono_metadata_signature_dup (mono_method_signature (method));
670 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
671 sig->call_convention = MONO_CALL_DEFAULT;
672 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
673 method->name, mono_dynimage_encode_method_signature (assembly, sig));
674 g_free (sig);
675 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
678 if (create_typespec) {
679 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
680 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
681 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
683 if (assembly->save) {
684 guint32 *values;
686 alloc_table (table, table->rows + 1);
687 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
688 values [MONO_METHODSPEC_METHOD] = token;
689 values [MONO_METHODSPEC_SIGNATURE] = mono_dynimage_encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
692 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
693 table->next_idx ++;
694 /*methodspec and memberef tokens are diferent, */
695 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
696 return token;
698 return token;
701 static guint32
702 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
703 const gchar *name, guint32 sig)
705 MonoDynamicTable *table;
706 guint32 token;
707 guint32 *values;
709 table = &assembly->tables [MONO_TABLE_MEMBERREF];
711 if (assembly->save) {
712 alloc_table (table, table->rows + 1);
713 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
714 values [MONO_MEMBERREF_CLASS] = original;
715 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
716 values [MONO_MEMBERREF_SIGNATURE] = sig;
719 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
720 table->next_idx ++;
722 return token;
725 #else /* DISABLE_REFLECTION_EMIT */
727 guint32
728 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
730 g_assert_not_reached ();
731 return -1;
733 #endif
735 static gboolean
736 is_field_on_inst (MonoClassField *field)
738 return mono_class_is_ginst (field->parent) && mono_class_get_generic_class (field->parent)->is_dynamic;
741 #ifndef DISABLE_REFLECTION_EMIT
742 static guint32
743 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObjectHandle f, MonoClassField *field)
745 MonoType *type;
746 guint32 token;
748 g_assert (field);
749 g_assert (field->parent);
751 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, MONO_HANDLE_RAW (f)));
752 if (token)
753 return token;
755 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) {
756 int index = field - field->parent->fields;
757 type = mono_field_get_type (&mono_class_get_generic_class (field->parent)->container_class->fields [index]);
758 } else {
759 type = mono_field_get_type (field);
761 token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
762 mono_field_get_name (field),
763 mono_dynimage_encode_fieldref_signature (assembly, field->parent->image, type));
764 mono_g_hash_table_insert (assembly->handleref_managed, MONO_HANDLE_RAW (f), GUINT_TO_POINTER(token));
765 return token;
768 static guint32
769 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
771 MonoDynamicTable *table;
772 guint32 *values;
773 guint32 token, mtoken = 0, sig;
774 MonoMethodInflated *imethod;
775 MonoMethod *declaring;
777 table = &assembly->tables [MONO_TABLE_METHODSPEC];
779 g_assert (method->is_inflated);
780 imethod = (MonoMethodInflated *) method;
781 declaring = imethod->declaring;
783 sig = mono_dynimage_encode_method_signature (assembly, mono_method_signature (declaring));
784 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
786 if (!mono_method_signature (declaring)->generic_param_count)
787 return mtoken;
789 switch (mono_metadata_token_table (mtoken)) {
790 case MONO_TABLE_MEMBERREF:
791 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
792 break;
793 case MONO_TABLE_METHOD:
794 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
795 break;
796 default:
797 g_assert_not_reached ();
800 sig = mono_dynimage_encode_generic_method_sig (assembly, mono_method_get_context (method));
802 if (assembly->save) {
803 alloc_table (table, table->rows + 1);
804 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
805 values [MONO_METHODSPEC_METHOD] = mtoken;
806 values [MONO_METHODSPEC_SIGNATURE] = sig;
809 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
810 table->next_idx ++;
812 return token;
815 static guint32
816 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
818 MonoMethodInflated *imethod;
819 guint32 token;
821 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
822 if (token)
823 return token;
825 g_assert (method->is_inflated);
826 imethod = (MonoMethodInflated *) method;
828 if (mono_method_signature (imethod->declaring)->generic_param_count) {
829 token = method_encode_methodspec (assembly, method);
830 } else {
831 guint32 sig = mono_dynimage_encode_method_signature (
832 assembly, mono_method_signature (imethod->declaring));
833 token = mono_image_get_memberref_token (
834 assembly, &method->klass->byval_arg, method->name, sig);
837 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
838 return token;
841 static guint32
842 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
844 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
845 guint32 sig, token;
847 sig = mono_dynimage_encode_method_signature (assembly, mono_method_signature (imethod->declaring));
848 token = mono_image_get_memberref_token (
849 assembly, &m->klass->byval_arg, m->name, sig);
851 return token;
854 static guint32
855 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelperHandle helper, MonoError *error)
857 guint32 idx;
858 MonoDynamicTable *table;
859 guint32 *values;
861 error_init (error);
863 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
864 idx = table->next_idx ++;
865 table->rows ++;
866 alloc_table (table, table->rows);
867 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
869 values [MONO_STAND_ALONE_SIGNATURE] =
870 mono_dynimage_encode_reflection_sighelper (assembly, helper, error);
871 return_val_if_nok (error, 0);
873 return idx;
876 static int
877 reflection_cc_to_file (int call_conv) {
878 switch (call_conv & 0x3) {
879 case 0:
880 case 1: return MONO_CALL_DEFAULT;
881 case 2: return MONO_CALL_VARARG;
882 default:
883 g_assert_not_reached ();
885 return 0;
887 #endif /* !DISABLE_REFLECTION_EMIT */
889 struct _ArrayMethod {
890 MonoType *parent;
891 MonoMethodSignature *sig;
892 char *name;
893 guint32 token;
896 void
897 mono_sre_array_method_free (ArrayMethod *am)
899 g_free (am->sig);
900 g_free (am->name);
901 g_free (am);
904 #ifndef DISABLE_REFLECTION_EMIT
905 static guint32
906 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethodHandle m, MonoError *error)
908 MonoMethodSignature *sig = NULL;
909 char *name = NULL;
911 error_init (error);
913 MonoArrayHandle parameters = MONO_HANDLE_NEW_GET (MonoArray, m, parameters);
914 guint32 nparams = mono_array_handle_length (parameters);
915 sig = (MonoMethodSignature *)g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
916 sig->hasthis = 1;
917 sig->sentinelpos = -1;
918 sig->call_convention = reflection_cc_to_file (MONO_HANDLE_GETVAL (m, call_conv));
919 sig->param_count = nparams;
920 MonoReflectionTypeHandle ret = MONO_HANDLE_NEW_GET (MonoReflectionType, m, ret);
921 if (!MONO_HANDLE_IS_NULL (ret)) {
922 sig->ret = mono_reflection_type_handle_mono_type (ret, error);
923 if (!is_ok (error))
924 goto fail;
925 } else
926 sig->ret = &mono_defaults.void_class->byval_arg;
928 MonoReflectionTypeHandle parent = MONO_HANDLE_NEW_GET (MonoReflectionType, m, parent);
929 MonoType *mtype = mono_reflection_type_handle_mono_type (parent, error);
930 if (!is_ok (error))
931 goto fail;
933 for (int i = 0; i < nparams; ++i) {
934 sig->params [i] = mono_type_array_get_and_resolve (parameters, i, error);
935 if (!is_ok (error))
936 goto fail;
939 MonoStringHandle mname = MONO_HANDLE_NEW_GET (MonoString, m, name);
940 name = mono_string_handle_to_utf8 (mname, error);
941 if (!is_ok (error))
942 goto fail;
944 ArrayMethod *am = NULL;
945 for (GList *tmp = assembly->array_methods; tmp; tmp = tmp->next) {
946 am = (ArrayMethod *)tmp->data;
947 if (strcmp (name, am->name) == 0 &&
948 mono_metadata_type_equal (am->parent, mtype) &&
949 mono_metadata_signature_equal (am->sig, sig)) {
950 g_free (name);
951 g_free (sig);
952 MONO_HANDLE_SETVAL (m, table_idx, guint32, am->token & 0xffffff);
953 return am->token;
956 am = g_new0 (ArrayMethod, 1);
957 am->name = name;
958 am->sig = sig;
959 am->parent = mtype;
960 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
961 mono_dynimage_encode_method_signature (assembly, sig));
962 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
963 MONO_HANDLE_SETVAL (m, table_idx, guint32, am->token & 0xffffff);
964 return am->token;
965 fail:
966 g_free (name);
967 g_free (sig);
968 return 0;
971 #endif
973 #ifndef DISABLE_REFLECTION_EMIT
976 * mono_image_insert_string:
977 * @module: module builder object
978 * @str: a string
980 * Insert @str into the user string stream of @module.
982 guint32
983 mono_image_insert_string (MonoReflectionModuleBuilderHandle ref_module, MonoStringHandle str, MonoError *error)
985 HANDLE_FUNCTION_ENTER ();
986 guint32 idx;
987 char buf [16];
988 char *b = buf;
989 guint32 token = 0;
991 MonoDynamicImage *assembly = MONO_HANDLE_GETVAL (ref_module, dynamic_image);
992 if (!assembly) {
993 if (!mono_image_module_basic_init (ref_module, error))
994 goto leave;
996 assembly = MONO_HANDLE_GETVAL (ref_module, dynamic_image);
998 g_assert (assembly != NULL);
1000 if (assembly->save) {
1001 int32_t length = mono_string_length (MONO_HANDLE_RAW (str));
1002 mono_metadata_encode_value (1 | (length * 2), b, &b);
1003 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
1004 /* pinned */
1005 uint32_t gchandle = mono_gchandle_from_handle (MONO_HANDLE_CAST (MonoObject, str), TRUE);
1006 const char *p = (const char*)mono_string_chars (MONO_HANDLE_RAW (str));
1007 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1009 char *swapped = g_malloc (2 * length);
1011 swap_with_size (swapped, p, 2, length);
1012 mono_image_add_stream_data (&assembly->us, swapped, length * 2);
1013 g_free (swapped);
1015 #else
1016 mono_image_add_stream_data (&assembly->us, p, length * 2);
1017 #endif
1018 mono_gchandle_free (gchandle);
1019 mono_image_add_stream_data (&assembly->us, "", 1);
1020 } else {
1021 idx = assembly->us.index ++;
1024 token = MONO_TOKEN_STRING | idx;
1025 mono_dynamic_image_register_token (assembly, token, MONO_HANDLE_CAST (MonoObject, str), MONO_DYN_IMAGE_TOK_NEW);
1027 leave:
1028 HANDLE_FUNCTION_RETURN_VAL (token);
1031 static guint32
1032 create_method_token (MonoDynamicImage *assembly, MonoMethod *method, MonoArrayHandle opt_param_types, MonoError *error)
1034 guint32 sig_token, parent;
1037 int nargs = mono_array_handle_length (opt_param_types);
1038 MonoMethodSignature *old = mono_method_signature (method);
1039 MonoMethodSignature *sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
1041 sig->hasthis = old->hasthis;
1042 sig->explicit_this = old->explicit_this;
1043 sig->call_convention = old->call_convention;
1044 sig->generic_param_count = old->generic_param_count;
1045 sig->param_count = old->param_count + nargs;
1046 sig->sentinelpos = old->param_count;
1047 sig->ret = old->ret;
1049 for (int i = 0; i < old->param_count; i++)
1050 sig->params [i] = old->params [i];
1052 MonoReflectionTypeHandle rt = MONO_HANDLE_NEW (MonoReflectionType, NULL);
1053 for (int i = 0; i < nargs; i++) {
1054 MONO_HANDLE_ARRAY_GETREF (rt, opt_param_types, i);
1055 sig->params [old->param_count + i] = mono_reflection_type_handle_mono_type (rt, error);
1056 if (!is_ok (error)) goto fail;
1059 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
1060 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
1061 parent >>= MONO_TYPEDEFORREF_BITS;
1063 parent <<= MONO_MEMBERREF_PARENT_BITS;
1064 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
1066 sig_token = mono_dynimage_encode_method_signature (assembly, sig);
1067 guint32 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
1068 g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
1069 return token;
1070 fail:
1071 return 0;
1074 guint32
1075 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObjectHandle obj, MonoArrayHandle opt_param_types, MonoError *error)
1077 guint32 token = 0;
1079 error_init (error);
1081 MonoClass *klass = mono_handle_class (obj);
1082 if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
1083 MonoReflectionMethodHandle ref_method = MONO_HANDLE_CAST (MonoReflectionMethod, obj);
1084 MonoMethod *method = MONO_HANDLE_GETVAL (ref_method, method);
1085 g_assert (!MONO_HANDLE_IS_NULL (opt_param_types) && (mono_method_signature (method)->sentinelpos >= 0));
1086 token = create_method_token (assembly, method, opt_param_types, error);
1087 if (!is_ok (error))
1088 goto fail;
1089 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
1090 g_assert_not_reached ();
1091 } else {
1092 g_error ("requested method token for %s\n", klass->name);
1095 mono_dynamic_image_register_token (assembly, token, obj, MONO_DYN_IMAGE_TOK_NEW);
1096 return token;
1097 fail:
1098 g_assert (!mono_error_ok (error));
1099 return 0;
1103 * mono_image_create_token:
1104 * @assembly: a dynamic assembly
1105 * @obj:
1106 * @register_token: Whenever to register the token in the assembly->tokens hash.
1108 * Get a token to insert in the IL code stream for the given MemberInfo.
1109 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
1110 * the table_idx-es were recomputed, so registering the token would overwrite an existing
1111 * entry.
1113 guint32
1114 mono_image_create_token (MonoDynamicImage *assembly, MonoObjectHandle obj,
1115 gboolean create_open_instance, gboolean register_token,
1116 MonoError *error)
1118 guint32 token = 0;
1120 error_init (error);
1122 MonoClass *klass = mono_handle_class (obj);
1124 /* Check for user defined reflection objects */
1125 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
1126 if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0)) {
1127 mono_error_set_not_supported (error, "User defined subclasses of System.Type are not yet supported");
1128 return 0;
1131 /* This function is called from ModuleBuilder:getToken multiple times for the same objects */
1132 int how_collide = MONO_DYN_IMAGE_TOK_SAME_OK;
1134 if (strcmp (klass->name, "RuntimeType") == 0) {
1135 MonoType *type = mono_reflection_type_handle_mono_type (MONO_HANDLE_CAST (MonoReflectionType, obj), error);
1136 return_val_if_nok (error, 0);
1137 MonoClass *mc = mono_class_from_mono_type (type);
1138 token = mono_metadata_token_from_dor (
1139 mono_dynimage_encode_typedef_or_ref_full (assembly, type, !mono_class_is_gtd (mc) || create_open_instance));
1140 /* If it's a RuntimeType now, we could have registered a
1141 * TypeBuilder for it before, so replacing is okay. */
1142 how_collide = MONO_DYN_IMAGE_TOK_REPLACE;
1143 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
1144 strcmp (klass->name, "MonoMethod") == 0) {
1145 MonoReflectionMethodHandle m = MONO_HANDLE_CAST (MonoReflectionMethod, obj);
1146 MonoMethod *method = MONO_HANDLE_GETVAL (m, method);
1147 if (method->is_inflated) {
1148 if (create_open_instance)
1149 token = mono_image_get_methodspec_token (assembly, method);
1150 else
1151 token = mono_image_get_inflated_method_token (assembly, method);
1152 } else if ((method->klass->image == &assembly->image) &&
1153 !mono_class_is_ginst (method->klass)) {
1154 static guint32 method_table_idx = 0xffffff;
1155 if (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 = method->token;
1161 how_collide = MONO_DYN_IMAGE_TOK_REPLACE;
1162 } else {
1164 * Each token should have a unique index, but the indexes are
1165 * assigned by managed code, so we don't know about them. An
1166 * easy solution is to count backwards...
1168 method_table_idx --;
1169 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
1170 how_collide = MONO_DYN_IMAGE_TOK_NEW;
1172 } else {
1173 token = mono_image_get_methodref_token (assembly, method, create_open_instance);
1175 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
1176 } else if (strcmp (klass->name, "MonoField") == 0) {
1177 MonoReflectionFieldHandle f = MONO_HANDLE_CAST (MonoReflectionField, obj);
1178 MonoClassField *field = MONO_HANDLE_GETVAL (f, field);
1179 if ((field->parent->image == &assembly->image) && !is_field_on_inst (field)) {
1180 static guint32 field_table_idx = 0xffffff;
1181 field_table_idx --;
1182 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
1183 how_collide = MONO_DYN_IMAGE_TOK_NEW;
1184 } else {
1185 token = mono_image_get_fieldref_token (assembly, obj, field);
1187 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
1188 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
1189 MonoReflectionArrayMethodHandle m = MONO_HANDLE_CAST (MonoReflectionArrayMethod, obj);
1190 token = mono_image_get_array_token (assembly, m, error);
1191 return_val_if_nok (error, 0);
1192 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
1193 MonoReflectionSigHelperHandle s = MONO_HANDLE_CAST (MonoReflectionSigHelper, obj);
1194 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s, error);
1195 return_val_if_nok (error, 0);
1196 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
1197 MonoType *type = mono_reflection_type_handle_mono_type (MONO_HANDLE_CAST (MonoReflectionType, obj), error);
1198 return_val_if_nok (error, 0);
1199 token = mono_metadata_token_from_dor (
1200 mono_image_typedef_or_ref (assembly, type));
1201 } else {
1202 g_error ("requested token for %s\n", klass->name);
1205 if (register_token)
1206 mono_dynamic_image_register_token (assembly, token, obj, how_collide);
1208 return token;
1212 #endif
1214 #ifndef DISABLE_REFLECTION_EMIT
1216 static gboolean
1217 assemblybuilderaccess_can_refonlyload (guint32 access)
1219 return (access & 0x4) != 0;
1222 static gboolean
1223 assemblybuilderaccess_can_run (guint32 access)
1225 return (access & MonoAssemblyBuilderAccess_Run) != 0;
1228 static gboolean
1229 assemblybuilderaccess_can_save (guint32 access)
1231 return (access & MonoAssemblyBuilderAccess_Save) != 0;
1236 * mono_reflection_dynimage_basic_init:
1237 * @assembly: an assembly builder object
1239 * Create the MonoImage that represents the assembly builder and setup some
1240 * of the helper hash table and the basic metadata streams.
1242 void
1243 mono_reflection_dynimage_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
1245 MonoError error;
1246 MonoDynamicAssembly *assembly;
1247 MonoDynamicImage *image;
1248 MonoDomain *domain = mono_object_domain (assemblyb);
1250 if (assemblyb->dynamic_assembly)
1251 return;
1253 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
1255 MONO_PROFILER_RAISE (assembly_loading, (&assembly->assembly));
1257 assembly->assembly.ref_count = 1;
1258 assembly->assembly.dynamic = TRUE;
1259 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
1260 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
1261 assembly->assembly.basedir = mono_string_to_utf8_checked (assemblyb->dir, &error);
1262 if (mono_error_set_pending_exception (&error))
1263 return;
1264 if (assemblyb->culture) {
1265 assembly->assembly.aname.culture = mono_string_to_utf8_checked (assemblyb->culture, &error);
1266 if (mono_error_set_pending_exception (&error))
1267 return;
1268 } else
1269 assembly->assembly.aname.culture = g_strdup ("");
1271 if (assemblyb->version) {
1272 char *vstr = mono_string_to_utf8_checked (assemblyb->version, &error);
1273 if (mono_error_set_pending_exception (&error))
1274 return;
1275 char **version = g_strsplit (vstr, ".", 4);
1276 char **parts = version;
1277 assembly->assembly.aname.major = atoi (*parts++);
1278 assembly->assembly.aname.minor = atoi (*parts++);
1279 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
1280 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
1282 g_strfreev (version);
1283 g_free (vstr);
1284 } else {
1285 assembly->assembly.aname.major = 0;
1286 assembly->assembly.aname.minor = 0;
1287 assembly->assembly.aname.build = 0;
1288 assembly->assembly.aname.revision = 0;
1291 assembly->assembly.ref_only = assemblybuilderaccess_can_refonlyload (assemblyb->access);
1292 assembly->run = assemblybuilderaccess_can_run (assemblyb->access);
1293 assembly->save = assemblybuilderaccess_can_save (assemblyb->access);
1294 assembly->domain = domain;
1296 char *assembly_name = mono_string_to_utf8_checked (assemblyb->name, &error);
1297 if (mono_error_set_pending_exception (&error))
1298 return;
1299 image = mono_dynamic_image_create (assembly, assembly_name, g_strdup ("RefEmit_YouForgotToDefineAModule"));
1300 image->initial_image = TRUE;
1301 assembly->assembly.aname.name = image->image.name;
1302 assembly->assembly.image = &image->image;
1303 if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
1304 /* -1 to correct for the trailing NULL byte */
1305 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
1306 g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
1308 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);
1311 mono_domain_assemblies_lock (domain);
1312 domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
1313 mono_domain_assemblies_unlock (domain);
1315 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
1317 MONO_PROFILER_RAISE (assembly_loaded, (&assembly->assembly));
1319 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
1322 #endif /* !DISABLE_REFLECTION_EMIT */
1324 #ifndef DISABLE_REFLECTION_EMIT
1325 static gpointer
1326 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
1328 return CACHE_OBJECT (MonoReflectionAssembly *, assembly, &res->object, NULL);
1331 static MonoReflectionModuleBuilderHandle
1332 register_module (MonoDomain *domain, MonoReflectionModuleBuilderHandle res, MonoDynamicImage *module)
1334 return CACHE_OBJECT_HANDLE (MonoReflectionModuleBuilderHandle, module, MONO_HANDLE_CAST (MonoObject, res), NULL);
1337 static gboolean
1338 image_module_basic_init (MonoReflectionModuleBuilderHandle moduleb, MonoError *error)
1340 error_init (error);
1341 MonoDomain *domain = MONO_HANDLE_DOMAIN (moduleb);
1342 MonoDynamicImage *image = MONO_HANDLE_GETVAL (moduleb, dynamic_image);
1343 MonoReflectionAssemblyBuilderHandle ab = MONO_HANDLE_NEW (MonoReflectionAssemblyBuilder, NULL);
1344 MONO_HANDLE_GET (ab, moduleb, assemblyb);
1345 if (!image) {
1347 * FIXME: we already created an image in mono_reflection_dynimage_basic_init (), but
1348 * we don't know which module it belongs to, since that is only
1349 * determined at assembly save time.
1351 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
1352 MonoStringHandle abname = MONO_HANDLE_NEW_GET (MonoString, ab, name);
1353 char *name = mono_string_handle_to_utf8 (abname, error);
1354 return_val_if_nok (error, FALSE);
1355 MonoStringHandle modfqname = MONO_HANDLE_NEW_GET (MonoString, MONO_HANDLE_CAST (MonoReflectionModule, moduleb), fqname);
1356 char *fqname = mono_string_handle_to_utf8 (modfqname, error);
1357 if (!is_ok (error)) {
1358 g_free (name);
1359 return FALSE;
1361 MonoDynamicAssembly *dynamic_assembly = MONO_HANDLE_GETVAL (ab, dynamic_assembly);
1362 image = mono_dynamic_image_create (dynamic_assembly, name, fqname);
1364 MONO_HANDLE_SETVAL (MONO_HANDLE_CAST (MonoReflectionModule, moduleb), image, MonoImage*, &image->image);
1365 MONO_HANDLE_SETVAL (moduleb, dynamic_image, MonoDynamicImage*, image);
1366 register_module (domain, moduleb, image);
1368 /* register the module with the assembly */
1369 MonoImage *ass = dynamic_assembly->assembly.image;
1370 int module_count = ass->module_count;
1371 MonoImage **new_modules = g_new0 (MonoImage *, module_count + 1);
1373 if (ass->modules)
1374 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
1375 new_modules [module_count] = &image->image;
1376 mono_image_addref (&image->image);
1378 g_free (ass->modules);
1379 ass->modules = new_modules;
1380 ass->module_count ++;
1382 return TRUE;
1385 static gboolean
1386 mono_image_module_basic_init (MonoReflectionModuleBuilderHandle moduleb, MonoError *error)
1388 error_init (error);
1389 return image_module_basic_init (moduleb, error);
1392 #endif
1394 static gboolean
1395 is_corlib_type (MonoClass *klass)
1397 return klass->image == mono_defaults.corlib;
1400 #define check_corlib_type_cached(_class, _namespace, _name) do { \
1401 static MonoClass *cached_class; \
1402 if (cached_class) \
1403 return cached_class == _class; \
1404 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
1405 cached_class = _class; \
1406 return TRUE; \
1408 return FALSE; \
1409 } while (0) \
1412 MonoType*
1413 mono_type_array_get_and_resolve (MonoArrayHandle array, int idx, MonoError *error)
1415 HANDLE_FUNCTION_ENTER();
1416 error_init (error);
1417 MonoReflectionTypeHandle t = MONO_HANDLE_NEW (MonoReflectionType, NULL);
1418 MONO_HANDLE_ARRAY_GETREF (t, array, idx);
1419 MonoType *result = mono_reflection_type_handle_mono_type (t, error);
1420 HANDLE_FUNCTION_RETURN_VAL (result);
1424 #ifndef DISABLE_REFLECTION_EMIT
1425 static gboolean
1426 is_sre_array (MonoClass *klass)
1428 check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
1431 static gboolean
1432 is_sre_byref (MonoClass *klass)
1434 check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
1437 static gboolean
1438 is_sre_pointer (MonoClass *klass)
1440 check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
1443 static gboolean
1444 is_sre_generic_instance (MonoClass *klass)
1446 check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilderInstantiation");
1449 static gboolean
1450 is_sre_type_builder (MonoClass *klass)
1452 check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
1455 static gboolean
1456 is_sre_method_builder (MonoClass *klass)
1458 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
1461 gboolean
1462 mono_is_sre_ctor_builder (MonoClass *klass)
1464 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
1467 static gboolean
1468 is_sre_field_builder (MonoClass *klass)
1470 check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
1473 static gboolean
1474 is_sre_gparam_builder (MonoClass *klass)
1476 check_corlib_type_cached (klass, "System.Reflection.Emit", "GenericTypeParameterBuilder");
1479 static gboolean
1480 is_sre_enum_builder (MonoClass *klass)
1482 check_corlib_type_cached (klass, "System.Reflection.Emit", "EnumBuilder");
1485 gboolean
1486 mono_is_sre_method_on_tb_inst (MonoClass *klass)
1488 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
1491 gboolean
1492 mono_is_sre_ctor_on_tb_inst (MonoClass *klass)
1494 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
1497 static MonoReflectionTypeHandle
1498 mono_reflection_type_get_underlying_system_type (MonoReflectionTypeHandle t, MonoError *error)
1500 static MonoMethod *method_get_underlying_system_type = NULL;
1501 HANDLE_FUNCTION_ENTER ();
1503 error_init (error);
1505 if (!method_get_underlying_system_type)
1506 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
1508 MonoReflectionTypeHandle rt = MONO_HANDLE_NEW (MonoReflectionType, NULL);
1510 MonoMethod *usertype_method = mono_object_handle_get_virtual_method (MONO_HANDLE_CAST (MonoObject, t), method_get_underlying_system_type, error);
1511 if (!is_ok (error))
1512 goto leave;
1514 MONO_HANDLE_ASSIGN (rt, MONO_HANDLE_NEW (MonoReflectionType, mono_runtime_invoke_checked (usertype_method, MONO_HANDLE_RAW (t), NULL, error)));
1516 leave:
1517 HANDLE_FUNCTION_RETURN_REF (MonoReflectionType, rt);
1520 MonoType*
1521 mono_reflection_type_get_handle (MonoReflectionType* ref_raw, MonoError *error)
1523 HANDLE_FUNCTION_ENTER ();
1524 error_init (error);
1525 MONO_HANDLE_DCL (MonoReflectionType, ref);
1526 MonoType *result = mono_reflection_type_handle_mono_type (ref, error);
1527 HANDLE_FUNCTION_RETURN_VAL (result);
1530 static MonoType*
1531 reflection_instance_handle_mono_type (MonoReflectionGenericClassHandle ref_gclass, MonoError *error)
1533 HANDLE_FUNCTION_ENTER ();
1534 MonoType *result = NULL;
1535 MonoType **types = NULL;
1537 MonoArrayHandle typeargs = MONO_HANDLE_NEW_GET (MonoArray, ref_gclass, type_arguments);
1538 int count = mono_array_handle_length (typeargs);
1539 types = g_new0 (MonoType*, count);
1540 MonoReflectionTypeHandle t = MONO_HANDLE_NEW (MonoReflectionType, NULL);
1541 for (int i = 0; i < count; ++i) {
1542 MONO_HANDLE_ARRAY_GETREF (t, typeargs, i);
1543 types [i] = mono_reflection_type_handle_mono_type (t, error);
1544 if (!types[i] || !is_ok (error)) {
1545 goto leave;
1548 /* Need to resolve the generic_type in order for it to create its generic context. */
1549 MonoReflectionTypeHandle ref_gtd = MONO_HANDLE_NEW_GET (MonoReflectionType, ref_gclass, generic_type);
1550 MonoType *gtd = mono_reflection_type_handle_mono_type (ref_gtd, error);
1551 if (!is_ok (error)) {
1552 goto leave;
1554 MonoClass *gtd_klass = mono_class_from_mono_type (gtd);
1555 if (is_sre_type_builder (mono_handle_class (ref_gtd))) {
1556 reflection_setup_internal_class (MONO_HANDLE_CAST (MonoReflectionTypeBuilder, ref_gtd), error);
1557 if (!is_ok (error)) {
1558 goto leave;
1561 g_assert (count == 0 || mono_class_is_gtd (gtd_klass));
1562 result = mono_reflection_bind_generic_parameters (ref_gtd, count, types, error);
1563 if (!is_ok (error))
1564 goto leave;
1565 g_assert (result);
1566 MONO_HANDLE_SETVAL (MONO_HANDLE_CAST (MonoReflectionType, ref_gclass), type, MonoType*, result);
1567 leave:
1568 g_free (types);
1569 HANDLE_FUNCTION_RETURN_VAL (result);
1572 static MonoType*
1573 reflection_param_handle_mono_type (MonoReflectionGenericParamHandle ref_gparam, MonoError *error)
1575 HANDLE_FUNCTION_ENTER ();
1576 error_init (error);
1577 MonoType *result = NULL;
1580 MonoReflectionTypeBuilderHandle ref_tbuilder = MONO_HANDLE_NEW_GET (MonoReflectionTypeBuilder, ref_gparam, tbuilder);
1581 MonoReflectionModuleBuilderHandle ref_module = MONO_HANDLE_NEW_GET (MonoReflectionModuleBuilder, ref_tbuilder, module);
1582 MonoDynamicImage *dynamic_image = MONO_HANDLE_GETVAL (ref_module, dynamic_image);
1583 MonoImage *image = &dynamic_image->image;
1585 MonoGenericParamFull *param = mono_image_new0 (image, MonoGenericParamFull, 1);
1587 MonoStringHandle ref_name = MONO_HANDLE_NEW_GET (MonoString, ref_gparam, name);
1588 param->info.name = mono_string_to_utf8_image (image, ref_name, error);
1589 mono_error_assert_ok (error);
1590 param->param.num = MONO_HANDLE_GETVAL (ref_gparam, index);
1592 MonoReflectionMethodBuilderHandle ref_mbuilder = MONO_HANDLE_NEW_GET (MonoReflectionMethodBuilder, ref_gparam, mbuilder);
1593 if (!MONO_HANDLE_IS_NULL (ref_mbuilder)) {
1594 MonoGenericContainer *generic_container = MONO_HANDLE_GETVAL (ref_mbuilder, generic_container);
1595 if (!generic_container) {
1596 generic_container = (MonoGenericContainer *)mono_image_alloc0 (image, sizeof (MonoGenericContainer));
1597 generic_container->is_method = TRUE;
1599 * Cannot set owner.method, since the MonoMethod is not created yet.
1600 * Set the image field instead, so type_in_image () works.
1602 generic_container->is_anonymous = TRUE;
1603 generic_container->owner.image = image;
1604 MONO_HANDLE_SETVAL (ref_mbuilder, generic_container, MonoGenericContainer*, generic_container);
1606 param->param.owner = generic_container;
1607 } else {
1608 MonoType *type = mono_reflection_type_handle_mono_type (MONO_HANDLE_CAST (MonoReflectionType, ref_tbuilder), error);
1609 if (!is_ok (error))
1610 goto leave;
1611 MonoClass *owner = mono_class_from_mono_type (type);
1612 g_assert (mono_class_is_gtd (owner));
1613 param->param.owner = mono_class_get_generic_container (owner);
1616 MonoClass *pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
1618 result = &pklass->byval_arg;
1620 mono_class_set_ref_info (pklass, MONO_HANDLE_CAST (MonoObject, ref_gparam));
1621 mono_image_append_class_to_reflection_info_set (pklass);
1623 MONO_HANDLE_SETVAL (MONO_HANDLE_CAST (MonoReflectionType, ref_gparam), type, MonoType*, result);
1625 leave:
1626 HANDLE_FUNCTION_RETURN_VAL (result);
1629 static MonoType*
1630 mono_type_array_get_and_resolve_raw (MonoArray* array_raw, int idx, MonoError *error)
1632 HANDLE_FUNCTION_ENTER(); /* FIXME callers of mono_type_array_get_and_resolve_raw should use handles */
1633 error_init (error);
1634 MONO_HANDLE_DCL (MonoArray, array);
1635 MonoType *result = mono_type_array_get_and_resolve (array, idx, error);
1636 HANDLE_FUNCTION_RETURN_VAL (result);
1639 MonoType*
1640 mono_reflection_type_handle_mono_type (MonoReflectionTypeHandle ref, MonoError *error)
1642 HANDLE_FUNCTION_ENTER ();
1643 error_init (error);
1645 MonoType* result = NULL;
1647 g_assert (ref);
1648 if (MONO_HANDLE_IS_NULL (ref))
1649 goto leave;
1650 MonoType *t = MONO_HANDLE_GETVAL (ref, type);
1651 if (t) {
1652 result = t;
1653 goto leave;
1656 if (mono_reflection_is_usertype (ref)) {
1657 MONO_HANDLE_ASSIGN (ref, mono_reflection_type_get_underlying_system_type (ref, error));
1658 if (!is_ok (error) || MONO_HANDLE_IS_NULL (ref) || mono_reflection_is_usertype (ref))
1659 goto leave;
1660 t = MONO_HANDLE_GETVAL (ref, type);
1661 if (t) {
1662 result = t;
1663 goto leave;
1667 MonoClass *klass = mono_handle_class (ref);
1669 if (is_sre_array (klass)) {
1670 MonoReflectionArrayTypeHandle sre_array = MONO_HANDLE_CAST (MonoReflectionArrayType, ref);
1671 MonoReflectionTypeHandle ref_element = MONO_HANDLE_NEW_GET (MonoReflectionType, sre_array, element_type);
1672 MonoType *base = mono_reflection_type_handle_mono_type (ref_element, error);
1673 if (!is_ok (error))
1674 goto leave;
1675 g_assert (base);
1676 gint32 rank = MONO_HANDLE_GETVAL (sre_array, rank);
1677 MonoClass *eclass = mono_class_from_mono_type (base);
1678 result = mono_image_new0 (eclass->image, MonoType, 1);
1679 if (rank == 0) {
1680 result->type = MONO_TYPE_SZARRAY;
1681 result->data.klass = eclass;
1682 } else {
1683 MonoArrayType *at = (MonoArrayType *)mono_image_alloc0 (eclass->image, sizeof (MonoArrayType));
1684 result->type = MONO_TYPE_ARRAY;
1685 result->data.array = at;
1686 at->eklass = eclass;
1687 at->rank = rank;
1689 MONO_HANDLE_SETVAL (ref, type, MonoType*, result);
1690 } else if (is_sre_byref (klass)) {
1691 MonoReflectionDerivedTypeHandle sre_byref = MONO_HANDLE_CAST (MonoReflectionDerivedType, ref);
1692 MonoReflectionTypeHandle ref_element = MONO_HANDLE_NEW_GET (MonoReflectionType, sre_byref, element_type);
1693 MonoType *base = mono_reflection_type_handle_mono_type (ref_element, error);
1694 if (!is_ok (error))
1695 goto leave;
1696 g_assert (base);
1697 result = &mono_class_from_mono_type (base)->this_arg;
1698 MONO_HANDLE_SETVAL (ref, type, MonoType*, result);
1699 } else if (is_sre_pointer (klass)) {
1700 MonoReflectionDerivedTypeHandle sre_pointer = MONO_HANDLE_CAST (MonoReflectionDerivedType, ref);
1701 MonoReflectionTypeHandle ref_element = MONO_HANDLE_NEW_GET (MonoReflectionType, sre_pointer, element_type);
1702 MonoType *base = mono_reflection_type_handle_mono_type (ref_element, error);
1703 if (!is_ok (error))
1704 goto leave;
1705 g_assert (base);
1706 result = &mono_ptr_class_get (base)->byval_arg;
1707 MONO_HANDLE_SETVAL (ref, type, MonoType*, result);
1708 } else if (is_sre_generic_instance (klass)) {
1709 result = reflection_instance_handle_mono_type (MONO_HANDLE_CAST (MonoReflectionGenericClass, ref), error);
1710 } else if (is_sre_gparam_builder (klass)) {
1711 result = reflection_param_handle_mono_type (MONO_HANDLE_CAST (MonoReflectionGenericParam, ref), error);
1712 } else if (is_sre_enum_builder (klass)) {
1713 MonoReflectionEnumBuilderHandle ref_ebuilder = MONO_HANDLE_CAST (MonoReflectionEnumBuilder, ref);
1715 MonoReflectionTypeHandle ref_tb = MONO_HANDLE_NEW_GET (MonoReflectionType, ref_ebuilder, tb);
1716 result = mono_reflection_type_handle_mono_type (ref_tb, error);
1717 } else if (is_sre_type_builder (klass)) {
1718 MonoReflectionTypeBuilderHandle ref_tb = MONO_HANDLE_CAST (MonoReflectionTypeBuilder, ref);
1720 /* This happens when a finished type references an unfinished one. Have to create the minimal type */
1721 reflection_setup_internal_class (ref_tb, error);
1722 mono_error_assert_ok (error);
1723 result = MONO_HANDLE_GETVAL (ref, type);
1724 } else {
1725 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
1727 leave:
1728 HANDLE_FUNCTION_RETURN_VAL (result);
1732 * LOCKING: Assumes the loader lock is held.
1734 static MonoMethodSignature*
1735 parameters_to_signature (MonoImage *image, MonoArrayHandle parameters, MonoError *error) {
1736 MonoMethodSignature *sig;
1737 int count, i;
1739 error_init (error);
1741 count = MONO_HANDLE_IS_NULL (parameters) ? 0 : mono_array_handle_length (parameters);
1743 sig = (MonoMethodSignature *)mono_image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
1744 sig->param_count = count;
1745 sig->sentinelpos = -1; /* FIXME */
1746 for (i = 0; i < count; ++i) {
1747 sig->params [i] = mono_type_array_get_and_resolve (parameters, i, error);
1748 if (!is_ok (error)) {
1749 image_g_free (image, sig);
1750 return NULL;
1753 return sig;
1757 * LOCKING: Assumes the loader lock is held.
1759 static MonoMethodSignature*
1760 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilderHandle ctor, MonoError *error) {
1761 MonoMethodSignature *sig;
1763 error_init (error);
1765 sig = parameters_to_signature (image, MONO_HANDLE_NEW_GET (MonoArray, ctor, parameters), error);
1766 return_val_if_nok (error, NULL);
1767 sig->hasthis = MONO_HANDLE_GETVAL (ctor, attrs) & METHOD_ATTRIBUTE_STATIC? 0: 1;
1768 sig->ret = &mono_defaults.void_class->byval_arg;
1769 return sig;
1772 static MonoMethodSignature*
1773 ctor_builder_to_signature_raw (MonoImage *image, MonoReflectionCtorBuilder* ctor_raw, MonoError *error) {
1774 HANDLE_FUNCTION_ENTER();
1775 MONO_HANDLE_DCL (MonoReflectionCtorBuilder, ctor);
1776 MonoMethodSignature *sig = ctor_builder_to_signature (image, ctor, error);
1777 HANDLE_FUNCTION_RETURN_VAL (sig);
1780 * LOCKING: Assumes the loader lock is held.
1782 static MonoMethodSignature*
1783 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilderHandle method, MonoError *error) {
1784 MonoMethodSignature *sig;
1786 error_init (error);
1788 sig = parameters_to_signature (image, MONO_HANDLE_NEW_GET(MonoArray, method, parameters), error);
1789 return_val_if_nok (error, NULL);
1790 sig->hasthis = MONO_HANDLE_GETVAL (method, attrs) & METHOD_ATTRIBUTE_STATIC? 0: 1;
1791 MonoReflectionTypeHandle rtype = MONO_HANDLE_NEW_GET (MonoReflectionType, method, rtype);
1792 if (!MONO_HANDLE_IS_NULL (rtype)) {
1793 sig->ret = mono_reflection_type_handle_mono_type (rtype, error);
1794 if (!is_ok (error)) {
1795 image_g_free (image, sig);
1796 return NULL;
1798 } else {
1799 sig->ret = &mono_defaults.void_class->byval_arg;
1801 MonoArrayHandle generic_params = MONO_HANDLE_NEW_GET (MonoArray, method, generic_params);
1802 sig->generic_param_count = MONO_HANDLE_IS_NULL (generic_params) ? 0 : mono_array_handle_length (generic_params);
1803 return sig;
1806 static MonoMethodSignature*
1807 dynamic_method_to_signature (MonoReflectionDynamicMethodHandle method, MonoError *error) {
1808 HANDLE_FUNCTION_ENTER ();
1809 MonoMethodSignature *sig = NULL;
1811 error_init (error);
1813 sig = parameters_to_signature (NULL, MONO_HANDLE_NEW_GET (MonoArray, method, parameters), error);
1814 if (!is_ok (error))
1815 goto leave;
1816 sig->hasthis = MONO_HANDLE_GETVAL (method, attrs) & METHOD_ATTRIBUTE_STATIC? 0: 1;
1817 MonoReflectionTypeHandle rtype = MONO_HANDLE_NEW_GET (MonoReflectionType, method, rtype);
1818 if (!MONO_HANDLE_IS_NULL (rtype)) {
1819 sig->ret = mono_reflection_type_handle_mono_type (rtype, error);
1820 if (!is_ok (error)) {
1821 g_free (sig);
1822 sig = NULL;
1823 goto leave;
1825 } else {
1826 sig->ret = &mono_defaults.void_class->byval_arg;
1828 sig->generic_param_count = 0;
1829 leave:
1830 HANDLE_FUNCTION_RETURN_VAL (sig);
1833 static void
1834 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type, MonoError *error)
1836 error_init (error);
1837 MonoClass *klass = mono_object_class (prop);
1838 if (strcmp (klass->name, "PropertyBuilder") == 0) {
1839 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
1840 *name = mono_string_to_utf8_checked (pb->name, error);
1841 return_if_nok (error);
1842 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type, error);
1843 } else {
1844 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
1845 *name = g_strdup (p->property->name);
1846 if (p->property->get)
1847 *type = mono_method_signature (p->property->get)->ret;
1848 else
1849 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
1853 static void
1854 get_field_name_and_type (MonoObject *field, char **name, MonoType **type, MonoError *error)
1856 error_init (error);
1857 MonoClass *klass = mono_object_class (field);
1858 if (strcmp (klass->name, "FieldBuilder") == 0) {
1859 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
1860 *name = mono_string_to_utf8_checked (fb->name, error);
1861 return_if_nok (error);
1862 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
1863 } else {
1864 MonoReflectionField *f = (MonoReflectionField *)field;
1865 *name = g_strdup (mono_field_get_name (f->field));
1866 *type = f->field->type;
1870 #else /* DISABLE_REFLECTION_EMIT */
1872 static gboolean
1873 is_sre_type_builder (MonoClass *klass)
1875 return FALSE;
1878 static gboolean
1879 is_sre_generic_instance (MonoClass *klass)
1881 return FALSE;
1884 gboolean
1885 mono_is_sre_ctor_builder (MonoClass *klass)
1887 return FALSE;
1890 gboolean
1891 mono_is_sre_method_on_tb_inst (MonoClass *klass)
1893 return FALSE;
1896 gboolean
1897 mono_is_sre_ctor_on_tb_inst (MonoClass *klass)
1899 return FALSE;
1902 #endif /* !DISABLE_REFLECTION_EMIT */
1905 static gboolean
1906 is_sr_mono_field (MonoClass *klass)
1908 check_corlib_type_cached (klass, "System.Reflection", "MonoField");
1911 gboolean
1912 mono_is_sr_mono_property (MonoClass *klass)
1914 check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
1917 static gboolean
1918 is_sr_mono_method (MonoClass *klass)
1920 check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
1923 gboolean
1924 mono_is_sr_mono_cmethod (MonoClass *klass)
1926 check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
1929 gboolean
1930 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
1932 return is_sr_mono_method (klass) || mono_is_sr_mono_cmethod (klass);
1935 gboolean
1936 mono_is_sre_type_builder (MonoClass *klass)
1938 return is_sre_type_builder (klass);
1941 gboolean
1942 mono_is_sre_generic_instance (MonoClass *klass)
1944 return is_sre_generic_instance (klass);
1950 * encode_cattr_value:
1951 * Encode a value in a custom attribute stream of bytes.
1952 * The value to encode is either supplied as an object in argument val
1953 * (valuetypes are boxed), or as a pointer to the data in the
1954 * argument argval.
1955 * @type represents the type of the value
1956 * @buffer is the start of the buffer
1957 * @p the current position in the buffer
1958 * @buflen contains the size of the buffer and is used to return the new buffer size
1959 * if this needs to be realloced.
1960 * @retbuffer and @retp return the start and the position of the buffer
1961 * @error set on error.
1963 static void
1964 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval, MonoError *error)
1966 MonoTypeEnum simple_type;
1968 error_init (error);
1969 if ((p-buffer) + 10 >= *buflen) {
1970 char *newbuf;
1971 *buflen *= 2;
1972 newbuf = (char *)g_realloc (buffer, *buflen);
1973 p = newbuf + (p-buffer);
1974 buffer = newbuf;
1976 if (!argval)
1977 argval = ((char*)arg + sizeof (MonoObject));
1978 simple_type = type->type;
1979 handle_enum:
1980 switch (simple_type) {
1981 case MONO_TYPE_BOOLEAN:
1982 case MONO_TYPE_U1:
1983 case MONO_TYPE_I1:
1984 *p++ = *argval;
1985 break;
1986 case MONO_TYPE_CHAR:
1987 case MONO_TYPE_U2:
1988 case MONO_TYPE_I2:
1989 swap_with_size (p, argval, 2, 1);
1990 p += 2;
1991 break;
1992 case MONO_TYPE_U4:
1993 case MONO_TYPE_I4:
1994 case MONO_TYPE_R4:
1995 swap_with_size (p, argval, 4, 1);
1996 p += 4;
1997 break;
1998 case MONO_TYPE_R8:
1999 swap_with_size (p, argval, 8, 1);
2000 p += 8;
2001 break;
2002 case MONO_TYPE_U8:
2003 case MONO_TYPE_I8:
2004 swap_with_size (p, argval, 8, 1);
2005 p += 8;
2006 break;
2007 case MONO_TYPE_VALUETYPE:
2008 if (type->data.klass->enumtype) {
2009 simple_type = mono_class_enum_basetype (type->data.klass)->type;
2010 goto handle_enum;
2011 } else {
2012 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
2014 break;
2015 case MONO_TYPE_STRING: {
2016 char *str;
2017 guint32 slen;
2018 if (!arg) {
2019 *p++ = 0xFF;
2020 break;
2022 str = mono_string_to_utf8_checked ((MonoString*)arg, error);
2023 return_if_nok (error);
2024 slen = strlen (str);
2025 if ((p-buffer) + 10 + slen >= *buflen) {
2026 char *newbuf;
2027 *buflen *= 2;
2028 *buflen += slen;
2029 newbuf = (char *)g_realloc (buffer, *buflen);
2030 p = newbuf + (p-buffer);
2031 buffer = newbuf;
2033 mono_metadata_encode_value (slen, p, &p);
2034 memcpy (p, str, slen);
2035 p += slen;
2036 g_free (str);
2037 break;
2039 case MONO_TYPE_CLASS: {
2040 char *str;
2041 guint32 slen;
2042 MonoType *arg_type;
2043 if (!arg) {
2044 *p++ = 0xFF;
2045 break;
2047 handle_type:
2048 arg_type = mono_reflection_type_get_handle ((MonoReflectionType*)arg, error);
2049 return_if_nok (error);
2051 str = type_get_qualified_name (arg_type, NULL);
2052 slen = strlen (str);
2053 if ((p-buffer) + 10 + slen >= *buflen) {
2054 char *newbuf;
2055 *buflen *= 2;
2056 *buflen += slen;
2057 newbuf = (char *)g_realloc (buffer, *buflen);
2058 p = newbuf + (p-buffer);
2059 buffer = newbuf;
2061 mono_metadata_encode_value (slen, p, &p);
2062 memcpy (p, str, slen);
2063 p += slen;
2064 g_free (str);
2065 break;
2067 case MONO_TYPE_SZARRAY: {
2068 int len, i;
2069 MonoClass *eclass, *arg_eclass;
2071 if (!arg) {
2072 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
2073 break;
2075 len = mono_array_length ((MonoArray*)arg);
2076 *p++ = len & 0xff;
2077 *p++ = (len >> 8) & 0xff;
2078 *p++ = (len >> 16) & 0xff;
2079 *p++ = (len >> 24) & 0xff;
2080 *retp = p;
2081 *retbuffer = buffer;
2082 eclass = type->data.klass;
2083 arg_eclass = mono_object_class (arg)->element_class;
2085 if (!eclass) {
2086 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
2087 eclass = mono_defaults.object_class;
2089 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
2090 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
2091 int elsize = mono_class_array_element_size (arg_eclass);
2092 for (i = 0; i < len; ++i) {
2093 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr, error);
2094 return_if_nok (error);
2095 elptr += elsize;
2097 } else if (eclass->valuetype && arg_eclass->valuetype) {
2098 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
2099 int elsize = mono_class_array_element_size (eclass);
2100 for (i = 0; i < len; ++i) {
2101 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr, error);
2102 return_if_nok (error);
2103 elptr += elsize;
2105 } else {
2106 for (i = 0; i < len; ++i) {
2107 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL, error);
2108 return_if_nok (error);
2111 break;
2113 case MONO_TYPE_OBJECT: {
2114 MonoClass *klass;
2115 char *str;
2116 guint32 slen;
2119 * The parameter type is 'object' but the type of the actual
2120 * argument is not. So we have to add type information to the blob
2121 * too. This is completely undocumented in the spec.
2124 if (arg == NULL) {
2125 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
2126 *p++ = 0xFF;
2127 break;
2130 klass = mono_object_class (arg);
2132 if (mono_object_isinst_checked (arg, mono_defaults.systemtype_class, error)) {
2133 *p++ = 0x50;
2134 goto handle_type;
2135 } else {
2136 return_if_nok (error);
2139 if (klass->enumtype) {
2140 *p++ = 0x55;
2141 } else if (klass == mono_defaults.string_class) {
2142 simple_type = MONO_TYPE_STRING;
2143 *p++ = 0x0E;
2144 goto handle_enum;
2145 } else if (klass->rank == 1) {
2146 *p++ = 0x1D;
2147 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
2148 /* See Partition II, Appendix B3 */
2149 *p++ = 0x51;
2150 else
2151 *p++ = klass->element_class->byval_arg.type;
2152 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL, error);
2153 return_if_nok (error);
2154 break;
2155 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
2156 *p++ = simple_type = klass->byval_arg.type;
2157 goto handle_enum;
2158 } else {
2159 g_error ("unhandled type in custom attr");
2161 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
2162 slen = strlen (str);
2163 if ((p-buffer) + 10 + slen >= *buflen) {
2164 char *newbuf;
2165 *buflen *= 2;
2166 *buflen += slen;
2167 newbuf = (char *)g_realloc (buffer, *buflen);
2168 p = newbuf + (p-buffer);
2169 buffer = newbuf;
2171 mono_metadata_encode_value (slen, p, &p);
2172 memcpy (p, str, slen);
2173 p += slen;
2174 g_free (str);
2175 simple_type = mono_class_enum_basetype (klass)->type;
2176 goto handle_enum;
2178 default:
2179 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
2181 *retp = p;
2182 *retbuffer = buffer;
2185 static void
2186 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
2188 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
2189 char *str = type_get_qualified_name (type, NULL);
2190 int slen = strlen (str);
2192 *p++ = 0x55;
2194 * This seems to be optional...
2195 * *p++ = 0x80;
2197 mono_metadata_encode_value (slen, p, &p);
2198 memcpy (p, str, slen);
2199 p += slen;
2200 g_free (str);
2201 } else if (type->type == MONO_TYPE_OBJECT) {
2202 *p++ = 0x51;
2203 } else if (type->type == MONO_TYPE_CLASS) {
2204 /* it should be a type: encode_cattr_value () has the check */
2205 *p++ = 0x50;
2206 } else {
2207 mono_metadata_encode_value (type->type, p, &p);
2208 if (type->type == MONO_TYPE_SZARRAY)
2209 /* See the examples in Partition VI, Annex B */
2210 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
2213 *retp = p;
2216 #ifndef DISABLE_REFLECTION_EMIT
2217 static void
2218 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value, MonoError *error)
2220 int len;
2222 error_init (error);
2224 /* Preallocate a large enough buffer */
2225 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
2226 char *str = type_get_qualified_name (type, NULL);
2227 len = strlen (str);
2228 g_free (str);
2229 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
2230 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
2231 len = strlen (str);
2232 g_free (str);
2233 } else {
2234 len = 0;
2236 len += strlen (name);
2238 if ((p-buffer) + 20 + len >= *buflen) {
2239 char *newbuf;
2240 *buflen *= 2;
2241 *buflen += len;
2242 newbuf = (char *)g_realloc (buffer, *buflen);
2243 p = newbuf + (p-buffer);
2244 buffer = newbuf;
2247 encode_field_or_prop_type (type, p, &p);
2249 len = strlen (name);
2250 mono_metadata_encode_value (len, p, &p);
2251 memcpy (p, name, len);
2252 p += len;
2253 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL, error);
2254 return_if_nok (error);
2255 *retp = p;
2256 *retbuffer = buffer;
2260 * mono_reflection_get_custom_attrs_blob:
2261 * \param ctor custom attribute constructor
2262 * \param ctorArgs arguments o the constructor
2263 * \param properties
2264 * \param propValues
2265 * \param fields
2266 * \param fieldValues
2267 * Creates the blob of data that needs to be saved in the metadata and that represents
2268 * the custom attributed described by \p ctor, \p ctorArgs etc.
2269 * \returns a \c Byte array representing the blob of data.
2271 MonoArray*
2272 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
2274 MonoError error;
2275 MonoArray *result = mono_reflection_get_custom_attrs_blob_checked (assembly, ctor, ctorArgs, properties, propValues, fields, fieldValues, &error);
2276 mono_error_cleanup (&error);
2277 return result;
2281 * mono_reflection_get_custom_attrs_blob_checked:
2282 * \param ctor custom attribute constructor
2283 * \param ctorArgs arguments o the constructor
2284 * \param properties
2285 * \param propValues
2286 * \param fields
2287 * \param fieldValues
2288 * \param error set on error
2289 * Creates the blob of data that needs to be saved in the metadata and that represents
2290 * the custom attributed described by \p ctor, \p ctorArgs etc.
2291 * \returns a \c Byte array representing the blob of data. On failure returns NULL and sets \p error.
2293 MonoArray*
2294 mono_reflection_get_custom_attrs_blob_checked (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues, MonoError *error)
2296 MonoArray *result = NULL;
2297 MonoMethodSignature *sig;
2298 MonoObject *arg;
2299 char *buffer, *p;
2300 guint32 buflen, i;
2302 error_init (error);
2304 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
2305 /* sig is freed later so allocate it in the heap */
2306 sig = ctor_builder_to_signature_raw (NULL, (MonoReflectionCtorBuilder*)ctor, error); /* FIXME use handles */
2307 if (!is_ok (error)) {
2308 g_free (sig);
2309 return NULL;
2311 } else {
2312 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
2315 g_assert (mono_array_length (ctorArgs) == sig->param_count);
2316 buflen = 256;
2317 p = buffer = (char *)g_malloc (buflen);
2318 /* write the prolog */
2319 *p++ = 1;
2320 *p++ = 0;
2321 for (i = 0; i < sig->param_count; ++i) {
2322 arg = mono_array_get (ctorArgs, MonoObject*, i);
2323 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL, error);
2324 if (!is_ok (error)) goto leave;
2326 i = 0;
2327 if (properties)
2328 i += mono_array_length (properties);
2329 if (fields)
2330 i += mono_array_length (fields);
2331 *p++ = i & 0xff;
2332 *p++ = (i >> 8) & 0xff;
2333 if (properties) {
2334 MonoObject *prop;
2335 for (i = 0; i < mono_array_length (properties); ++i) {
2336 MonoType *ptype;
2337 char *pname;
2339 prop = (MonoObject *)mono_array_get (properties, gpointer, i);
2340 get_prop_name_and_type (prop, &pname, &ptype, error);
2341 if (!is_ok (error)) goto leave;
2342 *p++ = 0x54; /* PROPERTY signature */
2343 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i), error);
2344 g_free (pname);
2345 if (!is_ok (error)) goto leave;
2349 if (fields) {
2350 MonoObject *field;
2351 for (i = 0; i < mono_array_length (fields); ++i) {
2352 MonoType *ftype;
2353 char *fname;
2355 field = (MonoObject *)mono_array_get (fields, gpointer, i);
2356 get_field_name_and_type (field, &fname, &ftype, error);
2357 if (!is_ok (error)) goto leave;
2358 *p++ = 0x53; /* FIELD signature */
2359 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i), error);
2360 g_free (fname);
2361 if (!is_ok (error)) goto leave;
2365 g_assert (p - buffer <= buflen);
2366 buflen = p - buffer;
2367 result = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, buflen, error);
2368 if (!is_ok (error))
2369 goto leave;
2370 p = mono_array_addr (result, char, 0);
2371 memcpy (p, buffer, buflen);
2372 leave:
2373 g_free (buffer);
2374 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
2375 g_free (sig);
2376 return result;
2379 static gboolean
2380 reflection_setup_class_hierarchy (GHashTable *unparented, MonoError *error)
2382 error_init (error);
2384 mono_loader_lock ();
2386 MonoType *parent_type;
2387 MonoType *child_type;
2388 GHashTableIter iter;
2390 g_hash_table_iter_init (&iter, unparented);
2392 while (g_hash_table_iter_next (&iter, (gpointer *) &child_type, (gpointer *) &parent_type)) {
2393 MonoClass *child_class = mono_class_from_mono_type (child_type);
2394 if (parent_type != NULL) {
2395 MonoClass *parent_class = mono_class_from_mono_type (parent_type);
2396 child_class->parent = NULL;
2397 /* fool mono_class_setup_parent */
2398 child_class->supertypes = NULL;
2399 mono_class_setup_parent (child_class, parent_class);
2400 } else if (strcmp (child_class->name, "Object") == 0 && strcmp (child_class->name_space, "System") == 0) {
2401 const char *old_n = child_class->name;
2402 /* trick to get relative numbering right when compiling corlib */
2403 child_class->name = "BuildingObject";
2404 mono_class_setup_parent (child_class, mono_defaults.object_class);
2405 child_class->name = old_n;
2407 mono_class_setup_mono_type (child_class);
2408 mono_class_setup_supertypes (child_class);
2411 mono_loader_unlock ();
2412 return is_ok (error);
2415 static gboolean
2416 reflection_setup_internal_class_internal (MonoReflectionTypeBuilderHandle ref_tb, MonoError *error)
2418 HANDLE_FUNCTION_ENTER ();
2419 error_init (error);
2421 mono_loader_lock ();
2423 gint32 entering_state = MONO_HANDLE_GETVAL (MONO_HANDLE_CAST (MonoReflectionTypeBuilder, ref_tb), state);
2424 if (entering_state != MonoTypeBuilderNew) {
2425 g_assert (MONO_HANDLE_GETVAL (MONO_HANDLE_CAST (MonoReflectionType, ref_tb), type));
2426 goto leave;
2429 MONO_HANDLE_SETVAL (ref_tb, state, MonoTypeBuilderState, MonoTypeBuilderEntered);
2430 MonoReflectionModuleBuilderHandle module_ref = MONO_HANDLE_NEW_GET (MonoReflectionModuleBuilder, ref_tb, module);
2431 GHashTable *unparented_classes = MONO_HANDLE_GETVAL(module_ref, unparented_classes);
2433 // If this type is already setup, exit. We'll fix the parenting later
2434 MonoType *type = MONO_HANDLE_GETVAL (MONO_HANDLE_CAST (MonoReflectionType, ref_tb), type);
2435 if (type)
2436 goto leave;
2438 MonoReflectionModuleBuilderHandle ref_module = MONO_HANDLE_NEW_GET (MonoReflectionModuleBuilder, ref_tb, module);
2439 MonoDynamicImage *dynamic_image = MONO_HANDLE_GETVAL (ref_module, dynamic_image);
2441 MonoStringHandle ref_name = MONO_HANDLE_NEW_GET (MonoString, ref_tb, name);
2442 MonoStringHandle ref_nspace = MONO_HANDLE_NEW_GET (MonoString, ref_tb, nspace);
2444 guint32 table_idx = MONO_HANDLE_GETVAL (ref_tb, table_idx);
2446 * The size calculation here warrants some explaining.
2447 * reflection_setup_internal_class is called too early, well before we know whether the type will be a GTD or DEF,
2448 * meaning we need to alloc enough space to morth a def into a gtd.
2450 MonoClass *klass = (MonoClass *)mono_image_alloc0 (&dynamic_image->image, MAX (sizeof (MonoClassDef), sizeof (MonoClassGtd)));
2451 klass->class_kind = MONO_CLASS_DEF;
2453 klass->image = &dynamic_image->image;
2455 klass->inited = 1; /* we lie to the runtime */
2456 klass->name = mono_string_to_utf8_image (klass->image, ref_name, error);
2457 if (!is_ok (error))
2458 goto leave;
2459 klass->name_space = mono_string_to_utf8_image (klass->image, ref_nspace, error);
2460 if (!is_ok (error))
2461 goto leave;
2462 klass->type_token = MONO_TOKEN_TYPE_DEF | table_idx;
2463 mono_class_set_flags (klass, MONO_HANDLE_GETVAL (ref_tb, attrs));
2465 MONO_PROFILER_RAISE (class_loading, (klass));
2467 klass->element_class = klass;
2469 g_assert (!mono_class_has_ref_info (klass));
2470 mono_class_set_ref_info (klass, MONO_HANDLE_CAST (MonoObject, ref_tb));
2472 MonoReflectionTypeHandle ref_nesting_type = MONO_HANDLE_NEW_GET (MonoReflectionType, ref_tb, nesting_type);
2473 /* Put into cache so mono_class_get_checked () will find it.
2474 Skip nested types as those should not be available on the global scope. */
2475 if (MONO_HANDLE_IS_NULL (ref_nesting_type))
2476 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, table_idx);
2479 We must register all types as we cannot rely on the name_cache hashtable since we find the class
2480 by performing a mono_class_get which does the full resolution.
2482 Working around this semantics would require us to write a lot of code for no clear advantage.
2484 mono_image_append_class_to_reflection_info_set (klass);
2486 mono_dynamic_image_register_token (dynamic_image, MONO_TOKEN_TYPE_DEF | table_idx, MONO_HANDLE_CAST (MonoObject, ref_tb), MONO_DYN_IMAGE_TOK_NEW);
2488 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
2489 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
2490 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
2491 klass->instance_size = sizeof (MonoObject);
2492 klass->size_inited = 1;
2493 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
2496 mono_class_setup_mono_type (klass);
2499 * FIXME: handle interfaces.
2501 MonoReflectionTypeHandle ref_tb_type = MONO_HANDLE_CAST (MonoReflectionType, ref_tb);
2502 MONO_HANDLE_SETVAL (ref_tb_type, type, MonoType*, &klass->byval_arg);
2503 MONO_HANDLE_SETVAL (ref_tb, state, gint32, MonoTypeBuilderFinished);
2505 reflection_init_generic_class (ref_tb, error);
2506 if (!is_ok (error))
2507 goto leave;
2509 // Do here so that the search inside of the parent can see the above type that's been set.
2510 MonoReflectionTypeHandle ref_parent = MONO_HANDLE_NEW_GET (MonoReflectionType, ref_tb, parent);
2511 MonoType *parent_type = NULL;
2512 if (!MONO_HANDLE_IS_NULL (ref_parent)) {
2513 MonoClass *parent_klass = mono_handle_class (ref_parent);
2514 gboolean recursive_init = TRUE;
2516 if (is_sre_type_builder (parent_klass)) {
2517 MonoTypeBuilderState parent_state = MONO_HANDLE_GETVAL (MONO_HANDLE_CAST (MonoReflectionTypeBuilder, ref_parent), state);
2519 if (parent_state != MonoTypeBuilderNew) {
2520 // Initialize types reachable from parent recursively
2521 // We'll fix the type hierarchy later
2522 recursive_init = FALSE;
2526 if (recursive_init) {
2527 // If we haven't encountered a cycle, force the creation of ref_parent's type
2528 mono_reflection_type_handle_mono_type (ref_parent, error);
2529 if (!is_ok (error))
2530 goto leave;
2533 parent_type = MONO_HANDLE_GETVAL (ref_parent, type);
2535 // If we failed to create the parent, fail the child
2536 if (!parent_type)
2537 goto leave;
2540 // Push the child type and parent type to process later
2541 // Note: parent_type may be null.
2542 g_assert (!g_hash_table_lookup (unparented_classes, &klass->byval_arg));
2543 g_hash_table_insert (unparented_classes, &klass->byval_arg, parent_type);
2545 if (!MONO_HANDLE_IS_NULL (ref_nesting_type)) {
2546 if (!reflection_setup_internal_class (MONO_HANDLE_CAST (MonoReflectionTypeBuilder, ref_nesting_type), error))
2547 goto leave;
2549 MonoType *nesting_type = mono_reflection_type_handle_mono_type (ref_nesting_type, error);
2550 if (!is_ok (error))
2551 goto leave;
2552 klass->nested_in = mono_class_from_mono_type (nesting_type);
2555 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
2557 MONO_PROFILER_RAISE (class_loaded, (klass));
2559 leave:
2560 mono_loader_unlock ();
2561 HANDLE_FUNCTION_RETURN_VAL (is_ok (error));
2565 * reflection_init_generic_class:
2566 * @tb: a TypeBuilder object
2567 * @error: set on error
2569 * Creates the generic class after all generic parameters have been added.
2570 * On success returns TRUE, on failure returns FALSE and sets @error.
2572 * This assumes that reflection_setup_internal_class has already set up
2573 * ref_tb
2575 static gboolean
2576 reflection_init_generic_class (MonoReflectionTypeBuilderHandle ref_tb, MonoError *error)
2578 HANDLE_FUNCTION_ENTER ();
2580 error_init (error);
2582 MonoTypeBuilderState ref_state = MONO_HANDLE_GETVAL (ref_tb, state);
2583 g_assert (ref_state == MonoTypeBuilderFinished);
2585 MonoType *type = MONO_HANDLE_GETVAL (MONO_HANDLE_CAST (MonoReflectionType, ref_tb), type);
2586 MonoClass *klass = mono_class_from_mono_type (type);
2588 MonoArrayHandle generic_params = MONO_HANDLE_NEW_GET (MonoArray, ref_tb, generic_params);
2589 int count = MONO_HANDLE_IS_NULL (generic_params) ? 0 : mono_array_handle_length (generic_params);
2591 if (count == 0)
2592 goto leave;
2594 if (mono_class_try_get_generic_container (klass) != NULL)
2595 goto leave; /* already setup */
2597 MonoGenericContainer *generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
2599 generic_container->owner.klass = klass;
2600 generic_container->type_argc = count;
2601 generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
2603 klass->class_kind = MONO_CLASS_GTD;
2604 mono_class_set_generic_container (klass, generic_container);
2607 MonoReflectionGenericParamHandle ref_gparam = MONO_HANDLE_NEW (MonoReflectionGenericParam, NULL);
2608 for (int i = 0; i < count; i++) {
2609 MONO_HANDLE_ARRAY_GETREF (ref_gparam, generic_params, i);
2610 MonoType *param_type = mono_reflection_type_handle_mono_type (MONO_HANDLE_CAST (MonoReflectionType, ref_gparam), error);
2611 if (!is_ok (error))
2612 goto leave;
2613 MonoGenericParamFull *param = (MonoGenericParamFull *) param_type->data.generic_param;
2614 generic_container->type_params [i] = *param;
2615 /*Make sure we are a diferent type instance */
2616 generic_container->type_params [i].param.owner = generic_container;
2617 generic_container->type_params [i].info.pklass = NULL;
2618 generic_container->type_params [i].info.flags = MONO_HANDLE_GETVAL (ref_gparam, attrs);
2620 g_assert (generic_container->type_params [i].param.owner);
2623 generic_container->context.class_inst = mono_get_shared_generic_inst (generic_container);
2624 MonoGenericContext* context = &generic_container->context;
2625 MonoType *canonical_inst = &((MonoClassGtd*)klass)->canonical_inst;
2626 canonical_inst->type = MONO_TYPE_GENERICINST;
2627 canonical_inst->data.generic_class = mono_metadata_lookup_generic_class (klass, context->class_inst, FALSE);
2629 leave:
2630 HANDLE_FUNCTION_RETURN_VAL (is_ok (error));
2633 static MonoMarshalSpec*
2634 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
2635 MonoReflectionMarshal *minfo, MonoError *error)
2637 MonoMarshalSpec *res;
2639 error_init (error);
2641 res = image_g_new0 (image, MonoMarshalSpec, 1);
2642 res->native = (MonoMarshalNative)minfo->type;
2644 switch (minfo->type) {
2645 case MONO_NATIVE_LPARRAY:
2646 res->data.array_data.elem_type = (MonoMarshalNative)minfo->eltype;
2647 if (minfo->has_size) {
2648 res->data.array_data.param_num = minfo->param_num;
2649 res->data.array_data.num_elem = minfo->count;
2650 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
2652 else {
2653 res->data.array_data.param_num = -1;
2654 res->data.array_data.num_elem = -1;
2655 res->data.array_data.elem_mult = -1;
2657 break;
2659 case MONO_NATIVE_BYVALTSTR:
2660 case MONO_NATIVE_BYVALARRAY:
2661 res->data.array_data.num_elem = minfo->count;
2662 break;
2664 case MONO_NATIVE_CUSTOM:
2665 if (minfo->marshaltyperef) {
2666 MonoType *marshaltyperef = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, error);
2667 if (!is_ok (error)) {
2668 image_g_free (image, res);
2669 return NULL;
2671 res->data.custom_data.custom_name =
2672 type_get_fully_qualified_name (marshaltyperef);
2674 if (minfo->mcookie) {
2675 res->data.custom_data.cookie = mono_string_to_utf8_checked (minfo->mcookie, error);
2676 if (!is_ok (error)) {
2677 image_g_free (image, res);
2678 return NULL;
2681 break;
2683 default:
2684 break;
2687 return res;
2689 #endif /* !DISABLE_REFLECTION_EMIT */
2691 MonoReflectionMarshalAsAttributeHandle
2692 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
2693 MonoMarshalSpec *spec, MonoError *error)
2695 error_init (error);
2697 MonoReflectionMarshalAsAttributeHandle minfo = MONO_HANDLE_NEW (MonoReflectionMarshalAsAttribute, mono_object_new_checked (domain, mono_class_get_marshal_as_attribute_class (), error));
2698 if (!is_ok (error))
2699 goto fail;
2700 guint32 utype = spec->native;
2701 MONO_HANDLE_SETVAL (minfo, utype, guint32, utype);
2703 switch (utype) {
2704 case MONO_NATIVE_LPARRAY:
2705 MONO_HANDLE_SETVAL (minfo, array_subtype, guint32, spec->data.array_data.elem_type);
2706 MONO_HANDLE_SETVAL (minfo, size_const, gint32, spec->data.array_data.num_elem);
2707 if (spec->data.array_data.param_num != -1)
2708 MONO_HANDLE_SETVAL (minfo, size_param_index, gint16, spec->data.array_data.param_num);
2709 break;
2711 case MONO_NATIVE_BYVALTSTR:
2712 case MONO_NATIVE_BYVALARRAY:
2713 MONO_HANDLE_SETVAL (minfo, size_const, gint32, spec->data.array_data.num_elem);
2714 break;
2716 case MONO_NATIVE_CUSTOM:
2717 if (spec->data.custom_data.custom_name) {
2718 MonoType *mtype = mono_reflection_type_from_name_checked (spec->data.custom_data.custom_name, klass->image, error);
2719 if (!is_ok (error))
2720 goto fail;
2722 if (mtype) {
2723 MonoReflectionTypeHandle rt = mono_type_get_object_handle (domain, mtype, error);
2724 if (!is_ok (error))
2725 goto fail;
2727 MONO_HANDLE_SET (minfo, marshal_type_ref, rt);
2730 MonoStringHandle custom_name = mono_string_new_handle (domain, spec->data.custom_data.custom_name, error);
2731 if (!is_ok (error))
2732 goto fail;
2733 MONO_HANDLE_SET (minfo, marshal_type, custom_name);
2735 if (spec->data.custom_data.cookie) {
2736 MonoStringHandle cookie = mono_string_new_handle (domain, spec->data.custom_data.cookie, error);
2737 if (!is_ok (error))
2738 goto fail;
2739 MONO_HANDLE_SET (minfo, marshal_cookie, cookie);
2741 break;
2743 default:
2744 break;
2747 return minfo;
2748 fail:
2749 return MONO_HANDLE_NEW (MonoReflectionMarshalAsAttribute, NULL);
2752 #ifndef DISABLE_REFLECTION_EMIT
2753 static MonoMethod*
2754 reflection_methodbuilder_to_mono_method (MonoClass *klass,
2755 ReflectionMethodBuilder *rmb,
2756 MonoMethodSignature *sig,
2757 MonoError *error)
2759 MonoMethod *m;
2760 MonoMethodWrapper *wrapperm;
2761 MonoMarshalSpec **specs;
2762 MonoReflectionMethodAux *method_aux;
2763 MonoImage *image;
2764 gboolean dynamic;
2765 int i;
2767 error_init (error);
2769 * Methods created using a MethodBuilder should have their memory allocated
2770 * inside the image mempool, while dynamic methods should have their memory
2771 * malloc'd.
2773 dynamic = rmb->refs != NULL;
2774 image = dynamic ? NULL : klass->image;
2776 if (!dynamic)
2777 g_assert (!mono_class_is_ginst (klass));
2779 mono_loader_lock ();
2781 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
2782 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
2783 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
2784 else
2785 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
2787 wrapperm = (MonoMethodWrapper*)m;
2789 m->dynamic = dynamic;
2790 m->slot = -1;
2791 m->flags = rmb->attrs;
2792 m->iflags = rmb->iattrs;
2793 m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
2794 m->klass = klass;
2795 m->signature = sig;
2796 m->sre_method = TRUE;
2797 m->skip_visibility = rmb->skip_visibility;
2798 if (rmb->table_idx)
2799 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
2801 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
2802 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
2803 m->string_ctor = 1;
2805 m->signature->pinvoke = 1;
2806 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
2807 m->signature->pinvoke = 1;
2809 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
2811 method_aux->dllentry = rmb->dllentry ? string_to_utf8_image_raw (image, rmb->dllentry, error) : image_strdup (image, m->name);
2812 mono_error_assert_ok (error);
2813 method_aux->dll = string_to_utf8_image_raw (image, rmb->dll, error);
2814 mono_error_assert_ok (error);
2816 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
2818 if (image_is_dynamic (klass->image))
2819 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
2821 mono_loader_unlock ();
2823 return m;
2824 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
2825 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
2826 MonoMethodHeader *header;
2827 guint32 code_size;
2828 gint32 max_stack, i;
2829 gint32 num_locals = 0;
2830 gint32 num_clauses = 0;
2831 guint8 *code;
2833 if (rmb->ilgen) {
2834 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
2835 code_size = rmb->ilgen->code_len;
2836 max_stack = rmb->ilgen->max_stack;
2837 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
2838 if (rmb->ilgen->ex_handlers)
2839 num_clauses = mono_reflection_method_count_clauses (rmb->ilgen);
2840 } else {
2841 if (rmb->code) {
2842 code = mono_array_addr (rmb->code, guint8, 0);
2843 code_size = mono_array_length (rmb->code);
2844 /* we probably need to run a verifier on the code... */
2845 max_stack = 8;
2847 else {
2848 code = NULL;
2849 code_size = 0;
2850 max_stack = 8;
2854 header = (MonoMethodHeader *)mono_image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
2855 header->code_size = code_size;
2856 header->code = (const unsigned char *)image_g_malloc (image, code_size);
2857 memcpy ((char*)header->code, code, code_size);
2858 header->max_stack = max_stack;
2859 header->init_locals = rmb->init_locals;
2860 header->num_locals = num_locals;
2862 for (i = 0; i < num_locals; ++i) {
2863 MonoReflectionLocalBuilder *lb =
2864 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
2866 header->locals [i] = image_g_new0 (image, MonoType, 1);
2867 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)lb->type, error);
2868 mono_error_assert_ok (error);
2869 memcpy (header->locals [i], type, MONO_SIZEOF_TYPE);
2872 header->num_clauses = num_clauses;
2873 if (num_clauses) {
2874 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
2875 rmb->ilgen, num_clauses, error);
2876 mono_error_assert_ok (error);
2879 wrapperm->header = header;
2882 if (rmb->generic_params) {
2883 int count = mono_array_length (rmb->generic_params);
2884 MonoGenericContainer *container;
2886 container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
2887 container->is_method = TRUE;
2888 container->is_anonymous = FALSE;
2889 container->type_argc = count;
2890 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
2891 container->owner.method = m;
2893 m->is_generic = TRUE;
2894 mono_method_set_generic_container (m, container);
2896 for (i = 0; i < count; i++) {
2897 MonoReflectionGenericParam *gp =
2898 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
2899 MonoType *gp_type = mono_reflection_type_get_handle ((MonoReflectionType*)gp, error);
2900 mono_error_assert_ok (error);
2901 MonoGenericParamFull *param = (MonoGenericParamFull *) gp_type->data.generic_param;
2902 container->type_params [i] = *param;
2903 container->type_params [i].param.owner = container;
2905 gp->type.type->data.generic_param = (MonoGenericParam*)&container->type_params [i];
2907 MonoClass *gklass = mono_class_from_mono_type (gp_type);
2908 gklass->wastypebuilder = TRUE;
2912 * The method signature might have pointers to generic parameters that belong to other methods.
2913 * This is a valid SRE case, but the resulting method signature must be encoded using the proper
2914 * generic parameters.
2916 for (i = 0; i < m->signature->param_count; ++i) {
2917 MonoType *t = m->signature->params [i];
2918 if (t->type == MONO_TYPE_MVAR) {
2919 MonoGenericParam *gparam = t->data.generic_param;
2920 if (gparam->num < count) {
2921 m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
2922 m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
2928 if (mono_class_is_gtd (klass)) {
2929 container->parent = mono_class_get_generic_container (klass);
2930 container->context.class_inst = mono_class_get_generic_container (klass)->context.class_inst;
2932 container->context.method_inst = mono_get_shared_generic_inst (container);
2935 if (rmb->refs) {
2936 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
2937 int i;
2938 void **data;
2940 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
2942 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
2943 data [0] = GUINT_TO_POINTER (rmb->nrefs);
2944 for (i = 0; i < rmb->nrefs; ++i)
2945 data [i + 1] = rmb->refs [i];
2948 method_aux = NULL;
2950 /* Parameter info */
2951 if (rmb->pinfo) {
2952 if (!method_aux)
2953 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
2954 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
2955 for (i = 0; i <= m->signature->param_count; ++i) {
2956 MonoReflectionParamBuilder *pb;
2957 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
2958 if ((i > 0) && (pb->attrs)) {
2959 /* Make a copy since it might point to a shared type structure */
2960 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
2961 m->signature->params [i - 1]->attrs = pb->attrs;
2964 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
2965 MonoDynamicImage *assembly;
2966 guint32 idx, len;
2967 MonoTypeEnum def_type;
2968 char *p;
2969 const char *p2;
2971 if (!method_aux->param_defaults) {
2972 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
2973 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
2975 assembly = (MonoDynamicImage*)klass->image;
2976 idx = mono_dynimage_encode_constant (assembly, pb->def_value, &def_type);
2977 /* Copy the data from the blob since it might get realloc-ed */
2978 p = assembly->blob.data + idx;
2979 len = mono_metadata_decode_blob_size (p, &p2);
2980 len += p2 - p;
2981 method_aux->param_defaults [i] = (uint8_t *)image_g_malloc (image, len);
2982 method_aux->param_default_types [i] = def_type;
2983 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
2986 if (pb->name) {
2987 method_aux->param_names [i] = string_to_utf8_image_raw (image, pb->name, error);
2988 mono_error_assert_ok (error);
2990 if (pb->cattrs) {
2991 if (!method_aux->param_cattr)
2992 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
2993 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
2999 /* Parameter marshalling */
3000 specs = NULL;
3001 if (rmb->pinfo)
3002 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
3003 MonoReflectionParamBuilder *pb;
3004 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
3005 if (pb->marshal_info) {
3006 if (specs == NULL)
3007 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
3008 specs [pb->position] =
3009 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info, error);
3010 if (!is_ok (error)) {
3011 mono_loader_unlock ();
3012 image_g_free (image, specs);
3013 /* FIXME: if image is NULL, this leaks all the other stuff we alloc'd in this function */
3014 return NULL;
3019 if (specs != NULL) {
3020 if (!method_aux)
3021 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
3022 method_aux->param_marshall = specs;
3025 if (image_is_dynamic (klass->image) && method_aux)
3026 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
3028 mono_loader_unlock ();
3030 return m;
3033 static MonoMethod*
3034 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb, MonoError *error)
3036 ReflectionMethodBuilder rmb;
3037 MonoMethodSignature *sig;
3039 mono_loader_lock ();
3041 if (!mono_reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
3042 return NULL;
3044 g_assert (klass->image != NULL);
3045 sig = ctor_builder_to_signature_raw (klass->image, mb, error); /* FIXME use handles */
3046 mono_loader_unlock ();
3047 return_val_if_nok (error, NULL);
3049 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
3050 return_val_if_nok (error, NULL);
3051 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
3053 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
3054 /* ilgen is no longer needed */
3055 mb->ilgen = NULL;
3058 return mb->mhandle;
3061 static MonoMethod*
3062 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilderHandle ref_mb, MonoError *error)
3064 ReflectionMethodBuilder rmb;
3065 MonoMethodSignature *sig;
3067 error_init (error);
3069 mono_loader_lock ();
3071 MonoReflectionMethodBuilder *mb = MONO_HANDLE_RAW (ref_mb); /* FIXME use handles */
3072 if (!mono_reflection_methodbuilder_from_method_builder (&rmb, mb, error))
3073 return NULL;
3075 g_assert (klass->image != NULL);
3076 sig = method_builder_to_signature (klass->image, ref_mb, error);
3077 mono_loader_unlock ();
3078 return_val_if_nok (error, NULL);
3080 MonoMethod *method = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
3081 return_val_if_nok (error, NULL);
3082 MONO_HANDLE_SETVAL (ref_mb, mhandle, MonoMethod*, method);
3083 mono_save_custom_attrs (klass->image, method, mb->cattrs);
3085 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save)
3086 /* ilgen is no longer needed */
3087 mb->ilgen = NULL;
3088 return method;
3091 static MonoMethod*
3092 methodbuilder_to_mono_method_raw (MonoClass *klass, MonoReflectionMethodBuilder* mb_raw, MonoError *error)
3094 HANDLE_FUNCTION_ENTER (); /* FIXME change callers of methodbuilder_to_mono_method_raw to use handles */
3095 error_init (error);
3096 MONO_HANDLE_DCL (MonoReflectionMethodBuilder, mb);
3097 MonoMethod *result = methodbuilder_to_mono_method (klass, mb, error);
3098 HANDLE_FUNCTION_RETURN_VAL (result);
3101 #endif
3103 #ifndef DISABLE_REFLECTION_EMIT
3106 * fix_partial_generic_class:
3107 * @klass: a generic instantiation MonoClass
3108 * @error: set on error
3110 * Assumes that the generic container of @klass has its vtable
3111 * initialized, and updates the parent class, interfaces, methods and
3112 * fields of @klass by inflating the types using the generic context.
3114 * On success returns TRUE, on failure returns FALSE and sets @error.
3117 static gboolean
3118 fix_partial_generic_class (MonoClass *klass, MonoError *error)
3120 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
3121 int i;
3123 error_init (error);
3125 if (klass->wastypebuilder)
3126 return TRUE;
3128 if (klass->parent != gklass->parent) {
3129 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &mono_class_get_generic_class (klass)->context, error);
3130 if (mono_error_ok (error)) {
3131 MonoClass *parent = mono_class_from_mono_type (parent_type);
3132 mono_metadata_free_type (parent_type);
3133 if (parent != klass->parent) {
3134 /*fool mono_class_setup_parent*/
3135 klass->supertypes = NULL;
3136 mono_class_setup_parent (klass, parent);
3138 } else {
3139 if (gklass->wastypebuilder)
3140 klass->wastypebuilder = TRUE;
3141 return FALSE;
3145 if (!mono_class_get_generic_class (klass)->need_sync)
3146 return TRUE;
3148 int mcount = mono_class_get_method_count (klass);
3149 int gmcount = mono_class_get_method_count (gklass);
3150 if (mcount != gmcount) {
3151 mono_class_set_method_count (klass, gmcount);
3152 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (gmcount + 1));
3154 for (i = 0; i < gmcount; i++) {
3155 klass->methods [i] = mono_class_inflate_generic_method_full_checked (
3156 gklass->methods [i], klass, mono_class_get_context (klass), error);
3157 mono_error_assert_ok (error);
3161 if (klass->interface_count && klass->interface_count != gklass->interface_count) {
3162 klass->interface_count = gklass->interface_count;
3163 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
3164 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
3166 for (i = 0; i < gklass->interface_count; ++i) {
3167 MonoType *iface_type = mono_class_inflate_generic_type_checked (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass), error);
3168 return_val_if_nok (error, FALSE);
3170 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
3171 mono_metadata_free_type (iface_type);
3173 if (!ensure_runtime_vtable (klass->interfaces [i], error))
3174 return FALSE;
3176 klass->interfaces_inited = 1;
3179 int fcount = mono_class_get_field_count (klass);
3180 int gfcount = mono_class_get_field_count (gklass);
3181 if (fcount != gfcount) {
3182 mono_class_set_field_count (klass, gfcount);
3183 klass->fields = image_g_new0 (klass->image, MonoClassField, gfcount);
3185 for (i = 0; i < gfcount; i++) {
3186 klass->fields [i] = gklass->fields [i];
3187 klass->fields [i].parent = klass;
3188 klass->fields [i].type = mono_class_inflate_generic_type_checked (gklass->fields [i].type, mono_class_get_context (klass), error);
3189 return_val_if_nok (error, FALSE);
3193 /*We can only finish with this klass once it's parent has as well*/
3194 if (gklass->wastypebuilder)
3195 klass->wastypebuilder = TRUE;
3196 return TRUE;
3200 * ensure_generic_class_runtime_vtable:
3201 * @klass a generic class
3202 * @error set on error
3204 * Ensures that the generic container of @klass has a vtable and
3205 * returns TRUE on success. On error returns FALSE and sets @error.
3207 static gboolean
3208 ensure_generic_class_runtime_vtable (MonoClass *klass, MonoError *error)
3210 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
3212 error_init (error);
3214 if (!ensure_runtime_vtable (gklass, error))
3215 return FALSE;
3217 return fix_partial_generic_class (klass, error);
3221 * ensure_runtime_vtable:
3222 * @klass the class
3223 * @error set on error
3225 * Ensures that @klass has a vtable and returns TRUE on success. On
3226 * error returns FALSE and sets @error.
3228 static gboolean
3229 ensure_runtime_vtable (MonoClass *klass, MonoError *error)
3231 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info_raw (klass); /* FIXME use handles */
3232 int i, num, j;
3234 error_init (error);
3236 if (!image_is_dynamic (klass->image) || (!tb && !mono_class_is_ginst (klass)) || klass->wastypebuilder)
3237 return TRUE;
3238 if (klass->parent)
3239 if (!ensure_runtime_vtable (klass->parent, error))
3240 return FALSE;
3242 if (tb) {
3243 num = tb->ctors? mono_array_length (tb->ctors): 0;
3244 num += tb->num_methods;
3245 mono_class_set_method_count (klass, num);
3246 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
3247 num = tb->ctors? mono_array_length (tb->ctors): 0;
3248 for (i = 0; i < num; ++i) {
3249 MonoMethod *ctor = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), error);
3250 if (!ctor)
3251 return FALSE;
3252 klass->methods [i] = ctor;
3254 num = tb->num_methods;
3255 j = i;
3256 for (i = 0; i < num; ++i) {
3257 MonoMethod *meth = methodbuilder_to_mono_method_raw (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), error); /* FIXME use handles */
3258 if (!meth)
3259 return FALSE;
3260 klass->methods [j++] = meth;
3263 if (tb->interfaces) {
3264 klass->interface_count = mono_array_length (tb->interfaces);
3265 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
3266 for (i = 0; i < klass->interface_count; ++i) {
3267 MonoType *iface = mono_type_array_get_and_resolve_raw (tb->interfaces, i, error); /* FIXME use handles */
3268 return_val_if_nok (error, FALSE);
3269 klass->interfaces [i] = mono_class_from_mono_type (iface);
3270 if (!ensure_runtime_vtable (klass->interfaces [i], error))
3271 return FALSE;
3273 klass->interfaces_inited = 1;
3275 } else if (mono_class_is_ginst (klass)){
3276 if (!ensure_generic_class_runtime_vtable (klass, error)) {
3277 mono_class_set_type_load_failure (klass, "Could not initialize vtable for generic class due to: %s", mono_error_get_message (error));
3278 return FALSE;
3282 if (mono_class_is_interface (klass) && !mono_class_is_ginst (klass)) {
3283 int slot_num = 0;
3284 int mcount = mono_class_get_method_count (klass);
3285 for (i = 0; i < mcount; ++i) {
3286 MonoMethod *im = klass->methods [i];
3287 if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
3288 im->slot = slot_num++;
3291 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
3292 mono_class_setup_interface_offsets (klass);
3293 mono_class_setup_interface_id (klass);
3297 * The generic vtable is needed even if image->run is not set since some
3298 * runtime code like ves_icall_Type_GetMethodsByName depends on
3299 * method->slot being defined.
3303 * tb->methods could not be freed since it is used for determining
3304 * overrides during dynamic vtable construction.
3307 return TRUE;
3310 static MonoMethod*
3311 mono_reflection_method_get_handle (MonoObject *method, MonoError *error)
3313 error_init (error);
3314 MonoClass *klass = mono_object_class (method);
3315 if (is_sr_mono_method (klass)) {
3316 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
3317 return sr_method->method;
3319 if (is_sre_method_builder (klass)) {
3320 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
3321 return mb->mhandle;
3323 if (mono_is_sre_method_on_tb_inst (klass)) {
3324 MonoClass *handle_class;
3326 MonoMethod *result = mono_reflection_resolve_object (NULL, method, &handle_class, NULL, error);
3327 return_val_if_nok (error, NULL);
3329 return result;
3332 g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
3333 return NULL;
3336 void
3337 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides, MonoError *error)
3339 MonoReflectionTypeBuilder *tb;
3340 int i, j, onum;
3341 MonoReflectionMethod *m;
3343 error_init (error);
3344 *overrides = NULL;
3345 *num_overrides = 0;
3347 g_assert (image_is_dynamic (klass->image));
3349 if (!mono_class_has_ref_info (klass))
3350 return;
3352 tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info_raw (klass); /* FIXME use handles */
3353 g_assert (strcmp (mono_object_class (tb)->name, "TypeBuilder") == 0);
3355 onum = 0;
3356 if (tb->methods) {
3357 for (i = 0; i < tb->num_methods; ++i) {
3358 MonoReflectionMethodBuilder *mb =
3359 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3360 if (mb->override_methods)
3361 onum += mono_array_length (mb->override_methods);
3365 if (onum) {
3366 *overrides = g_new0 (MonoMethod*, onum * 2);
3368 onum = 0;
3369 for (i = 0; i < tb->num_methods; ++i) {
3370 MonoReflectionMethodBuilder *mb =
3371 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3372 if (mb->override_methods) {
3373 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
3374 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
3376 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m, error);
3377 return_if_nok (error);
3378 (*overrides) [onum * 2 + 1] = mb->mhandle;
3380 g_assert (mb->mhandle);
3382 onum ++;
3388 *num_overrides = onum;
3391 /* This initializes the same data as mono_class_setup_fields () */
3392 static void
3393 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
3395 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info_raw (klass); /* FIXME use handles */
3396 MonoReflectionFieldBuilder *fb;
3397 MonoClassField *field;
3398 MonoFieldDefaultValue *def_values;
3399 MonoImage *image = klass->image;
3400 const char *p, *p2;
3401 int i, instance_size, packing_size = 0;
3402 guint32 len, idx;
3404 if (klass->parent) {
3405 if (!klass->parent->size_inited)
3406 mono_class_init (klass->parent);
3407 instance_size = klass->parent->instance_size;
3408 } else {
3409 instance_size = sizeof (MonoObject);
3412 int fcount = tb->num_fields;
3413 mono_class_set_field_count (klass, fcount);
3415 error_init (error);
3417 if (tb->class_size) {
3418 packing_size = tb->packing_size;
3419 instance_size += tb->class_size;
3422 klass->fields = image_g_new0 (image, MonoClassField, fcount);
3423 def_values = image_g_new0 (image, MonoFieldDefaultValue, fcount);
3424 mono_class_set_field_def_values (klass, def_values);
3426 This is, guess what, a hack.
3427 The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
3428 On the static path no field class is resolved, only types are built. This is the right thing to do
3429 but we suck.
3430 Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
3432 klass->size_inited = 1;
3434 for (i = 0; i < fcount; ++i) {
3435 MonoArray *rva_data;
3436 fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
3437 field = &klass->fields [i];
3438 field->parent = klass;
3439 field->name = string_to_utf8_image_raw (image, fb->name, error); /* FIXME use handles */
3440 if (!mono_error_ok (error))
3441 return;
3442 if (fb->attrs) {
3443 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
3444 return_if_nok (error);
3445 field->type = mono_metadata_type_dup (klass->image, type);
3446 field->type->attrs = fb->attrs;
3447 } else {
3448 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
3449 return_if_nok (error);
3452 if (!klass->enumtype && !mono_type_get_underlying_type (field->type)) {
3453 mono_class_set_type_load_failure (klass, "Field '%s' is an enum type with a bad underlying type", field->name);
3454 continue;
3457 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
3458 char *base = mono_array_addr (rva_data, char, 0);
3459 size_t size = mono_array_length (rva_data);
3460 char *data = (char *)mono_image_alloc (klass->image, size);
3461 memcpy (data, base, size);
3462 def_values [i].data = data;
3464 if (fb->offset != -1)
3465 field->offset = fb->offset;
3466 fb->handle = field;
3467 mono_save_custom_attrs (klass->image, field, fb->cattrs);
3469 if (fb->def_value) {
3470 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
3471 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
3472 idx = mono_dynimage_encode_constant (assembly, fb->def_value, &def_values [i].def_type);
3473 /* Copy the data from the blob since it might get realloc-ed */
3474 p = assembly->blob.data + idx;
3475 len = mono_metadata_decode_blob_size (p, &p2);
3476 len += p2 - p;
3477 def_values [i].data = (const char *)mono_image_alloc (image, len);
3478 memcpy ((gpointer)def_values [i].data, p, len);
3482 if (!mono_class_has_failure (klass)) {
3483 mono_class_layout_fields (klass, instance_size, packing_size, TRUE);
3487 static void
3488 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
3490 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info_raw (klass); /* FIXME use handles */
3491 MonoReflectionPropertyBuilder *pb;
3492 MonoImage *image = klass->image;
3493 MonoProperty *properties;
3494 MonoClassPropertyInfo *info;
3495 int i;
3497 error_init (error);
3499 info = mono_class_get_property_info (klass);
3500 if (!info) {
3501 info = mono_class_alloc0 (klass, sizeof (MonoClassPropertyInfo));
3502 mono_class_set_property_info (klass, info);
3505 info->count = tb->properties ? mono_array_length (tb->properties) : 0;
3506 info->first = 0;
3508 properties = image_g_new0 (image, MonoProperty, info->count);
3509 info->properties = properties;
3510 for (i = 0; i < info->count; ++i) {
3511 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3512 properties [i].parent = klass;
3513 properties [i].attrs = pb->attrs;
3514 properties [i].name = string_to_utf8_image_raw (image, pb->name, error); /* FIXME use handles */
3515 if (!mono_error_ok (error))
3516 return;
3517 if (pb->get_method)
3518 properties [i].get = pb->get_method->mhandle;
3519 if (pb->set_method)
3520 properties [i].set = pb->set_method->mhandle;
3522 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
3523 if (pb->def_value) {
3524 guint32 len, idx;
3525 const char *p, *p2;
3526 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
3527 if (!info->def_values)
3528 info->def_values = image_g_new0 (image, MonoFieldDefaultValue, info->count);
3529 properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
3530 idx = mono_dynimage_encode_constant (assembly, pb->def_value, &info->def_values [i].def_type);
3531 /* Copy the data from the blob since it might get realloc-ed */
3532 p = assembly->blob.data + idx;
3533 len = mono_metadata_decode_blob_size (p, &p2);
3534 len += p2 - p;
3535 info->def_values [i].data = (const char *)mono_image_alloc (image, len);
3536 memcpy ((gpointer)info->def_values [i].data, p, len);
3541 static void
3542 typebuilder_setup_events (MonoClass *klass, MonoError *error)
3544 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info_raw (klass); /* FIXME use handles */
3545 MonoReflectionEventBuilder *eb;
3546 MonoImage *image = klass->image;
3547 MonoEvent *events;
3548 MonoClassEventInfo *info;
3549 int i;
3551 error_init (error);
3553 info = mono_class_alloc0 (klass, sizeof (MonoClassEventInfo));
3554 mono_class_set_event_info (klass, info);
3556 info->count = tb->events ? mono_array_length (tb->events) : 0;
3557 info->first = 0;
3559 events = image_g_new0 (image, MonoEvent, info->count);
3560 info->events = events;
3561 for (i = 0; i < info->count; ++i) {
3562 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3563 events [i].parent = klass;
3564 events [i].attrs = eb->attrs;
3565 events [i].name = string_to_utf8_image_raw (image, eb->name, error); /* FIXME use handles */
3566 if (!mono_error_ok (error))
3567 return;
3568 if (eb->add_method)
3569 events [i].add = eb->add_method->mhandle;
3570 if (eb->remove_method)
3571 events [i].remove = eb->remove_method->mhandle;
3572 if (eb->raise_method)
3573 events [i].raise = eb->raise_method->mhandle;
3575 #ifndef MONO_SMALL_CONFIG
3576 if (eb->other_methods) {
3577 int j;
3578 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
3579 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
3580 MonoReflectionMethodBuilder *mb =
3581 mono_array_get (eb->other_methods,
3582 MonoReflectionMethodBuilder*, j);
3583 events [i].other [j] = mb->mhandle;
3586 #endif
3587 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
3591 struct remove_instantiations_user_data
3593 MonoClass *klass;
3594 MonoError *error;
3597 static gboolean
3598 remove_instantiations_of_and_ensure_contents (gpointer key,
3599 gpointer value,
3600 gpointer user_data)
3602 struct remove_instantiations_user_data *data = (struct remove_instantiations_user_data*)user_data;
3603 MonoType *type = (MonoType*)key;
3604 MonoClass *klass = data->klass;
3605 gboolean already_failed = !is_ok (data->error);
3606 MonoError lerror;
3607 MonoError *error = already_failed ? &lerror : data->error;
3609 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
3610 MonoClass *inst_klass = mono_class_from_mono_type (type);
3611 //Ensure it's safe to use it.
3612 if (!fix_partial_generic_class (inst_klass, error)) {
3613 mono_class_set_type_load_failure (inst_klass, "Could not initialized generic type instance due to: %s", mono_error_get_message (error));
3614 // Marked the class with failure, but since some other instantiation already failed,
3615 // just report that one, and swallow the error from this one.
3616 if (already_failed)
3617 mono_error_cleanup (error);
3619 return TRUE;
3620 } else
3621 return FALSE;
3625 * reflection_setup_internal_class:
3626 * @tb: a TypeBuilder object
3627 * @error: set on error
3629 * Creates a MonoClass that represents the TypeBuilder.
3630 * This is a trick that lets us simplify a lot of reflection code
3631 * (and will allow us to support Build and Run assemblies easier).
3633 * Returns TRUE on success. On failure, returns FALSE and sets @error.
3635 static gboolean
3636 reflection_setup_internal_class (MonoReflectionTypeBuilderHandle ref_tb, MonoError *error)
3638 MonoReflectionModuleBuilderHandle module_ref = MONO_HANDLE_NEW_GET (MonoReflectionModuleBuilder, ref_tb, module);
3639 GHashTable *unparented_classes = MONO_HANDLE_GETVAL(module_ref, unparented_classes);
3641 if (unparented_classes) {
3642 return reflection_setup_internal_class_internal (ref_tb, error);
3643 } else {
3644 // If we're not being called recursively
3645 unparented_classes = g_hash_table_new (NULL, NULL);
3646 MONO_HANDLE_SETVAL (module_ref, unparented_classes, GHashTable *, unparented_classes);
3648 gboolean ret_val = reflection_setup_internal_class_internal (ref_tb, error);
3649 mono_error_assert_ok (error);
3651 // Fix the relationship between the created classes and their parents
3652 reflection_setup_class_hierarchy (unparented_classes, error);
3653 mono_error_assert_ok (error);
3655 g_hash_table_destroy (unparented_classes);
3656 MONO_HANDLE_SETVAL (module_ref, unparented_classes, GHashTable *, NULL);
3658 return ret_val;
3663 MonoReflectionTypeHandle
3664 ves_icall_TypeBuilder_create_runtime_class (MonoReflectionTypeBuilderHandle ref_tb, MonoError *error)
3666 error_init (error);
3668 reflection_setup_internal_class (ref_tb, error);
3669 mono_error_assert_ok (error);
3671 MonoDomain *domain = MONO_HANDLE_DOMAIN (ref_tb);
3672 MonoType *type = MONO_HANDLE_GETVAL (MONO_HANDLE_CAST (MonoReflectionType, ref_tb), type);
3673 MonoClass *klass = mono_class_from_mono_type (type);
3675 MonoArrayHandle cattrs = MONO_HANDLE_NEW_GET (MonoArray, ref_tb, cattrs);
3676 mono_save_custom_attrs (klass->image, klass, MONO_HANDLE_RAW (cattrs)); /* FIXME use handles */
3679 * we need to lock the domain because the lock will be taken inside
3680 * So, we need to keep the locking order correct.
3682 mono_loader_lock ();
3683 mono_domain_lock (domain);
3684 if (klass->wastypebuilder) {
3685 mono_domain_unlock (domain);
3686 mono_loader_unlock ();
3688 return mono_type_get_object_handle (domain, &klass->byval_arg, error);
3691 * Fields to set in klass:
3692 * the various flags: delegate/unicode/contextbound etc.
3694 mono_class_set_flags (klass, MONO_HANDLE_GETVAL (ref_tb, attrs));
3695 klass->has_cctor = 1;
3697 mono_class_setup_parent (klass, klass->parent);
3698 /* fool mono_class_setup_supertypes */
3699 klass->supertypes = NULL;
3700 mono_class_setup_supertypes (klass);
3701 mono_class_setup_mono_type (klass);
3703 /* enums are done right away */
3704 if (!klass->enumtype)
3705 if (!ensure_runtime_vtable (klass, error))
3706 goto failure;
3708 MonoArrayHandle nested_types = MONO_HANDLE_NEW_GET (MonoArray, ref_tb, subtypes);
3709 if (!MONO_HANDLE_IS_NULL (nested_types)) {
3710 GList *nested = NULL;
3711 int num_nested = mono_array_handle_length (nested_types);
3712 MonoReflectionTypeHandle nested_tb = MONO_HANDLE_NEW (MonoReflectionType, NULL);
3713 for (int i = 0; i < num_nested; ++i) {
3714 MONO_HANDLE_ARRAY_GETREF (nested_tb, nested_types, i);
3716 if (MONO_HANDLE_GETVAL (nested_tb, type) == NULL) {
3717 reflection_setup_internal_class (MONO_HANDLE_CAST (MonoReflectionTypeBuilder, nested_tb), error);
3718 mono_error_assert_ok (error);
3721 MonoType *subtype = mono_reflection_type_handle_mono_type (nested_tb, error);
3722 if (!is_ok (error)) goto failure;
3723 nested = g_list_prepend_image (klass->image, nested, mono_class_from_mono_type (subtype));
3725 mono_class_set_nested_classes_property (klass, nested);
3728 klass->nested_classes_inited = TRUE;
3730 typebuilder_setup_fields (klass, error);
3731 if (!is_ok (error))
3732 goto failure;
3733 typebuilder_setup_properties (klass, error);
3734 if (!is_ok (error))
3735 goto failure;
3737 typebuilder_setup_events (klass, error);
3738 if (!is_ok (error))
3739 goto failure;
3741 klass->wastypebuilder = TRUE;
3743 MonoArrayHandle generic_params = MONO_HANDLE_NEW_GET (MonoArray, ref_tb, generic_params);
3744 if (!MONO_HANDLE_IS_NULL (generic_params)) {
3745 int num_params = mono_array_handle_length (generic_params);
3746 MonoReflectionTypeHandle ref_gparam = MONO_HANDLE_NEW (MonoReflectionType, NULL);
3747 for (int i = 0; i < num_params; i++) {
3748 MONO_HANDLE_ARRAY_GETREF (ref_gparam, generic_params, i);
3749 MonoType *param_type = mono_reflection_type_handle_mono_type (ref_gparam, error);
3750 if (!is_ok (error))
3751 goto failure;
3752 MonoClass *gklass = mono_class_from_mono_type (param_type);
3754 gklass->wastypebuilder = TRUE;
3759 * If we are a generic TypeBuilder, there might be instantiations in the type cache
3760 * which have type System.Reflection.MonoGenericClass, but after the type is created,
3761 * we want to return normal System.MonoType objects, so clear these out from the cache.
3763 * Together with this we must ensure the contents of all instances to match the created type.
3765 if (domain->type_hash && mono_class_is_gtd (klass)) {
3766 struct remove_instantiations_user_data data;
3767 data.klass = klass;
3768 data.error = error;
3769 mono_error_assert_ok (error);
3770 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, &data);
3771 if (!is_ok (error))
3772 goto failure;
3775 mono_domain_unlock (domain);
3776 mono_loader_unlock ();
3778 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
3779 mono_class_set_type_load_failure (klass, "Not a valid enumeration");
3780 mono_error_set_type_load_class (error, klass, "Not a valid enumeration");
3781 goto failure_unlocked;
3784 MonoReflectionTypeHandle res = mono_type_get_object_handle (domain, &klass->byval_arg, error);
3785 if (!is_ok (error))
3786 goto failure_unlocked;
3788 return res;
3790 failure:
3791 mono_class_set_type_load_failure (klass, "TypeBuilder could not create runtime class due to: %s", mono_error_get_message (error));
3792 klass->wastypebuilder = TRUE;
3793 mono_domain_unlock (domain);
3794 mono_loader_unlock ();
3795 failure_unlocked:
3796 return NULL;
3799 typedef struct {
3800 MonoMethod *handle;
3801 MonoDomain *domain;
3802 } DynamicMethodReleaseData;
3805 * The runtime automatically clean up those after finalization.
3807 static MonoReferenceQueue *dynamic_method_queue;
3809 static void
3810 free_dynamic_method (void *dynamic_method)
3812 DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
3813 MonoDomain *domain = data->domain;
3814 MonoMethod *method = data->handle;
3815 guint32 dis_link;
3817 mono_domain_lock (domain);
3818 dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
3819 g_hash_table_remove (domain->method_to_dyn_method, method);
3820 mono_domain_unlock (domain);
3821 g_assert (dis_link);
3822 mono_gchandle_free (dis_link);
3824 mono_runtime_free_method (domain, method);
3825 g_free (data);
3828 static gboolean
3829 reflection_create_dynamic_method (MonoReflectionDynamicMethodHandle ref_mb, MonoError *error)
3831 MonoReferenceQueue *queue;
3832 MonoMethod *handle;
3833 DynamicMethodReleaseData *release_data;
3834 ReflectionMethodBuilder rmb;
3835 MonoMethodSignature *sig;
3836 MonoClass *klass;
3837 MonoDomain *domain;
3838 GSList *l;
3839 int i;
3841 error_init (error);
3843 if (mono_runtime_is_shutting_down ()) {
3844 mono_error_set_generic_error (error, "System", "InvalidOperationException", "");
3845 return FALSE;
3848 if (!(queue = dynamic_method_queue)) {
3849 mono_loader_lock ();
3850 if (!(queue = dynamic_method_queue))
3851 queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
3852 mono_loader_unlock ();
3855 sig = dynamic_method_to_signature (ref_mb, error);
3856 return_val_if_nok (error, FALSE);
3858 MonoReflectionDynamicMethod *mb = MONO_HANDLE_RAW (ref_mb); /* FIXME convert reflection_create_dynamic_method to use handles */
3859 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
3862 * Resolve references.
3865 * Every second entry in the refs array is reserved for storing handle_class,
3866 * which is needed by the ldtoken implementation in the JIT.
3868 rmb.nrefs = mb->nrefs;
3869 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
3870 for (i = 0; i < mb->nrefs; i += 2) {
3871 MonoClass *handle_class;
3872 gpointer ref;
3873 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
3875 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
3876 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
3878 * The referenced DynamicMethod should already be created by the managed
3879 * code, except in the case of circular references. In that case, we store
3880 * method in the refs array, and fix it up later when the referenced
3881 * DynamicMethod is created.
3883 if (method->mhandle) {
3884 ref = method->mhandle;
3885 } else {
3886 /* FIXME: GC object stored in unmanaged memory */
3887 ref = method;
3889 /* FIXME: GC object stored in unmanaged memory */
3890 method->referenced_by = g_slist_append (method->referenced_by, mb);
3892 handle_class = mono_defaults.methodhandle_class;
3893 } else {
3894 MonoException *ex = NULL;
3895 ref = mono_reflection_resolve_object (mb->module->image, obj, &handle_class, NULL, error);
3896 if (!is_ok (error)) {
3897 g_free (rmb.refs);
3898 return FALSE;
3900 if (!ref)
3901 ex = mono_get_exception_type_load (NULL, NULL);
3902 else if (mono_security_core_clr_enabled ())
3903 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
3905 if (ex) {
3906 g_free (rmb.refs);
3907 mono_error_set_exception_instance (error, ex);
3908 return FALSE;
3912 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
3913 rmb.refs [i + 1] = handle_class;
3916 if (mb->owner) {
3917 MonoType *owner_type = mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner, error);
3918 if (!is_ok (error)) {
3919 g_free (rmb.refs);
3920 return FALSE;
3922 klass = mono_class_from_mono_type (owner_type);
3923 } else {
3924 klass = mono_defaults.object_class;
3927 mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
3928 g_free (rmb.refs);
3929 return_val_if_nok (error, FALSE);
3931 release_data = g_new (DynamicMethodReleaseData, 1);
3932 release_data->handle = handle;
3933 release_data->domain = mono_object_get_domain ((MonoObject*)mb);
3934 if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
3935 g_free (release_data);
3937 /* Fix up refs entries pointing at us */
3938 for (l = mb->referenced_by; l; l = l->next) {
3939 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
3940 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
3941 gpointer *data;
3943 g_assert (method->mhandle);
3945 data = (gpointer*)wrapper->method_data;
3946 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
3947 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
3948 data [i + 1] = mb->mhandle;
3951 g_slist_free (mb->referenced_by);
3953 /* ilgen is no longer needed */
3954 mb->ilgen = NULL;
3956 domain = mono_domain_get ();
3957 mono_domain_lock (domain);
3958 if (!domain->method_to_dyn_method)
3959 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
3960 g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
3961 mono_domain_unlock (domain);
3963 return TRUE;
3966 void
3967 ves_icall_DynamicMethod_create_dynamic_method (MonoReflectionDynamicMethodHandle mb, MonoError *error)
3969 (void) reflection_create_dynamic_method (mb, error);
3972 #endif /* DISABLE_REFLECTION_EMIT */
3974 MonoMethodSignature *
3975 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
3977 MonoMethodSignature *sig;
3978 g_assert (image_is_dynamic (image));
3980 error_init (error);
3982 sig = (MonoMethodSignature *)g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
3983 if (sig)
3984 return sig;
3986 return mono_method_signature_checked (method, error);
3989 #ifndef DISABLE_REFLECTION_EMIT
3992 * ensure_complete_type:
3994 * Ensure that KLASS is completed if it is a dynamic type, or references
3995 * dynamic types.
3997 static void
3998 ensure_complete_type (MonoClass *klass, MonoError *error)
4000 error_init (error);
4002 if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_has_ref_info (klass)) {
4003 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info_raw (klass); /* FIXME use handles */
4005 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
4006 return_if_nok (error);
4008 // Asserting here could break a lot of code
4009 //g_assert (klass->wastypebuilder);
4012 if (mono_class_is_ginst (klass)) {
4013 MonoGenericInst *inst = mono_class_get_generic_class (klass)->context.class_inst;
4014 int i;
4016 for (i = 0; i < inst->type_argc; ++i) {
4017 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]), error);
4018 return_if_nok (error);
4023 gpointer
4024 mono_reflection_resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
4026 MonoClass *oklass = obj->vtable->klass;
4027 gpointer result = NULL;
4029 error_init (error);
4031 if (strcmp (oklass->name, "String") == 0) {
4032 result = mono_string_intern_checked ((MonoString*)obj, error);
4033 return_val_if_nok (error, NULL);
4034 *handle_class = mono_defaults.string_class;
4035 g_assert (result);
4036 } else if (strcmp (oklass->name, "RuntimeType") == 0) {
4037 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
4038 return_val_if_nok (error, NULL);
4039 MonoClass *mc = mono_class_from_mono_type (type);
4040 if (!mono_class_init (mc)) {
4041 mono_error_set_for_class_failure (error, mc);
4042 return NULL;
4045 if (context) {
4046 MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, error);
4047 return_val_if_nok (error, NULL);
4049 result = mono_class_from_mono_type (inflated);
4050 mono_metadata_free_type (inflated);
4051 } else {
4052 result = mono_class_from_mono_type (type);
4054 *handle_class = mono_defaults.typehandle_class;
4055 g_assert (result);
4056 } else if (strcmp (oklass->name, "MonoMethod") == 0 ||
4057 strcmp (oklass->name, "MonoCMethod") == 0) {
4058 result = ((MonoReflectionMethod*)obj)->method;
4059 if (context) {
4060 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
4061 mono_error_assert_ok (error);
4063 *handle_class = mono_defaults.methodhandle_class;
4064 g_assert (result);
4065 } else if (strcmp (oklass->name, "MonoField") == 0) {
4066 MonoClassField *field = ((MonoReflectionField*)obj)->field;
4068 ensure_complete_type (field->parent, error);
4069 return_val_if_nok (error, NULL);
4071 if (context) {
4072 MonoType *inflated = mono_class_inflate_generic_type_checked (&field->parent->byval_arg, context, error);
4073 return_val_if_nok (error, NULL);
4075 MonoClass *klass = mono_class_from_mono_type (inflated);
4076 MonoClassField *inflated_field;
4077 gpointer iter = NULL;
4078 mono_metadata_free_type (inflated);
4079 while ((inflated_field = mono_class_get_fields (klass, &iter))) {
4080 if (!strcmp (field->name, inflated_field->name))
4081 break;
4083 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
4084 result = inflated_field;
4085 } else {
4086 result = field;
4088 *handle_class = mono_defaults.fieldhandle_class;
4089 g_assert (result);
4090 } else if (strcmp (oklass->name, "TypeBuilder") == 0) {
4091 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
4092 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
4093 return_val_if_nok (error, NULL);
4094 MonoClass *klass;
4096 klass = type->data.klass;
4097 if (klass->wastypebuilder) {
4098 /* Already created */
4099 result = klass;
4101 else {
4102 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
4103 return_val_if_nok (error, NULL);
4104 result = type->data.klass;
4105 g_assert (result);
4107 *handle_class = mono_defaults.typehandle_class;
4108 } else if (strcmp (oklass->name, "SignatureHelper") == 0) {
4109 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
4110 MonoMethodSignature *sig;
4111 int nargs, i;
4113 if (helper->arguments)
4114 nargs = mono_array_length (helper->arguments);
4115 else
4116 nargs = 0;
4118 sig = mono_metadata_signature_alloc (image, nargs);
4119 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
4120 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
4122 if (helper->unmanaged_call_conv) { /* unmanaged */
4123 sig->call_convention = helper->unmanaged_call_conv - 1;
4124 sig->pinvoke = TRUE;
4125 } else if (helper->call_conv & 0x02) {
4126 sig->call_convention = MONO_CALL_VARARG;
4127 } else {
4128 sig->call_convention = MONO_CALL_DEFAULT;
4131 sig->param_count = nargs;
4132 /* TODO: Copy type ? */
4133 sig->ret = helper->return_type->type;
4134 for (i = 0; i < nargs; ++i) {
4135 sig->params [i] = mono_type_array_get_and_resolve_raw (helper->arguments, i, error); /* FIXME use handles */
4136 if (!is_ok (error)) {
4137 image_g_free (image, sig);
4138 return NULL;
4142 result = sig;
4143 *handle_class = NULL;
4144 } else if (strcmp (oklass->name, "DynamicMethod") == 0) {
4145 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
4146 /* Already created by the managed code */
4147 g_assert (method->mhandle);
4148 result = method->mhandle;
4149 *handle_class = mono_defaults.methodhandle_class;
4150 } else if (strcmp (oklass->name, "MonoArrayMethod") == 0) {
4151 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
4152 MonoType *mtype;
4153 MonoClass *klass;
4154 MonoMethod *method;
4155 gpointer iter;
4156 char *name;
4158 mtype = mono_reflection_type_get_handle (m->parent, error);
4159 return_val_if_nok (error, NULL);
4160 klass = mono_class_from_mono_type (mtype);
4162 /* Find the method */
4164 name = mono_string_to_utf8_checked (m->name, error);
4165 return_val_if_nok (error, NULL);
4166 iter = NULL;
4167 while ((method = mono_class_get_methods (klass, &iter))) {
4168 if (!strcmp (method->name, name))
4169 break;
4171 g_free (name);
4173 // FIXME:
4174 g_assert (method);
4175 // FIXME: Check parameters/return value etc. match
4177 result = method;
4178 *handle_class = mono_defaults.methodhandle_class;
4179 } else if (is_sre_method_builder (oklass) ||
4180 mono_is_sre_ctor_builder (oklass) ||
4181 is_sre_field_builder (oklass) ||
4182 is_sre_gparam_builder (oklass) ||
4183 is_sre_generic_instance (oklass) ||
4184 is_sre_array (oklass) ||
4185 is_sre_byref (oklass) ||
4186 is_sre_pointer (oklass) ||
4187 !strcmp (oklass->name, "FieldOnTypeBuilderInst") ||
4188 !strcmp (oklass->name, "MethodOnTypeBuilderInst") ||
4189 !strcmp (oklass->name, "ConstructorOnTypeBuilderInst")) {
4190 static MonoMethod *resolve_method;
4191 if (!resolve_method) {
4192 MonoMethod *m = mono_class_get_method_from_name_flags (mono_class_get_module_builder_class (), "RuntimeResolve", 1, 0);
4193 g_assert (m);
4194 mono_memory_barrier ();
4195 resolve_method = m;
4197 void *args [16];
4198 args [0] = obj;
4199 obj = mono_runtime_invoke_checked (resolve_method, NULL, args, error);
4200 mono_error_assert_ok (error);
4201 g_assert (obj);
4202 return mono_reflection_resolve_object (image, obj, handle_class, context, error);
4203 } else {
4204 g_print ("%s\n", obj->vtable->klass->name);
4205 g_assert_not_reached ();
4207 return result;
4210 #else /* DISABLE_REFLECTION_EMIT */
4212 MonoArray*
4213 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
4215 g_assert_not_reached ();
4216 return NULL;
4219 void
4220 mono_reflection_dynimage_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4222 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
4225 static gboolean
4226 mono_image_module_basic_init (MonoReflectionModuleBuilderHandle moduleb, MonoError *error)
4228 g_assert_not_reached ();
4229 return FALSE;
4232 guint32
4233 mono_image_insert_string (MonoReflectionModuleBuilderHandle module, MonoStringHandle str, MonoError *error)
4235 g_assert_not_reached ();
4236 return 0;
4239 guint32
4240 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObjectHandle obj, MonoArrayHandle opt_param_types, MonoError *error)
4242 g_assert_not_reached ();
4243 return 0;
4246 guint32
4247 mono_image_create_token (MonoDynamicImage *assembly, MonoObjectHandle obj,
4248 gboolean create_open_instance, gboolean register_token, MonoError *error)
4250 g_assert_not_reached ();
4251 return 0;
4254 void
4255 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides, MonoError *error)
4257 error_init (error);
4258 *overrides = NULL;
4259 *num_overrides = 0;
4262 MonoReflectionTypeHandle
4263 ves_icall_TypeBuilder_create_runtime_class (MonoReflectionTypeBuilderHandle tb, MonoError *error)
4265 g_assert_not_reached ();
4266 return NULL;
4269 void
4270 ves_icall_DynamicMethod_create_dynamic_method (MonoReflectionDynamicMethodHandle mb, MonoError *error)
4272 error_init (error);
4275 MonoType*
4276 mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
4278 error_init (error);
4279 if (!ref)
4280 return NULL;
4281 return ref->type;
4284 MonoType*
4285 mono_reflection_type_handle_mono_type (MonoReflectionTypeHandle ref, MonoError *error)
4287 error_init (error);
4288 if (MONO_HANDLE_IS_NULL (ref))
4289 return NULL;
4290 return MONO_HANDLE_GETVAL (ref, type);
4294 #endif /* DISABLE_REFLECTION_EMIT */
4296 void
4297 mono_sre_generic_param_table_entry_free (GenericParamTableEntry *entry)
4299 MONO_GC_UNREGISTER_ROOT_IF_MOVING (entry->gparam);
4300 g_free (entry);
4303 gint32
4304 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilderHandle mb, MonoObjectHandle obj, gboolean create_open_instance, MonoError *error)
4306 error_init (error);
4307 if (MONO_HANDLE_IS_NULL (obj)) {
4308 mono_error_set_argument_null (error, "obj", "");
4309 return 0;
4311 return mono_image_create_token (MONO_HANDLE_GETVAL (mb, dynamic_image), obj, create_open_instance, TRUE, error);
4314 gint32
4315 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilderHandle mb,
4316 MonoReflectionMethodHandle method,
4317 MonoArrayHandle opt_param_types,
4318 MonoError *error)
4320 error_init (error);
4321 if (MONO_HANDLE_IS_NULL (method)) {
4322 mono_error_set_argument_null (error, "method", "");
4323 return 0;
4326 return mono_image_create_method_token (MONO_HANDLE_GETVAL (mb, dynamic_image), MONO_HANDLE_CAST (MonoObject, method), opt_param_types, error);
4329 void
4330 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
4332 MonoError error;
4333 mono_image_create_pefile (mb, file, &error);
4334 mono_error_set_pending_exception (&error);
4337 void
4338 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
4340 MonoError error;
4341 mono_image_build_metadata (mb, &error);
4342 mono_error_set_pending_exception (&error);
4345 void
4346 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilderHandle mb, MonoObjectHandle obj, guint32 token, MonoError *error)
4348 error_init (error);
4349 /* This function may be called by ModuleBuilder.FixupTokens to update
4350 * an existing token, so replace is okay here. */
4351 mono_dynamic_image_register_token (MONO_HANDLE_GETVAL (mb, dynamic_image), token, obj, MONO_DYN_IMAGE_TOK_REPLACE);
4354 MonoObjectHandle
4355 ves_icall_ModuleBuilder_GetRegisteredToken (MonoReflectionModuleBuilderHandle mb, guint32 token, MonoError *error)
4357 error_init (error);
4358 MonoDynamicImage *dynamic_image = MONO_HANDLE_GETVAL (mb, dynamic_image);
4359 return mono_dynamic_image_get_registered_token (dynamic_image, token, error);
4362 #ifndef DISABLE_REFLECTION_EMIT
4363 MonoArray*
4364 ves_icall_CustomAttributeBuilder_GetBlob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
4366 MonoError error;
4367 MonoArray *result = mono_reflection_get_custom_attrs_blob_checked (assembly, ctor, ctorArgs, properties, propValues, fields, fieldValues, &error);
4368 mono_error_set_pending_exception (&error);
4369 return result;
4371 #endif
4373 void
4374 ves_icall_AssemblyBuilder_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4376 mono_reflection_dynimage_basic_init (assemblyb);
4379 void
4380 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionTypeHandle enumtype,
4381 MonoReflectionTypeHandle t,
4382 MonoError *error)
4384 error_init (error);
4385 MONO_HANDLE_SETVAL (enumtype, type, MonoType*, MONO_HANDLE_GETVAL (t, type));
4388 void
4389 ves_icall_ModuleBuilder_basic_init (MonoReflectionModuleBuilderHandle moduleb, MonoError *error)
4391 error_init (error);
4392 mono_image_module_basic_init (moduleb, error);
4395 guint32
4396 ves_icall_ModuleBuilder_getUSIndex (MonoReflectionModuleBuilderHandle module, MonoStringHandle str, MonoError *error)
4398 return mono_image_insert_string (module, str, error);
4401 void
4402 ves_icall_ModuleBuilder_set_wrappers_type (MonoReflectionModuleBuilderHandle moduleb, MonoReflectionTypeHandle ref_type, MonoError *error)
4404 error_init (error);
4405 MonoDynamicImage *image = MONO_HANDLE_GETVAL (moduleb, dynamic_image);
4406 MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
4408 g_assert (type);
4409 image->wrappers_type = mono_class_from_mono_type (type);