Revert some changes which don't have proper dependencies.
[mono-project.git] / mono / metadata / sre.c
blobfc706a487290cf6f651b0ab39737498ab7a4e66f
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/class-init.h"
21 #include "mono/metadata/debug-helpers.h"
22 #include "mono/metadata/dynamic-image-internals.h"
23 #include "mono/metadata/dynamic-stream-internals.h"
24 #include "mono/metadata/exception.h"
25 #include "mono/metadata/gc-internals.h"
26 #include "mono/metadata/mono-ptr-array.h"
27 #include "mono/metadata/object-internals.h"
28 #include "mono/metadata/profiler-private.h"
29 #include "mono/metadata/reflection-internals.h"
30 #include "mono/metadata/reflection-cache.h"
31 #include "mono/metadata/sre-internals.h"
32 #include "mono/metadata/custom-attrs-internals.h"
33 #include "mono/metadata/security-manager.h"
34 #include "mono/metadata/security-core-clr.h"
35 #include "mono/metadata/tabledefs.h"
36 #include "mono/metadata/tokentype.h"
37 #include "mono/metadata/abi-details.h"
38 #include "mono/utils/checked-build.h"
39 #include "mono/utils/mono-digest.h"
40 #include "mono/utils/w32api.h"
41 #ifdef MONO_CLASS_DEF_PRIVATE
42 /* Rationale: Some of the code here does MonoClass construction.
43 * FIXME: Move SRE class construction to class-init.c and unify with ordinary class construction.
45 #define REALLY_INCLUDE_CLASS_DEF 1
46 #include <mono/metadata/class-private-definition.h>
47 #undef REALLY_INCLUDE_CLASS_DEF
48 #endif
49 #include "icall-decl.h"
51 static GENERATE_GET_CLASS_WITH_CACHE (marshal_as_attribute, "System.Runtime.InteropServices", "MarshalAsAttribute");
52 static GENERATE_GET_CLASS_WITH_CACHE (module_builder, "System.Reflection.Emit", "ModuleBuilder");
54 static char* string_to_utf8_image_raw (MonoImage *image, MonoString *s, MonoError *error);
56 #ifndef DISABLE_REFLECTION_EMIT
57 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelperHandle helper, MonoError *error);
58 static gboolean ensure_runtime_vtable (MonoClass *klass, MonoError *error);
59 static void reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb);
60 static gboolean reflection_setup_internal_class (MonoReflectionTypeBuilderHandle tb, MonoError *error);
61 static gboolean reflection_init_generic_class (MonoReflectionTypeBuilderHandle tb, MonoError *error);
62 static gboolean reflection_setup_class_hierarchy (GHashTable *unparented, MonoError *error);
65 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
66 #endif
68 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
69 static MonoReflectionTypeHandle mono_reflection_type_get_underlying_system_type (MonoReflectionTypeHandle t, MonoError *error);
70 static gboolean is_sre_array (MonoClass *klass);
71 static gboolean is_sre_byref (MonoClass *klass);
72 static gboolean is_sre_pointer (MonoClass *klass);
73 static gboolean is_sre_generic_instance (MonoClass *klass);
74 static gboolean is_sre_type_builder (MonoClass *klass);
75 static gboolean is_sre_method_builder (MonoClass *klass);
76 static gboolean is_sre_field_builder (MonoClass *klass);
77 static gboolean is_sre_gparam_builder (MonoClass *klass);
78 static gboolean is_sre_enum_builder (MonoClass *klass);
79 static gboolean is_sr_mono_method (MonoClass *klass);
80 static gboolean is_sr_mono_field (MonoClass *klass);
82 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
83 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
84 static guint32 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObjectHandle obj, MonoArrayHandle opt_param_types, MonoError *error);
87 #ifndef DISABLE_REFLECTION_EMIT
88 static MonoType* mono_type_array_get_and_resolve_raw (MonoArray* array, int idx, MonoError* error);
89 #endif
91 static gboolean mono_image_module_basic_init (MonoReflectionModuleBuilderHandle module, MonoError *error);
93 void
94 mono_reflection_emit_init (void)
96 mono_dynamic_images_init ();
99 char*
100 string_to_utf8_image_raw (MonoImage *image, MonoString *s_raw, MonoError *error)
102 /* FIXME all callers to string_to_utf8_image_raw should use handles */
103 HANDLE_FUNCTION_ENTER ();
104 char* result = NULL;
105 error_init (error);
106 MONO_HANDLE_DCL (MonoString, s);
107 result = mono_string_to_utf8_image (image, s, error);
108 HANDLE_FUNCTION_RETURN_VAL (result);
111 static char*
112 type_get_fully_qualified_name (MonoType *type)
114 MONO_REQ_GC_NEUTRAL_MODE;
116 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
119 static char*
120 type_get_qualified_name (MonoType *type, MonoAssembly *ass)
122 MONO_REQ_GC_UNSAFE_MODE;
124 MonoClass *klass;
125 MonoAssembly *ta;
127 klass = mono_class_from_mono_type_internal (type);
128 if (!klass)
129 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
130 ta = klass->image->assembly;
131 if (assembly_is_dynamic (ta) || (ta == ass)) {
132 if (mono_class_is_ginst (klass) || mono_class_is_gtd (klass))
133 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
134 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
135 else
136 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
139 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
142 #ifndef DISABLE_REFLECTION_EMIT
144 * mp_g_alloc:
146 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
147 * from the C heap.
149 static gpointer
150 image_g_malloc (MonoImage *image, guint size)
152 MONO_REQ_GC_NEUTRAL_MODE;
154 if (image)
155 return mono_image_alloc (image, size);
156 else
157 return g_malloc (size);
159 #endif /* !DISABLE_REFLECTION_EMIT */
162 * image_g_alloc0:
164 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
165 * from the C heap.
167 gpointer
168 (mono_image_g_malloc0) (MonoImage *image, guint size)
170 MONO_REQ_GC_NEUTRAL_MODE;
172 if (image)
173 return mono_image_alloc0 (image, size);
174 else
175 return g_malloc0 (size);
179 * image_g_free:
180 * @image: a MonoImage
181 * @ptr: pointer
183 * If @image is NULL, free @ptr, otherwise do nothing.
185 static void
186 image_g_free (MonoImage *image, gpointer ptr)
188 if (image == NULL)
189 g_free (ptr);
192 #ifndef DISABLE_REFLECTION_EMIT
193 static char*
194 image_strdup (MonoImage *image, const char *s)
196 MONO_REQ_GC_NEUTRAL_MODE;
198 if (image)
199 return mono_image_strdup (image, s);
200 else
201 return g_strdup (s);
203 #endif
205 #define image_g_new(image,struct_type, n_structs) \
206 ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
208 #define image_g_new0(image,struct_type, n_structs) \
209 ((struct_type *) mono_image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
212 static void
213 alloc_table (MonoDynamicTable *table, guint nrows)
215 mono_dynimage_alloc_table (table, nrows);
218 static guint32
219 string_heap_insert (MonoDynamicStream *sh, const char *str)
221 return mono_dynstream_insert_string (sh, str);
224 static guint32
225 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
227 return mono_dynstream_add_data (stream, data, len);
231 * Despite the name, we handle also TypeSpec (with the above helper).
233 static guint32
234 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
236 return mono_dynimage_encode_typedef_or_ref_full (assembly, type, TRUE);
240 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
241 * dest may be misaligned.
243 static void
244 swap_with_size (gpointer void_dest, gconstpointer void_val, int len, int nelem)
246 char *dest = (char*)void_dest;
247 const char* val = (const char*)void_val;
248 MONO_REQ_GC_NEUTRAL_MODE;
249 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
250 int elem;
252 for (elem = 0; elem < nelem; ++elem) {
253 switch (len) {
254 case 1:
255 *dest = *val;
256 break;
257 case 2:
258 dest [0] = val [1];
259 dest [1] = val [0];
260 break;
261 case 4:
262 dest [0] = val [3];
263 dest [1] = val [2];
264 dest [2] = val [1];
265 dest [3] = val [0];
266 break;
267 case 8:
268 dest [0] = val [7];
269 dest [1] = val [6];
270 dest [2] = val [5];
271 dest [3] = val [4];
272 dest [4] = val [3];
273 dest [5] = val [2];
274 dest [6] = val [1];
275 dest [7] = val [0];
276 break;
277 default:
278 g_assert_not_reached ();
280 dest += len;
281 val += len;
283 #else
284 memcpy (dest, val, len * nelem);
285 #endif
288 guint32
289 mono_reflection_method_count_clauses (MonoReflectionILGen *ilgen)
291 MONO_REQ_GC_UNSAFE_MODE;
293 guint32 num_clauses = 0;
294 int i;
296 MonoILExceptionInfo *ex_info;
297 for (i = 0; i < mono_array_length_internal (ilgen->ex_handlers); ++i) {
298 ex_info = (MonoILExceptionInfo*)mono_array_addr_internal (ilgen->ex_handlers, MonoILExceptionInfo, i);
299 if (ex_info->handlers)
300 num_clauses += mono_array_length_internal (ex_info->handlers);
301 else
302 num_clauses++;
305 return num_clauses;
308 #ifndef DISABLE_REFLECTION_EMIT
309 static MonoExceptionClause*
310 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses, MonoError *error)
312 MONO_REQ_GC_UNSAFE_MODE;
314 error_init (error);
316 MonoExceptionClause *clauses;
317 MonoExceptionClause *clause;
318 MonoILExceptionInfo *ex_info;
319 MonoILExceptionBlock *ex_block;
320 guint32 finally_start;
321 int i, j, clause_index;
323 clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
325 clause_index = 0;
326 for (i = mono_array_length_internal (ilgen->ex_handlers) - 1; i >= 0; --i) {
327 ex_info = (MonoILExceptionInfo*)mono_array_addr_internal (ilgen->ex_handlers, MonoILExceptionInfo, i);
328 finally_start = ex_info->start + ex_info->len;
329 if (!ex_info->handlers)
330 continue;
331 for (j = 0; j < mono_array_length_internal (ex_info->handlers); ++j) {
332 ex_block = (MonoILExceptionBlock*)mono_array_addr_internal (ex_info->handlers, MonoILExceptionBlock, j);
333 clause = &(clauses [clause_index]);
335 clause->flags = ex_block->type;
336 clause->try_offset = ex_info->start;
338 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
339 clause->try_len = finally_start - ex_info->start;
340 else
341 clause->try_len = ex_info->len;
342 clause->handler_offset = ex_block->start;
343 clause->handler_len = ex_block->len;
344 if (ex_block->extype) {
345 MonoType *extype = mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype, error);
347 if (!is_ok (error)) {
348 image_g_free (image, clauses);
349 return NULL;
351 clause->data.catch_class = mono_class_from_mono_type_internal (extype);
352 } else {
353 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
354 clause->data.filter_offset = ex_block->filter_offset;
355 else
356 clause->data.filter_offset = 0;
358 finally_start = ex_block->start + ex_block->len;
360 clause_index ++;
364 return clauses;
366 #endif /* !DISABLE_REFLECTION_EMIT */
368 #ifndef DISABLE_REFLECTION_EMIT
370 * LOCKING: Acquires the loader lock.
372 static void
373 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
375 MONO_REQ_GC_UNSAFE_MODE;
377 MonoCustomAttrInfo *ainfo, *tmp;
379 if (!cattrs || !mono_array_length_internal (cattrs))
380 return;
382 ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
384 mono_loader_lock ();
385 tmp = (MonoCustomAttrInfo *)mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
386 if (tmp)
387 mono_custom_attrs_free (tmp);
388 mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
389 mono_loader_unlock ();
392 #else
393 //FIXME some code compiled under DISABLE_REFLECTION_EMIT depends on this function, we should be more aggressively disabling things
394 static void
395 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
398 #endif
400 guint32
401 mono_reflection_resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
403 MONO_REQ_GC_UNSAFE_MODE;
405 MonoDynamicTable *table;
406 guint32 token;
407 guint32 *values;
408 guint32 cols [MONO_ASSEMBLY_SIZE];
409 const char *pubkey;
410 guint32 publen;
412 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
413 return token;
415 if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
416 table = &assembly->tables [MONO_TABLE_MODULEREF];
417 token = table->next_idx ++;
418 table->rows ++;
419 alloc_table (table, table->rows);
420 values = table->values + token * MONO_MODULEREF_SIZE;
421 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
423 token <<= MONO_RESOLUTION_SCOPE_BITS;
424 token |= MONO_RESOLUTION_SCOPE_MODULEREF;
425 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
427 return token;
430 if (assembly_is_dynamic (image->assembly))
431 /* FIXME: */
432 memset (cols, 0, sizeof (cols));
433 else {
434 /* image->assembly->image is the manifest module */
435 image = image->assembly->image;
436 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
439 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
440 token = table->next_idx ++;
441 table->rows ++;
442 alloc_table (table, table->rows);
443 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
444 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
445 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
446 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
447 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
448 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
449 values [MONO_ASSEMBLYREF_FLAGS] = 0;
450 values [MONO_ASSEMBLYREF_CULTURE] = 0;
451 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
453 if (strcmp ("", image->assembly->aname.culture)) {
454 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
455 image->assembly->aname.culture);
458 if ((pubkey = mono_image_get_public_key (image, &publen))) {
459 guchar pubtoken [9];
460 pubtoken [0] = 8;
461 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
462 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
463 } else {
464 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
466 token <<= MONO_RESOLUTION_SCOPE_BITS;
467 token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
468 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
469 return token;
472 #ifndef DISABLE_REFLECTION_EMIT
473 gboolean
474 mono_reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error)
476 MONO_REQ_GC_UNSAFE_MODE;
478 error_init (error);
479 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
481 rmb->ilgen = mb->ilgen;
482 rmb->rtype = (MonoReflectionType*)mb->rtype;
483 return_val_if_nok (error, FALSE);
484 rmb->parameters = mb->parameters;
485 rmb->generic_params = mb->generic_params;
486 rmb->generic_container = mb->generic_container;
487 rmb->opt_types = NULL;
488 rmb->pinfo = mb->pinfo;
489 rmb->attrs = mb->attrs;
490 rmb->iattrs = mb->iattrs;
491 rmb->call_conv = mb->call_conv;
492 rmb->code = mb->code;
493 rmb->type = mb->type;
494 rmb->name = mb->name;
495 rmb->table_idx = &mb->table_idx;
496 rmb->init_locals = mb->init_locals;
497 rmb->skip_visibility = FALSE;
498 rmb->return_modreq = mb->return_modreq;
499 rmb->return_modopt = mb->return_modopt;
500 rmb->param_modreq = mb->param_modreq;
501 rmb->param_modopt = mb->param_modopt;
502 rmb->permissions = mb->permissions;
503 rmb->mhandle = mb->mhandle;
504 rmb->nrefs = 0;
505 rmb->refs = NULL;
507 if (mb->dll) {
508 rmb->charset = mb->charset;
509 rmb->extra_flags = mb->extra_flags;
510 rmb->native_cc = mb->native_cc;
511 rmb->dllentry = mb->dllentry;
512 rmb->dll = mb->dll;
515 return TRUE;
518 gboolean
519 mono_reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error)
521 MONO_REQ_GC_UNSAFE_MODE;
523 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
525 error_init (error);
527 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
529 rmb->ilgen = mb->ilgen;
530 rmb->rtype = mono_type_get_object_checked (mono_domain_get (), mono_get_void_type (), error);
531 return_val_if_nok (error, FALSE);
532 rmb->parameters = mb->parameters;
533 rmb->generic_params = NULL;
534 rmb->generic_container = NULL;
535 rmb->opt_types = NULL;
536 rmb->pinfo = mb->pinfo;
537 rmb->attrs = mb->attrs;
538 rmb->iattrs = mb->iattrs;
539 rmb->call_conv = mb->call_conv;
540 rmb->code = NULL;
541 rmb->type = mb->type;
542 rmb->name = mono_string_new_checked (mono_domain_get (), name, error);
543 return_val_if_nok (error, FALSE);
544 rmb->table_idx = &mb->table_idx;
545 rmb->init_locals = mb->init_locals;
546 rmb->skip_visibility = FALSE;
547 rmb->return_modreq = NULL;
548 rmb->return_modopt = NULL;
549 rmb->param_modreq = mb->param_modreq;
550 rmb->param_modopt = mb->param_modopt;
551 rmb->permissions = mb->permissions;
552 rmb->mhandle = mb->mhandle;
553 rmb->nrefs = 0;
554 rmb->refs = NULL;
556 return TRUE;
559 static void
560 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
562 MONO_REQ_GC_UNSAFE_MODE;
564 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
566 rmb->ilgen = mb->ilgen;
567 rmb->rtype = mb->rtype;
568 rmb->parameters = mb->parameters;
569 rmb->generic_params = NULL;
570 rmb->generic_container = NULL;
571 rmb->opt_types = NULL;
572 rmb->pinfo = NULL;
573 rmb->attrs = mb->attrs;
574 rmb->iattrs = 0;
575 rmb->call_conv = mb->call_conv;
576 rmb->code = NULL;
577 rmb->type = (MonoObject *) mb->owner;
578 rmb->name = mb->name;
579 rmb->table_idx = NULL;
580 rmb->init_locals = mb->init_locals;
581 rmb->skip_visibility = mb->skip_visibility;
582 rmb->return_modreq = NULL;
583 rmb->return_modopt = NULL;
584 rmb->param_modreq = NULL;
585 rmb->param_modopt = NULL;
586 rmb->permissions = NULL;
587 rmb->mhandle = mb->mhandle;
588 rmb->nrefs = 0;
589 rmb->refs = NULL;
591 #else /* DISABLE_REFLECTION_EMIT */
592 gboolean
593 mono_reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error) {
594 g_assert_not_reached ();
595 return FALSE;
597 gboolean
598 mono_reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error)
600 g_assert_not_reached ();
601 return FALSE;
603 #endif /* DISABLE_REFLECTION_EMIT */
605 #ifndef DISABLE_REFLECTION_EMIT
606 static guint32
607 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
609 MONO_REQ_GC_NEUTRAL_MODE;
611 MonoDynamicTable *table;
612 guint32 *values;
613 guint32 token, pclass;
615 switch (parent & MONO_TYPEDEFORREF_MASK) {
616 case MONO_TYPEDEFORREF_TYPEREF:
617 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
618 break;
619 case MONO_TYPEDEFORREF_TYPESPEC:
620 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
621 break;
622 case MONO_TYPEDEFORREF_TYPEDEF:
623 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
624 break;
625 default:
626 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
627 return 0;
629 /* extract the index */
630 parent >>= MONO_TYPEDEFORREF_BITS;
632 table = &assembly->tables [MONO_TABLE_MEMBERREF];
634 if (assembly->save) {
635 alloc_table (table, table->rows + 1);
636 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
637 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
638 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
639 values [MONO_MEMBERREF_SIGNATURE] = sig;
642 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
643 table->next_idx ++;
645 return token;
649 * Insert a memberef row into the metadata: the token that point to the memberref
650 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
651 * mono_image_get_fieldref_token()).
652 * The sig param is an index to an already built signature.
654 static guint32
655 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
657 MONO_REQ_GC_NEUTRAL_MODE;
659 guint32 parent = mono_image_typedef_or_ref (assembly, type);
660 return mono_image_add_memberef_row (assembly, parent, name, sig);
664 guint32
665 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
667 MONO_REQ_GC_NEUTRAL_MODE;
669 guint32 token;
670 MonoMethodSignature *sig;
672 create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
674 if (create_typespec) {
675 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
676 if (token)
677 return token;
680 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
681 if (token && !create_typespec)
682 return token;
684 g_assert (!method->is_inflated);
685 if (!token) {
687 * A methodref signature can't contain an unmanaged calling convention.
689 sig = mono_metadata_signature_dup (mono_method_signature_internal (method));
690 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
691 sig->call_convention = MONO_CALL_DEFAULT;
692 token = mono_image_get_memberref_token (assembly, m_class_get_byval_arg (method->klass),
693 method->name, mono_dynimage_encode_method_signature (assembly, sig));
694 g_free (sig);
695 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
698 if (create_typespec) {
699 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
700 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
701 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
703 if (assembly->save) {
704 guint32 *values;
706 alloc_table (table, table->rows + 1);
707 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
708 values [MONO_METHODSPEC_METHOD] = token;
709 values [MONO_METHODSPEC_SIGNATURE] = mono_dynimage_encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
712 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
713 table->next_idx ++;
714 /*methodspec and memberef tokens are diferent, */
715 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
716 return token;
718 return token;
721 static guint32
722 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
723 const gchar *name, guint32 sig)
725 MonoDynamicTable *table;
726 guint32 token;
727 guint32 *values;
729 table = &assembly->tables [MONO_TABLE_MEMBERREF];
731 if (assembly->save) {
732 alloc_table (table, table->rows + 1);
733 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
734 values [MONO_MEMBERREF_CLASS] = original;
735 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
736 values [MONO_MEMBERREF_SIGNATURE] = sig;
739 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
740 table->next_idx ++;
742 return token;
745 #else /* DISABLE_REFLECTION_EMIT */
747 guint32
748 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
750 g_assert_not_reached ();
751 return -1;
753 #endif
755 static gboolean
756 is_field_on_inst (MonoClassField *field)
758 return mono_class_is_ginst (field->parent) && mono_class_get_generic_class (field->parent)->is_dynamic;
761 static gboolean
762 is_field_on_gtd (MonoClassField *field)
764 return mono_class_is_gtd (field->parent);
767 #ifndef DISABLE_REFLECTION_EMIT
768 static guint32
769 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoClassField *field)
771 MonoType *type;
772 guint32 token;
774 g_assert (field);
775 g_assert (field->parent);
777 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, field));
778 if (token)
779 return token;
781 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) {
782 int index = field - field->parent->fields;
783 type = mono_field_get_type_internal (&mono_class_get_generic_class (field->parent)->container_class->fields [index]);
784 } else {
785 type = mono_field_get_type_internal (field);
787 token = mono_image_get_memberref_token (assembly, m_class_get_byval_arg (field->parent),
788 mono_field_get_name (field),
789 mono_dynimage_encode_fieldref_signature (assembly, field->parent->image, type));
790 g_hash_table_insert (assembly->handleref, field, GUINT_TO_POINTER(token));
791 return token;
794 static guint32
795 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
797 MonoDynamicTable *table;
798 guint32 *values;
799 guint32 token, mtoken = 0, sig;
800 MonoMethodInflated *imethod;
801 MonoMethod *declaring;
803 table = &assembly->tables [MONO_TABLE_METHODSPEC];
805 g_assert (method->is_inflated);
806 imethod = (MonoMethodInflated *) method;
807 declaring = imethod->declaring;
809 sig = mono_dynimage_encode_method_signature (assembly, mono_method_signature_internal (declaring));
810 mtoken = mono_image_get_memberref_token (assembly, m_class_get_byval_arg (method->klass), declaring->name, sig);
812 if (!mono_method_signature_internal (declaring)->generic_param_count)
813 return mtoken;
815 switch (mono_metadata_token_table (mtoken)) {
816 case MONO_TABLE_MEMBERREF:
817 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
818 break;
819 case MONO_TABLE_METHOD:
820 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
821 break;
822 default:
823 g_assert_not_reached ();
826 sig = mono_dynimage_encode_generic_method_sig (assembly, mono_method_get_context (method));
828 if (assembly->save) {
829 alloc_table (table, table->rows + 1);
830 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
831 values [MONO_METHODSPEC_METHOD] = mtoken;
832 values [MONO_METHODSPEC_SIGNATURE] = sig;
835 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
836 table->next_idx ++;
838 return token;
841 static guint32
842 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
844 MonoMethodInflated *imethod;
845 guint32 token;
847 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
848 if (token)
849 return token;
851 g_assert (method->is_inflated);
852 imethod = (MonoMethodInflated *) method;
854 if (mono_method_signature_internal (imethod->declaring)->generic_param_count) {
855 token = method_encode_methodspec (assembly, method);
856 } else {
857 guint32 sig = mono_dynimage_encode_method_signature (
858 assembly, mono_method_signature_internal (imethod->declaring));
859 token = mono_image_get_memberref_token (
860 assembly, m_class_get_byval_arg (method->klass), method->name, sig);
863 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
864 return token;
867 static guint32
868 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
870 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
871 guint32 sig, token;
873 sig = mono_dynimage_encode_method_signature (assembly, mono_method_signature_internal (imethod->declaring));
874 token = mono_image_get_memberref_token (
875 assembly, m_class_get_byval_arg (m->klass), m->name, sig);
877 return token;
880 static guint32
881 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelperHandle helper, MonoError *error)
883 guint32 idx;
884 MonoDynamicTable *table;
885 guint32 *values;
887 error_init (error);
889 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
890 idx = table->next_idx ++;
891 table->rows ++;
892 alloc_table (table, table->rows);
893 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
895 values [MONO_STAND_ALONE_SIGNATURE] =
896 mono_dynimage_encode_reflection_sighelper (assembly, helper, error);
897 return_val_if_nok (error, 0);
899 return idx;
902 static int
903 reflection_cc_to_file (int call_conv) {
904 switch (call_conv & 0x3) {
905 case 0:
906 case 1: return MONO_CALL_DEFAULT;
907 case 2: return MONO_CALL_VARARG;
908 default:
909 g_assert_not_reached ();
911 return 0;
913 #endif /* !DISABLE_REFLECTION_EMIT */
915 struct _ArrayMethod {
916 MonoType *parent;
917 MonoMethodSignature *sig;
918 char *name;
919 guint32 token;
922 void
923 mono_sre_array_method_free (ArrayMethod *am)
925 g_free (am->sig);
926 g_free (am->name);
927 g_free (am);
930 #ifndef DISABLE_REFLECTION_EMIT
931 static guint32
932 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethodHandle m, MonoError *error)
934 MonoMethodSignature *sig = NULL;
935 char *name = NULL;
937 error_init (error);
939 MonoArrayHandle parameters = MONO_HANDLE_NEW_GET (MonoArray, m, parameters);
940 guint32 nparams = mono_array_handle_length (parameters);
941 sig = (MonoMethodSignature *)g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
942 sig->hasthis = 1;
943 sig->sentinelpos = -1;
944 sig->call_convention = reflection_cc_to_file (MONO_HANDLE_GETVAL (m, call_conv));
945 sig->param_count = nparams;
946 MonoReflectionTypeHandle ret = MONO_HANDLE_NEW_GET (MonoReflectionType, m, ret);
947 if (!MONO_HANDLE_IS_NULL (ret)) {
948 sig->ret = mono_reflection_type_handle_mono_type (ret, error);
949 goto_if_nok (error, fail);
950 } else
951 sig->ret = mono_get_void_type ();
953 MonoReflectionTypeHandle parent;
954 parent = MONO_HANDLE_NEW_GET (MonoReflectionType, m, parent);
955 MonoType *mtype;
956 mtype = mono_reflection_type_handle_mono_type (parent, error);
957 goto_if_nok (error, fail);
959 for (int i = 0; i < nparams; ++i) {
960 sig->params [i] = mono_type_array_get_and_resolve (parameters, i, error);
961 goto_if_nok (error, fail);
964 MonoStringHandle mname;
965 mname = MONO_HANDLE_NEW_GET (MonoString, m, name);
966 name = mono_string_handle_to_utf8 (mname, error);
967 goto_if_nok (error, fail);
969 ArrayMethod *am;
970 am = NULL;
971 for (GList *tmp = assembly->array_methods; tmp; tmp = tmp->next) {
972 am = (ArrayMethod *)tmp->data;
973 if (strcmp (name, am->name) == 0 &&
974 mono_metadata_type_equal (am->parent, mtype) &&
975 mono_metadata_signature_equal (am->sig, sig)) {
976 g_free (name);
977 g_free (sig);
978 MONO_HANDLE_SETVAL (m, table_idx, guint32, am->token & 0xffffff);
979 return am->token;
982 am = g_new0 (ArrayMethod, 1);
983 am->name = name;
984 am->sig = sig;
985 am->parent = mtype;
986 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
987 mono_dynimage_encode_method_signature (assembly, sig));
988 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
989 MONO_HANDLE_SETVAL (m, table_idx, guint32, am->token & 0xffffff);
990 return am->token;
991 fail:
992 g_free (name);
993 g_free (sig);
994 return 0;
997 #endif
999 #ifndef DISABLE_REFLECTION_EMIT
1002 * mono_image_insert_string:
1003 * @module: module builder object
1004 * @str: a string
1006 * Insert @str into the user string stream of @module.
1008 guint32
1009 mono_image_insert_string (MonoReflectionModuleBuilderHandle ref_module, MonoStringHandle str, MonoError *error)
1011 HANDLE_FUNCTION_ENTER ();
1012 guint32 idx;
1013 char buf [16];
1014 char *b = buf;
1015 guint32 token = 0;
1017 MonoDynamicImage *assembly = MONO_HANDLE_GETVAL (ref_module, dynamic_image);
1018 if (!assembly) {
1019 if (!mono_image_module_basic_init (ref_module, error))
1020 goto leave;
1022 assembly = MONO_HANDLE_GETVAL (ref_module, dynamic_image);
1024 g_assert (assembly != NULL);
1026 if (assembly->save) {
1027 int32_t length = mono_string_length_internal (MONO_HANDLE_RAW (str));
1028 mono_metadata_encode_value (1 | (length * 2), b, &b);
1029 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
1030 /* pinned */
1031 uint32_t gchandle = mono_gchandle_from_handle (MONO_HANDLE_CAST (MonoObject, str), TRUE);
1032 const char *p = (const char*)mono_string_chars_internal (MONO_HANDLE_RAW (str));
1033 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1035 char *swapped = g_malloc (2 * length);
1037 swap_with_size (swapped, p, 2, length);
1038 mono_image_add_stream_data (&assembly->us, swapped, length * 2);
1039 g_free (swapped);
1041 #else
1042 mono_image_add_stream_data (&assembly->us, p, length * 2);
1043 #endif
1044 mono_gchandle_free_internal (gchandle);
1045 mono_image_add_stream_data (&assembly->us, "", 1);
1046 } else {
1047 idx = assembly->us.index ++;
1050 token = MONO_TOKEN_STRING | idx;
1051 mono_dynamic_image_register_token (assembly, token, MONO_HANDLE_CAST (MonoObject, str), MONO_DYN_IMAGE_TOK_NEW);
1053 leave:
1054 HANDLE_FUNCTION_RETURN_VAL (token);
1057 static guint32
1058 create_method_token (MonoDynamicImage *assembly, MonoMethod *method, MonoArrayHandle opt_param_types, MonoError *error)
1060 guint32 sig_token, parent;
1063 int nargs = mono_array_handle_length (opt_param_types);
1064 MonoMethodSignature *old = mono_method_signature_internal (method);
1065 MonoMethodSignature *sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
1067 sig->hasthis = old->hasthis;
1068 sig->explicit_this = old->explicit_this;
1069 sig->call_convention = old->call_convention;
1070 sig->generic_param_count = old->generic_param_count;
1071 sig->param_count = old->param_count + nargs;
1072 sig->sentinelpos = old->param_count;
1073 sig->ret = old->ret;
1075 for (int i = 0; i < old->param_count; i++)
1076 sig->params [i] = old->params [i];
1078 MonoReflectionTypeHandle rt = MONO_HANDLE_NEW (MonoReflectionType, NULL);
1079 for (int i = 0; i < nargs; i++) {
1080 MONO_HANDLE_ARRAY_GETREF (rt, opt_param_types, i);
1081 sig->params [old->param_count + i] = mono_reflection_type_handle_mono_type (rt, error);
1082 goto_if_nok (error, fail);
1085 parent = mono_image_typedef_or_ref (assembly, m_class_get_byval_arg (method->klass));
1086 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
1087 parent >>= MONO_TYPEDEFORREF_BITS;
1089 parent <<= MONO_MEMBERREF_PARENT_BITS;
1090 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
1092 sig_token = mono_dynimage_encode_method_signature (assembly, sig);
1093 guint32 token;
1094 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
1095 g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
1096 return token;
1097 fail:
1098 return 0;
1101 guint32
1102 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObjectHandle obj, MonoArrayHandle opt_param_types, MonoError *error)
1104 guint32 token = 0;
1106 error_init (error);
1108 MonoClass *klass = mono_handle_class (obj);
1109 if (strcmp (klass->name, "RuntimeMethodInfo") == 0 || strcmp (klass->name, "RuntimeConstructorInfo") == 0) {
1110 MonoReflectionMethodHandle ref_method = MONO_HANDLE_CAST (MonoReflectionMethod, obj);
1111 MonoMethod *method = MONO_HANDLE_GETVAL (ref_method, method);
1112 g_assert (!MONO_HANDLE_IS_NULL (opt_param_types) && (mono_method_signature_internal (method)->sentinelpos >= 0));
1113 token = create_method_token (assembly, method, opt_param_types, error);
1114 goto_if_nok (error, fail);
1115 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
1116 g_assert_not_reached ();
1117 } else {
1118 g_error ("requested method token for %s\n", klass->name);
1121 mono_dynamic_image_register_token (assembly, token, obj, MONO_DYN_IMAGE_TOK_NEW);
1122 return token;
1123 fail:
1124 g_assert (!mono_error_ok (error));
1125 return 0;
1129 * mono_image_create_token:
1130 * @assembly: a dynamic assembly
1131 * @obj:
1132 * @register_token: Whenever to register the token in the assembly->tokens hash.
1134 * Get a token to insert in the IL code stream for the given MemberInfo.
1135 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
1136 * the table_idx-es were recomputed, so registering the token would overwrite an existing
1137 * entry.
1139 guint32
1140 mono_image_create_token (MonoDynamicImage *assembly, MonoObjectHandle obj,
1141 gboolean create_open_instance, gboolean register_token,
1142 MonoError *error)
1144 HANDLE_FUNCTION_ENTER ();
1145 guint32 token = 0;
1147 error_init (error);
1149 MonoClass *klass = mono_handle_class (obj);
1150 MonoObjectHandle register_obj = MONO_HANDLE_NEW (MonoObject, NULL);
1151 MONO_HANDLE_ASSIGN (register_obj, obj);
1153 /* Check for user defined reflection objects */
1154 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
1155 if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0)) {
1156 mono_error_set_not_supported (error, "User defined subclasses of System.Type are not yet supported");
1157 goto leave;
1160 /* This function is called from ModuleBuilder:getToken multiple times for the same objects */
1161 int how_collide;
1162 how_collide = MONO_DYN_IMAGE_TOK_SAME_OK;
1164 if (strcmp (klass->name, "RuntimeType") == 0) {
1165 MonoType *type = mono_reflection_type_handle_mono_type (MONO_HANDLE_CAST (MonoReflectionType, obj), error);
1166 goto_if_nok (error, leave);
1167 MonoClass *mc = mono_class_from_mono_type_internal (type);
1168 token = mono_metadata_token_from_dor (
1169 mono_dynimage_encode_typedef_or_ref_full (assembly, type, !mono_class_is_gtd (mc) || create_open_instance));
1170 /* If it's a RuntimeType now, we could have registered a
1171 * TypeBuilder for it before, so replacing is okay. */
1172 how_collide = MONO_DYN_IMAGE_TOK_REPLACE;
1173 } else if (strcmp (klass->name, "RuntimeMethodInfo") == 0 ||
1174 strcmp (klass->name, "RuntimeConstructorInfo") == 0) {
1175 MonoReflectionMethodHandle m = MONO_HANDLE_CAST (MonoReflectionMethod, obj);
1176 MonoMethod *method = MONO_HANDLE_GETVAL (m, method);
1177 if (method->is_inflated) {
1178 if (create_open_instance) {
1179 guint32 methodspec_token = mono_image_get_methodspec_token (assembly, method);
1180 MonoReflectionMethodHandle canonical_obj =
1181 mono_method_get_object_handle (MONO_HANDLE_DOMAIN (obj), method, NULL, error);
1182 goto_if_nok (error, leave);
1183 MONO_HANDLE_ASSIGN (register_obj, canonical_obj);
1184 token = methodspec_token;
1185 } else
1186 token = mono_image_get_inflated_method_token (assembly, method);
1187 } else if ((method->klass->image == &assembly->image) &&
1188 !mono_class_is_ginst (method->klass) &&
1189 !mono_class_is_gtd (method->klass)) {
1190 static guint32 method_table_idx = 0xffffff;
1191 if (method->klass->wastypebuilder) {
1192 /* we use the same token as the one that was assigned
1193 * to the Methodbuilder.
1194 * FIXME: do the equivalent for Fields.
1196 token = method->token;
1197 how_collide = MONO_DYN_IMAGE_TOK_REPLACE;
1198 } else {
1200 * Each token should have a unique index, but the indexes are
1201 * assigned by managed code, so we don't know about them. An
1202 * easy solution is to count backwards...
1204 method_table_idx --;
1205 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
1206 how_collide = MONO_DYN_IMAGE_TOK_NEW;
1208 } else {
1209 guint32 methodref_token = mono_image_get_methodref_token (assembly, method, create_open_instance);
1210 /* We need to register a 'canonical' object. The same
1211 * MonoMethod could have been reflected via different
1212 * classes so the MonoReflectionMethod:reftype could be
1213 * different, and the object lookup in
1214 * dynamic_image_register_token would assert assert. So
1215 * we pick the MonoReflectionMethod object that has the
1216 * reflected type as NULL (ie, take the declaring type
1217 * of the method) */
1218 MonoReflectionMethodHandle canonical_obj =
1219 mono_method_get_object_handle (MONO_HANDLE_DOMAIN (obj), method, NULL, error);
1220 goto_if_nok (error, leave);
1221 MONO_HANDLE_ASSIGN (register_obj, canonical_obj);
1222 token = methodref_token;
1224 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
1225 } else if (strcmp (klass->name, "RuntimeFieldInfo") == 0) {
1226 MonoReflectionFieldHandle f = MONO_HANDLE_CAST (MonoReflectionField, obj);
1227 MonoClassField *field = MONO_HANDLE_GETVAL (f, field);
1228 if ((field->parent->image == &assembly->image) &&
1229 !is_field_on_gtd (field) &&
1230 !is_field_on_inst (field)) {
1231 static guint32 field_table_idx = 0xffffff;
1232 field_table_idx --;
1233 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
1234 g_assert (!mono_class_is_gtd (field->parent));
1235 how_collide = MONO_DYN_IMAGE_TOK_NEW;
1236 } else {
1237 guint32 fieldref_token = mono_image_get_fieldref_token (assembly, field);
1238 /* Same as methodref: get a canonical object to
1239 * register with the token. */
1240 MonoReflectionFieldHandle canonical_obj =
1241 mono_field_get_object_handle (MONO_HANDLE_DOMAIN (obj), field->parent, field, error);
1242 goto_if_nok (error, leave);
1243 MONO_HANDLE_ASSIGN (register_obj, canonical_obj);
1244 token = fieldref_token;
1246 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
1247 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
1248 MonoReflectionArrayMethodHandle m = MONO_HANDLE_CAST (MonoReflectionArrayMethod, obj);
1249 /* mono_image_get_array_token caches tokens by signature */
1250 guint32 array_token = mono_image_get_array_token (assembly, m, error);
1251 goto_if_nok (error, leave);
1252 token = array_token;
1253 /* ModuleBuilder:GetArrayMethod() always returns a fresh
1254 * MonoArrayMethod instance even given the same method name and
1255 * signature. But they're all interchangeable, so it's okay to
1256 * replace.
1258 how_collide = MONO_DYN_IMAGE_TOK_REPLACE;
1259 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
1260 MonoReflectionSigHelperHandle s = MONO_HANDLE_CAST (MonoReflectionSigHelper, obj);
1261 /* always returns a fresh token */
1262 guint32 sig_token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s, error);
1263 goto_if_nok (error, leave);
1264 token = sig_token;
1265 how_collide = MONO_DYN_IMAGE_TOK_NEW;
1266 } else {
1267 g_error ("requested token for %s\n", klass->name);
1270 if (register_token)
1271 mono_dynamic_image_register_token (assembly, token, register_obj, how_collide);
1273 leave:
1274 HANDLE_FUNCTION_RETURN_VAL (token);
1278 #endif
1280 #ifndef DISABLE_REFLECTION_EMIT
1282 static gboolean
1283 assemblybuilderaccess_can_refonlyload (guint32 access)
1285 return (access & 0x4) != 0;
1288 static gboolean
1289 assemblybuilderaccess_can_run (guint32 access)
1291 return (access & MonoAssemblyBuilderAccess_Run) != 0;
1294 static gboolean
1295 assemblybuilderaccess_can_save (guint32 access)
1297 return (access & MonoAssemblyBuilderAccess_Save) != 0;
1302 * mono_reflection_dynimage_basic_init:
1303 * @assembly: an assembly builder object
1305 * Create the MonoImage that represents the assembly builder and setup some
1306 * of the helper hash table and the basic metadata streams.
1308 void
1309 mono_reflection_dynimage_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
1311 ERROR_DECL (error);
1312 MonoDynamicAssembly *assembly;
1313 MonoDynamicImage *image;
1314 MonoDomain *domain = mono_object_domain (assemblyb);
1316 if (assemblyb->dynamic_assembly)
1317 return;
1319 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
1321 MONO_PROFILER_RAISE (assembly_loading, (&assembly->assembly));
1323 assembly->assembly.ref_count = 1;
1324 assembly->assembly.dynamic = TRUE;
1325 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
1326 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
1327 assembly->assembly.basedir = mono_string_to_utf8_checked_internal (assemblyb->dir, error);
1328 if (mono_error_set_pending_exception (error))
1329 return;
1330 if (assemblyb->culture) {
1331 assembly->assembly.aname.culture = mono_string_to_utf8_checked_internal (assemblyb->culture, error);
1332 if (mono_error_set_pending_exception (error))
1333 return;
1334 } else
1335 assembly->assembly.aname.culture = g_strdup ("");
1337 if (assemblyb->version) {
1338 char *vstr = mono_string_to_utf8_checked_internal (assemblyb->version, error);
1339 if (mono_error_set_pending_exception (error))
1340 return;
1341 char **version = g_strsplit (vstr, ".", 4);
1342 char **parts = version;
1343 assembly->assembly.aname.major = atoi (*parts++);
1344 assembly->assembly.aname.minor = atoi (*parts++);
1345 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
1346 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
1348 g_strfreev (version);
1349 g_free (vstr);
1350 } else {
1351 assembly->assembly.aname.major = 0;
1352 assembly->assembly.aname.minor = 0;
1353 assembly->assembly.aname.build = 0;
1354 assembly->assembly.aname.revision = 0;
1357 /* SRE assemblies are loaded into the individual loading context, ie,
1358 * they only fire AssemblyResolve events, they don't cause probing for
1359 * referenced assemblies to happen. */
1360 assembly->assembly.context.kind = assemblybuilderaccess_can_refonlyload (assemblyb->access) ? MONO_ASMCTX_REFONLY : MONO_ASMCTX_INDIVIDUAL;
1361 assembly->run = assemblybuilderaccess_can_run (assemblyb->access);
1362 assembly->save = assemblybuilderaccess_can_save (assemblyb->access);
1363 assembly->domain = domain;
1365 char *assembly_name = mono_string_to_utf8_checked_internal (assemblyb->name, error);
1366 if (mono_error_set_pending_exception (error))
1367 return;
1368 image = mono_dynamic_image_create (assembly, assembly_name, g_strdup ("RefEmit_YouForgotToDefineAModule"));
1369 image->initial_image = TRUE;
1370 assembly->assembly.aname.name = image->image.name;
1371 assembly->assembly.image = &image->image;
1372 if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
1373 /* -1 to correct for the trailing NULL byte */
1374 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
1375 g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
1377 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr_internal (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);
1380 mono_domain_assemblies_lock (domain);
1381 domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
1382 mono_domain_assemblies_unlock (domain);
1384 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
1386 MONO_PROFILER_RAISE (assembly_loaded, (&assembly->assembly));
1388 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
1391 #endif /* !DISABLE_REFLECTION_EMIT */
1393 #ifndef DISABLE_REFLECTION_EMIT
1394 static gpointer
1395 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
1397 return CACHE_OBJECT (MonoReflectionAssembly *, assembly, &res->object, NULL);
1400 static MonoReflectionModuleBuilderHandle
1401 register_module (MonoDomain *domain, MonoReflectionModuleBuilderHandle res, MonoDynamicImage *module)
1403 return CACHE_OBJECT_HANDLE (MonoReflectionModuleBuilder, module, MONO_HANDLE_CAST (MonoObject, res), NULL);
1406 static gboolean
1407 image_module_basic_init (MonoReflectionModuleBuilderHandle moduleb, MonoError *error)
1409 error_init (error);
1410 MonoDomain *domain = MONO_HANDLE_DOMAIN (moduleb);
1411 MonoDynamicImage *image = MONO_HANDLE_GETVAL (moduleb, dynamic_image);
1412 MonoReflectionAssemblyBuilderHandle ab = MONO_HANDLE_NEW (MonoReflectionAssemblyBuilder, NULL);
1413 MONO_HANDLE_GET (ab, moduleb, assemblyb);
1414 if (!image) {
1416 * FIXME: we already created an image in mono_reflection_dynimage_basic_init (), but
1417 * we don't know which module it belongs to, since that is only
1418 * determined at assembly save time.
1420 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
1421 MonoStringHandle abname = MONO_HANDLE_NEW_GET (MonoString, ab, name);
1422 char *name = mono_string_handle_to_utf8 (abname, error);
1423 return_val_if_nok (error, FALSE);
1424 MonoStringHandle modfqname = MONO_HANDLE_NEW_GET (MonoString, MONO_HANDLE_CAST (MonoReflectionModule, moduleb), fqname);
1425 char *fqname = mono_string_handle_to_utf8 (modfqname, error);
1426 if (!is_ok (error)) {
1427 g_free (name);
1428 return FALSE;
1430 MonoDynamicAssembly *dynamic_assembly = MONO_HANDLE_GETVAL (ab, dynamic_assembly);
1431 image = mono_dynamic_image_create (dynamic_assembly, name, fqname);
1433 MONO_HANDLE_SETVAL (MONO_HANDLE_CAST (MonoReflectionModule, moduleb), image, MonoImage*, &image->image);
1434 MONO_HANDLE_SETVAL (moduleb, dynamic_image, MonoDynamicImage*, image);
1435 register_module (domain, moduleb, image);
1437 /* register the module with the assembly */
1438 MonoImage *ass = dynamic_assembly->assembly.image;
1439 int module_count = ass->module_count;
1440 MonoImage **new_modules = g_new0 (MonoImage *, module_count + 1);
1442 if (ass->modules)
1443 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
1444 new_modules [module_count] = &image->image;
1445 mono_image_addref (&image->image);
1447 g_free (ass->modules);
1448 ass->modules = new_modules;
1449 ass->module_count ++;
1451 return TRUE;
1454 static gboolean
1455 mono_image_module_basic_init (MonoReflectionModuleBuilderHandle moduleb, MonoError *error)
1457 error_init (error);
1458 return image_module_basic_init (moduleb, error);
1461 #endif
1463 static gboolean
1464 is_corlib_type (MonoClass *klass)
1466 return klass->image == mono_defaults.corlib;
1469 #define check_corlib_type_cached(_class, _namespace, _name) do { \
1470 static MonoClass *cached_class; \
1471 if (cached_class) \
1472 return cached_class == _class; \
1473 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
1474 cached_class = _class; \
1475 return TRUE; \
1477 return FALSE; \
1478 } while (0) \
1481 MonoType*
1482 mono_type_array_get_and_resolve (MonoArrayHandle array, int idx, MonoError *error)
1484 HANDLE_FUNCTION_ENTER();
1485 error_init (error);
1486 MonoReflectionTypeHandle t = MONO_HANDLE_NEW (MonoReflectionType, NULL);
1487 MONO_HANDLE_ARRAY_GETREF (t, array, idx);
1488 MonoType *result = mono_reflection_type_handle_mono_type (t, error);
1489 HANDLE_FUNCTION_RETURN_VAL (result);
1492 static MonoType *
1493 add_custom_modifiers_to_type (MonoType *without_mods, MonoArrayHandle req_array, MonoArrayHandle opt_array, MonoImage *image, MonoError *error)
1495 HANDLE_FUNCTION_ENTER();
1496 error_init (error);
1498 int num_req_mods = 0;
1499 if (!MONO_HANDLE_IS_NULL (req_array))
1500 num_req_mods = mono_array_handle_length (req_array);
1502 int num_opt_mods = 0;
1503 if (!MONO_HANDLE_IS_NULL (opt_array))
1504 num_opt_mods = mono_array_handle_length (opt_array);
1506 const int total_mods = num_req_mods + num_opt_mods;
1507 if (total_mods == 0)
1508 return without_mods;
1510 MonoTypeWithModifiers *result;
1511 result = mono_image_g_malloc0 (image, mono_sizeof_type_with_mods (total_mods, FALSE));
1512 memcpy (result, without_mods, MONO_SIZEOF_TYPE);
1513 result->unmodified.has_cmods = 1;
1514 MonoCustomModContainer *cmods = mono_type_get_cmods ((MonoType *)result);
1515 g_assert (cmods);
1516 cmods->count = total_mods;
1517 cmods->image = image;
1519 g_assert (image_is_dynamic (image));
1520 MonoDynamicImage *allocator = (MonoDynamicImage *) image;
1522 g_assert (total_mods > 0);
1523 /* store cmods in reverse order from how the API supplies them.
1524 (Assemblies store modifiers in reverse order of IL syntax - and SRE
1525 follows the same order as IL syntax). */
1526 int modifier_index = total_mods - 1;
1528 MonoObjectHandle mod_handle = MONO_HANDLE_NEW (MonoObject, NULL);
1529 for (int i=0; i < num_req_mods; i++) {
1530 cmods->modifiers [modifier_index].required = TRUE;
1531 MONO_HANDLE_ARRAY_GETREF (mod_handle, req_array, i);
1532 cmods->modifiers [modifier_index].token = mono_image_create_token (allocator, mod_handle, FALSE, TRUE, error);
1533 modifier_index--;
1536 for (int i=0; i < num_opt_mods; i++) {
1537 cmods->modifiers [modifier_index].required = FALSE;
1538 MONO_HANDLE_ARRAY_GETREF (mod_handle, opt_array, i);
1539 cmods->modifiers [modifier_index].token = mono_image_create_token (allocator, mod_handle, FALSE, TRUE, error);
1540 modifier_index--;
1543 g_assert (modifier_index == -1);
1545 HANDLE_FUNCTION_RETURN_VAL ((MonoType *) result);
1548 static
1549 MonoType *
1550 mono_type_array_get_and_resolve_with_modifiers (MonoArrayHandle types, MonoArrayHandle required_modifiers, MonoArrayHandle optional_modifiers, int idx, MonoImage *image, MonoError *error)
1552 HANDLE_FUNCTION_ENTER();
1553 error_init (error);
1554 MonoReflectionTypeHandle type = MONO_HANDLE_NEW (MonoReflectionType, NULL);
1555 MonoArrayHandle req_mods_handle = MONO_HANDLE_NEW (MonoArray, NULL);
1556 MonoArrayHandle opt_mods_handle = MONO_HANDLE_NEW (MonoArray, NULL);
1558 if (!MONO_HANDLE_IS_NULL (required_modifiers))
1559 MONO_HANDLE_ARRAY_GETREF (req_mods_handle, required_modifiers, idx);
1561 if (!MONO_HANDLE_IS_NULL (optional_modifiers))
1562 MONO_HANDLE_ARRAY_GETREF (opt_mods_handle, optional_modifiers, idx);
1564 MONO_HANDLE_ARRAY_GETREF (type, types, idx);
1566 MonoType *result = mono_reflection_type_handle_mono_type (type, error);
1567 result = (MonoType *) add_custom_modifiers_to_type (result, req_mods_handle, opt_mods_handle, image, error);
1569 HANDLE_FUNCTION_RETURN_VAL (result);
1573 #ifndef DISABLE_REFLECTION_EMIT
1574 static gboolean
1575 is_sre_array (MonoClass *klass)
1577 check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
1580 static gboolean
1581 is_sre_byref (MonoClass *klass)
1583 check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
1586 static gboolean
1587 is_sre_pointer (MonoClass *klass)
1589 check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
1592 static gboolean
1593 is_sre_generic_instance (MonoClass *klass)
1595 check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilderInstantiation");
1598 static gboolean
1599 is_sre_type_builder (MonoClass *klass)
1601 check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
1604 static gboolean
1605 is_sre_method_builder (MonoClass *klass)
1607 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
1610 gboolean
1611 mono_is_sre_ctor_builder (MonoClass *klass)
1613 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
1616 static gboolean
1617 is_sre_field_builder (MonoClass *klass)
1619 check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
1622 static gboolean
1623 is_sre_gparam_builder (MonoClass *klass)
1625 check_corlib_type_cached (klass, "System.Reflection.Emit", "GenericTypeParameterBuilder");
1628 static gboolean
1629 is_sre_enum_builder (MonoClass *klass)
1631 check_corlib_type_cached (klass, "System.Reflection.Emit", "EnumBuilder");
1634 gboolean
1635 mono_is_sre_method_on_tb_inst (MonoClass *klass)
1637 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
1640 gboolean
1641 mono_is_sre_ctor_on_tb_inst (MonoClass *klass)
1643 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
1646 static MonoReflectionTypeHandle
1647 mono_reflection_type_get_underlying_system_type (MonoReflectionTypeHandle t, MonoError *error)
1649 static MonoMethod *method_get_underlying_system_type = NULL;
1650 HANDLE_FUNCTION_ENTER ();
1652 error_init (error);
1654 if (!method_get_underlying_system_type) {
1655 method_get_underlying_system_type = mono_class_get_method_from_name_checked (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0, 0, error);
1656 mono_error_assert_ok (error);
1659 MonoReflectionTypeHandle rt = MONO_HANDLE_NEW (MonoReflectionType, NULL);
1661 MonoMethod *usertype_method = mono_object_handle_get_virtual_method (MONO_HANDLE_CAST (MonoObject, t), method_get_underlying_system_type, error);
1662 goto_if_nok (error, leave);
1664 MONO_HANDLE_ASSIGN (rt, MONO_HANDLE_CAST (MonoReflectionType, MONO_HANDLE_NEW (MonoObject, mono_runtime_invoke_checked (usertype_method, MONO_HANDLE_RAW (t), NULL, error))));
1666 leave:
1667 HANDLE_FUNCTION_RETURN_REF (MonoReflectionType, rt);
1670 MonoType*
1671 mono_reflection_type_get_handle (MonoReflectionType* ref_raw, MonoError *error)
1673 HANDLE_FUNCTION_ENTER ();
1674 error_init (error);
1675 MONO_HANDLE_DCL (MonoReflectionType, ref);
1676 MonoType *result = mono_reflection_type_handle_mono_type (ref, error);
1677 HANDLE_FUNCTION_RETURN_VAL (result);
1680 static MonoType*
1681 reflection_instance_handle_mono_type (MonoReflectionGenericClassHandle ref_gclass, MonoError *error)
1683 HANDLE_FUNCTION_ENTER ();
1684 MonoType *result = NULL;
1685 MonoType **types = NULL;
1687 MonoArrayHandle typeargs = MONO_HANDLE_NEW_GET (MonoArray, ref_gclass, type_arguments);
1688 int count = mono_array_handle_length (typeargs);
1689 types = g_new0 (MonoType*, count);
1690 MonoReflectionTypeHandle t = MONO_HANDLE_NEW (MonoReflectionType, NULL);
1691 for (int i = 0; i < count; ++i) {
1692 MONO_HANDLE_ARRAY_GETREF (t, typeargs, i);
1693 types [i] = mono_reflection_type_handle_mono_type (t, error);
1694 if (!types[i] || !is_ok (error)) {
1695 goto leave;
1698 /* Need to resolve the generic_type in order for it to create its generic context. */
1699 MonoReflectionTypeHandle ref_gtd;
1700 ref_gtd = MONO_HANDLE_NEW_GET (MonoReflectionType, ref_gclass, generic_type);
1701 MonoType *gtd;
1702 gtd = mono_reflection_type_handle_mono_type (ref_gtd, error);
1703 goto_if_nok (error, leave);
1704 MonoClass *gtd_klass;
1705 gtd_klass = mono_class_from_mono_type_internal (gtd);
1706 if (is_sre_type_builder (mono_handle_class (ref_gtd))) {
1707 reflection_setup_internal_class (MONO_HANDLE_CAST (MonoReflectionTypeBuilder, ref_gtd), error);
1708 goto_if_nok (error, leave);
1710 g_assert (count == 0 || mono_class_is_gtd (gtd_klass));
1711 result = mono_reflection_bind_generic_parameters (ref_gtd, count, types, error);
1712 goto_if_nok (error, leave);
1713 g_assert (result);
1714 MONO_HANDLE_SETVAL (MONO_HANDLE_CAST (MonoReflectionType, ref_gclass), type, MonoType*, result);
1715 leave:
1716 g_free (types);
1717 HANDLE_FUNCTION_RETURN_VAL (result);
1720 static MonoType*
1721 reflection_param_handle_mono_type (MonoReflectionGenericParamHandle ref_gparam, MonoError *error)
1723 HANDLE_FUNCTION_ENTER ();
1724 error_init (error);
1725 MonoType *result = NULL;
1728 MonoReflectionTypeBuilderHandle ref_tbuilder = MONO_HANDLE_NEW_GET (MonoReflectionTypeBuilder, ref_gparam, tbuilder);
1729 MonoReflectionModuleBuilderHandle ref_module = MONO_HANDLE_NEW_GET (MonoReflectionModuleBuilder, ref_tbuilder, module);
1730 MonoDynamicImage *dynamic_image = MONO_HANDLE_GETVAL (ref_module, dynamic_image);
1731 MonoImage *image = &dynamic_image->image;
1733 MonoGenericParamFull *param = mono_image_new0 (image, MonoGenericParamFull, 1);
1735 MonoStringHandle ref_name = MONO_HANDLE_NEW_GET (MonoString, ref_gparam, name);
1736 param->info.name = mono_string_to_utf8_image (image, ref_name, error);
1737 mono_error_assert_ok (error);
1738 param->num = MONO_HANDLE_GETVAL (ref_gparam, index);
1740 MonoReflectionMethodBuilderHandle ref_mbuilder = MONO_HANDLE_NEW_GET (MonoReflectionMethodBuilder, ref_gparam, mbuilder);
1741 if (!MONO_HANDLE_IS_NULL (ref_mbuilder)) {
1742 MonoGenericContainer *generic_container = MONO_HANDLE_GETVAL (ref_mbuilder, generic_container);
1743 if (!generic_container) {
1744 generic_container = (MonoGenericContainer *)mono_image_alloc0 (image, sizeof (MonoGenericContainer));
1745 generic_container->is_method = TRUE;
1747 * Cannot set owner.method, since the MonoMethod is not created yet.
1748 * Set the image field instead, so type_in_image () works.
1750 generic_container->is_anonymous = TRUE;
1751 generic_container->owner.image = image;
1752 MONO_HANDLE_SETVAL (ref_mbuilder, generic_container, MonoGenericContainer*, generic_container);
1754 param->owner = generic_container;
1755 } else {
1756 MonoType *type = mono_reflection_type_handle_mono_type (MONO_HANDLE_CAST (MonoReflectionType, ref_tbuilder), error);
1757 goto_if_nok (error, leave);
1758 MonoClass *owner;
1759 owner = mono_class_from_mono_type_internal (type);
1760 g_assert (mono_class_is_gtd (owner));
1761 param->owner = mono_class_get_generic_container (owner);
1764 MonoClass *pklass;
1765 pklass = mono_class_create_generic_parameter ((MonoGenericParam *) param);
1767 result = m_class_get_byval_arg (pklass);
1769 mono_class_set_ref_info (pklass, MONO_HANDLE_CAST (MonoObject, ref_gparam));
1770 mono_image_append_class_to_reflection_info_set (pklass);
1772 MONO_HANDLE_SETVAL (MONO_HANDLE_CAST (MonoReflectionType, ref_gparam), type, MonoType*, result);
1774 leave:
1775 HANDLE_FUNCTION_RETURN_VAL (result);
1778 static MonoType*
1779 mono_type_array_get_and_resolve_raw (MonoArray* array_raw, int idx, MonoError *error)
1781 HANDLE_FUNCTION_ENTER(); /* FIXME callers of mono_type_array_get_and_resolve_raw should use handles */
1782 error_init (error);
1783 MONO_HANDLE_DCL (MonoArray, array);
1784 MonoType *result = mono_type_array_get_and_resolve (array, idx, error);
1785 HANDLE_FUNCTION_RETURN_VAL (result);
1788 MonoType*
1789 mono_reflection_type_handle_mono_type (MonoReflectionTypeHandle ref, MonoError *error)
1791 HANDLE_FUNCTION_ENTER ();
1792 error_init (error);
1794 MonoType* result = NULL;
1796 g_assert (!MONO_HANDLE_IS_NULL (ref));
1797 if (MONO_HANDLE_IS_NULL (ref))
1798 goto leave;
1799 MonoType *t;
1800 t = MONO_HANDLE_GETVAL (ref, type);
1801 if (t) {
1802 result = t;
1803 goto leave;
1806 if (mono_reflection_is_usertype (ref)) {
1807 MONO_HANDLE_ASSIGN (ref, mono_reflection_type_get_underlying_system_type (ref, error));
1808 if (!is_ok (error) || MONO_HANDLE_IS_NULL (ref) || mono_reflection_is_usertype (ref))
1809 goto leave;
1810 t = MONO_HANDLE_GETVAL (ref, type);
1811 if (t) {
1812 result = t;
1813 goto leave;
1817 MonoClass *klass;
1818 klass = mono_handle_class (ref);
1820 if (is_sre_array (klass)) {
1821 MonoReflectionArrayTypeHandle sre_array = MONO_HANDLE_CAST (MonoReflectionArrayType, ref);
1822 MonoReflectionTypeHandle ref_element = MONO_HANDLE_NEW_GET (MonoReflectionType, sre_array, element_type);
1823 MonoType *base = mono_reflection_type_handle_mono_type (ref_element, error);
1824 goto_if_nok (error, leave);
1825 g_assert (base);
1826 gint32 rank = MONO_HANDLE_GETVAL (sre_array, rank);
1827 MonoClass *eclass = mono_class_from_mono_type_internal (base);
1828 result = mono_image_new0 (eclass->image, MonoType, 1);
1829 if (rank == 0) {
1830 result->type = MONO_TYPE_SZARRAY;
1831 result->data.klass = eclass;
1832 } else {
1833 MonoArrayType *at = (MonoArrayType *)mono_image_alloc0 (eclass->image, sizeof (MonoArrayType));
1834 result->type = MONO_TYPE_ARRAY;
1835 result->data.array = at;
1836 at->eklass = eclass;
1837 at->rank = rank;
1839 MONO_HANDLE_SETVAL (ref, type, MonoType*, result);
1840 } else if (is_sre_byref (klass)) {
1841 MonoReflectionDerivedTypeHandle sre_byref = MONO_HANDLE_CAST (MonoReflectionDerivedType, ref);
1842 MonoReflectionTypeHandle ref_element = MONO_HANDLE_NEW_GET (MonoReflectionType, sre_byref, element_type);
1843 MonoType *base = mono_reflection_type_handle_mono_type (ref_element, error);
1844 goto_if_nok (error, leave);
1845 g_assert (base);
1846 result = &mono_class_from_mono_type_internal (base)->this_arg;
1847 MONO_HANDLE_SETVAL (ref, type, MonoType*, result);
1848 } else if (is_sre_pointer (klass)) {
1849 MonoReflectionDerivedTypeHandle sre_pointer = MONO_HANDLE_CAST (MonoReflectionDerivedType, ref);
1850 MonoReflectionTypeHandle ref_element = MONO_HANDLE_NEW_GET (MonoReflectionType, sre_pointer, element_type);
1851 MonoType *base = mono_reflection_type_handle_mono_type (ref_element, error);
1852 goto_if_nok (error, leave);
1853 g_assert (base);
1854 result = m_class_get_byval_arg (mono_class_create_ptr (base));
1855 MONO_HANDLE_SETVAL (ref, type, MonoType*, result);
1856 } else if (is_sre_generic_instance (klass)) {
1857 result = reflection_instance_handle_mono_type (MONO_HANDLE_CAST (MonoReflectionGenericClass, ref), error);
1858 } else if (is_sre_gparam_builder (klass)) {
1859 result = reflection_param_handle_mono_type (MONO_HANDLE_CAST (MonoReflectionGenericParam, ref), error);
1860 } else if (is_sre_enum_builder (klass)) {
1861 MonoReflectionEnumBuilderHandle ref_ebuilder = MONO_HANDLE_CAST (MonoReflectionEnumBuilder, ref);
1863 MonoReflectionTypeHandle ref_tb = MONO_HANDLE_CAST (MonoReflectionType, MONO_HANDLE_NEW_GET (MonoReflectionTypeBuilder, ref_ebuilder, tb));
1864 result = mono_reflection_type_handle_mono_type (ref_tb, error);
1865 } else if (is_sre_type_builder (klass)) {
1866 MonoReflectionTypeBuilderHandle ref_tb = MONO_HANDLE_CAST (MonoReflectionTypeBuilder, ref);
1868 /* This happens when a finished type references an unfinished one. Have to create the minimal type */
1869 reflection_setup_internal_class (ref_tb, error);
1870 mono_error_assert_ok (error);
1871 result = MONO_HANDLE_GETVAL (ref, type);
1872 } else {
1873 g_error ("Cannot handle corlib user type %s", mono_type_full_name (m_class_get_byval_arg (mono_handle_class (ref))));
1875 leave:
1876 HANDLE_FUNCTION_RETURN_VAL (result);
1880 * LOCKING: Assumes the loader lock is held.
1882 static MonoMethodSignature*
1883 parameters_to_signature (MonoImage *image, MonoArrayHandle parameters, MonoArrayHandle required_modifiers, MonoArrayHandle optional_modifiers, MonoError *error) {
1884 MonoMethodSignature *sig;
1885 int count, i;
1887 error_init (error);
1889 count = MONO_HANDLE_IS_NULL (parameters) ? 0 : mono_array_handle_length (parameters);
1891 sig = (MonoMethodSignature *)mono_image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
1892 sig->param_count = count;
1893 sig->sentinelpos = -1; /* FIXME */
1894 for (i = 0; i < count; ++i) {
1895 sig->params [i] = mono_type_array_get_and_resolve_with_modifiers (parameters, required_modifiers, optional_modifiers, i, image, error);
1896 if (!is_ok (error)) {
1897 image_g_free (image, sig);
1898 return NULL;
1901 return sig;
1905 * LOCKING: Assumes the loader lock is held.
1907 static MonoMethodSignature*
1908 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilderHandle ctor, MonoError *error) {
1909 MonoMethodSignature *sig;
1911 error_init (error);
1912 MonoArrayHandle params = MONO_HANDLE_NEW_GET(MonoArray, ctor, parameters);
1913 MonoArrayHandle required_modifiers = MONO_HANDLE_NEW_GET(MonoArray, ctor, param_modreq);
1914 MonoArrayHandle optional_modifiers = MONO_HANDLE_NEW_GET(MonoArray, ctor, param_modopt);
1916 sig = parameters_to_signature (image, params, required_modifiers, optional_modifiers, error);
1917 return_val_if_nok (error, NULL);
1918 sig->hasthis = MONO_HANDLE_GETVAL (ctor, attrs) & METHOD_ATTRIBUTE_STATIC? 0: 1;
1919 sig->ret = mono_get_void_type ();
1920 return sig;
1923 static MonoMethodSignature*
1924 ctor_builder_to_signature_raw (MonoImage *image, MonoReflectionCtorBuilder* ctor_raw, MonoError *error) {
1925 HANDLE_FUNCTION_ENTER();
1926 MONO_HANDLE_DCL (MonoReflectionCtorBuilder, ctor);
1927 MonoMethodSignature *sig = ctor_builder_to_signature (image, ctor, error);
1928 HANDLE_FUNCTION_RETURN_VAL (sig);
1931 * LOCKING: Assumes the loader lock is held.
1933 static MonoMethodSignature*
1934 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilderHandle method, MonoError *error)
1936 MonoMethodSignature *sig;
1938 error_init (error);
1939 MonoArrayHandle params = MONO_HANDLE_NEW_GET(MonoArray, method, parameters);
1940 MonoArrayHandle required_modifiers = MONO_HANDLE_NEW_GET(MonoArray, method, param_modreq);
1941 MonoArrayHandle optional_modifiers = MONO_HANDLE_NEW_GET(MonoArray, method, param_modopt);
1942 MonoArrayHandle ret_req_modifiers = MONO_HANDLE_NEW_GET (MonoArray, method, return_modreq);
1943 MonoArrayHandle ret_opt_modifiers = MONO_HANDLE_NEW_GET (MonoArray, method, return_modopt);
1945 sig = parameters_to_signature (image, params, required_modifiers, optional_modifiers, error);
1946 return_val_if_nok (error, NULL);
1947 sig->hasthis = MONO_HANDLE_GETVAL (method, attrs) & METHOD_ATTRIBUTE_STATIC? 0: 1;
1948 MonoReflectionTypeHandle rtype;
1949 rtype = MONO_HANDLE_CAST (MonoReflectionType, MONO_HANDLE_NEW_GET (MonoObject, method, rtype));
1950 if (!MONO_HANDLE_IS_NULL (rtype)) {
1951 sig->ret = mono_reflection_type_handle_mono_type (rtype, error);
1952 sig->ret = add_custom_modifiers_to_type (sig->ret, ret_req_modifiers, ret_opt_modifiers, image, error);
1953 if (!is_ok (error)) {
1954 image_g_free (image, sig);
1955 return NULL;
1957 } else {
1958 sig->ret = mono_get_void_type ();
1960 MonoArrayHandle generic_params = MONO_HANDLE_NEW_GET (MonoArray, method, generic_params);
1961 sig->generic_param_count = MONO_HANDLE_IS_NULL (generic_params) ? 0 : mono_array_handle_length (generic_params);
1962 return sig;
1965 static MonoMethodSignature*
1966 dynamic_method_to_signature (MonoReflectionDynamicMethodHandle method, MonoError *error)
1968 HANDLE_FUNCTION_ENTER ();
1969 MonoMethodSignature *sig = NULL;
1971 error_init (error);
1973 sig = parameters_to_signature (NULL, MONO_HANDLE_NEW_GET (MonoArray, method, parameters),
1974 MONO_HANDLE_CAST (MonoArray, NULL_HANDLE), MONO_HANDLE_CAST (MonoArray, NULL_HANDLE), error);
1975 goto_if_nok (error, leave);
1976 sig->hasthis = MONO_HANDLE_GETVAL (method, attrs) & METHOD_ATTRIBUTE_STATIC? 0: 1;
1977 MonoReflectionTypeHandle rtype;
1978 rtype = MONO_HANDLE_NEW_GET (MonoReflectionType, method, rtype);
1979 if (!MONO_HANDLE_IS_NULL (rtype)) {
1980 sig->ret = mono_reflection_type_handle_mono_type (rtype, error);
1981 if (!is_ok (error)) {
1982 g_free (sig);
1983 sig = NULL;
1984 goto leave;
1986 } else {
1987 sig->ret = mono_get_void_type ();
1989 sig->generic_param_count = 0;
1990 leave:
1991 HANDLE_FUNCTION_RETURN_VAL (sig);
1994 static void
1995 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type, MonoError *error)
1997 error_init (error);
1998 MonoClass *klass = mono_object_class (prop);
1999 if (strcmp (klass->name, "PropertyBuilder") == 0) {
2000 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
2001 *name = mono_string_to_utf8_checked_internal (pb->name, error);
2002 return_if_nok (error);
2003 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type, error);
2004 } else {
2005 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
2006 *name = g_strdup (p->property->name);
2007 if (p->property->get)
2008 *type = mono_method_signature_internal (p->property->get)->ret;
2009 else
2010 *type = mono_method_signature_internal (p->property->set)->params [mono_method_signature_internal (p->property->set)->param_count - 1];
2014 static void
2015 get_field_name_and_type (MonoObject *field, char **name, MonoType **type, MonoError *error)
2017 error_init (error);
2018 MonoClass *klass = mono_object_class (field);
2019 if (strcmp (klass->name, "FieldBuilder") == 0) {
2020 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
2021 *name = mono_string_to_utf8_checked_internal (fb->name, error);
2022 return_if_nok (error);
2023 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
2024 } else {
2025 MonoReflectionField *f = (MonoReflectionField *)field;
2026 *name = g_strdup (mono_field_get_name (f->field));
2027 *type = f->field->type;
2031 #else /* DISABLE_REFLECTION_EMIT */
2033 static gboolean
2034 is_sre_type_builder (MonoClass *klass)
2036 return FALSE;
2039 static gboolean
2040 is_sre_generic_instance (MonoClass *klass)
2042 return FALSE;
2045 gboolean
2046 mono_is_sre_ctor_builder (MonoClass *klass)
2048 return FALSE;
2051 gboolean
2052 mono_is_sre_method_on_tb_inst (MonoClass *klass)
2054 return FALSE;
2057 gboolean
2058 mono_is_sre_ctor_on_tb_inst (MonoClass *klass)
2060 return FALSE;
2063 #endif /* !DISABLE_REFLECTION_EMIT */
2066 static gboolean
2067 is_sr_mono_field (MonoClass *klass)
2069 check_corlib_type_cached (klass, "System.Reflection", "RuntimeFieldInfo");
2072 gboolean
2073 mono_is_sr_mono_property (MonoClass *klass)
2075 check_corlib_type_cached (klass, "System.Reflection", "RuntimePropertyInfo");
2078 static gboolean
2079 is_sr_mono_method (MonoClass *klass)
2081 check_corlib_type_cached (klass, "System.Reflection", "RuntimeMethodInfo");
2084 gboolean
2085 mono_is_sr_mono_cmethod (MonoClass *klass)
2087 check_corlib_type_cached (klass, "System.Reflection", "RuntimeConstructorInfo");
2090 gboolean
2091 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
2093 return is_sr_mono_method (klass) || mono_is_sr_mono_cmethod (klass);
2096 gboolean
2097 mono_is_sre_type_builder (MonoClass *klass)
2099 return is_sre_type_builder (klass);
2102 gboolean
2103 mono_is_sre_generic_instance (MonoClass *klass)
2105 return is_sre_generic_instance (klass);
2111 * encode_cattr_value:
2112 * Encode a value in a custom attribute stream of bytes.
2113 * The value to encode is either supplied as an object in argument val
2114 * (valuetypes are boxed), or as a pointer to the data in the
2115 * argument argval.
2116 * @type represents the type of the value
2117 * @buffer is the start of the buffer
2118 * @p the current position in the buffer
2119 * @buflen contains the size of the buffer and is used to return the new buffer size
2120 * if this needs to be realloced.
2121 * @retbuffer and @retp return the start and the position of the buffer
2122 * @error set on error.
2124 static void
2125 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, gconstpointer void_argval, MonoError *error)
2127 const char *argval = (const char*)void_argval;
2128 MonoTypeEnum simple_type;
2130 error_init (error);
2131 if ((p-buffer) + 10 >= *buflen) {
2132 char *newbuf;
2133 *buflen *= 2;
2134 newbuf = (char *)g_realloc (buffer, *buflen);
2135 p = newbuf + (p-buffer);
2136 buffer = newbuf;
2138 if (!argval)
2139 argval = (const char*)mono_object_get_data (arg);
2140 simple_type = type->type;
2141 handle_enum:
2142 switch (simple_type) {
2143 case MONO_TYPE_BOOLEAN:
2144 case MONO_TYPE_U1:
2145 case MONO_TYPE_I1:
2146 *p++ = *argval;
2147 break;
2148 case MONO_TYPE_CHAR:
2149 case MONO_TYPE_U2:
2150 case MONO_TYPE_I2:
2151 swap_with_size (p, argval, 2, 1);
2152 p += 2;
2153 break;
2154 case MONO_TYPE_U4:
2155 case MONO_TYPE_I4:
2156 case MONO_TYPE_R4:
2157 swap_with_size (p, argval, 4, 1);
2158 p += 4;
2159 break;
2160 case MONO_TYPE_R8:
2161 swap_with_size (p, argval, 8, 1);
2162 p += 8;
2163 break;
2164 case MONO_TYPE_U8:
2165 case MONO_TYPE_I8:
2166 swap_with_size (p, argval, 8, 1);
2167 p += 8;
2168 break;
2169 case MONO_TYPE_VALUETYPE:
2170 if (type->data.klass->enumtype) {
2171 simple_type = mono_class_enum_basetype_internal (type->data.klass)->type;
2172 goto handle_enum;
2173 } else {
2174 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
2176 break;
2177 case MONO_TYPE_STRING: {
2178 char *str;
2179 guint32 slen;
2180 if (!arg) {
2181 *p++ = 0xFF;
2182 break;
2184 str = mono_string_to_utf8_checked_internal ((MonoString*)arg, error);
2185 return_if_nok (error);
2186 slen = strlen (str);
2187 if ((p-buffer) + 10 + slen >= *buflen) {
2188 char *newbuf;
2189 *buflen *= 2;
2190 *buflen += slen;
2191 newbuf = (char *)g_realloc (buffer, *buflen);
2192 p = newbuf + (p-buffer);
2193 buffer = newbuf;
2195 mono_metadata_encode_value (slen, p, &p);
2196 memcpy (p, str, slen);
2197 p += slen;
2198 g_free (str);
2199 break;
2201 case MONO_TYPE_CLASS: {
2202 char *str;
2203 guint32 slen;
2204 MonoType *arg_type;
2205 if (!arg) {
2206 *p++ = 0xFF;
2207 break;
2209 handle_type:
2210 arg_type = mono_reflection_type_get_handle ((MonoReflectionType*)arg, error);
2211 return_if_nok (error);
2213 str = type_get_qualified_name (arg_type, NULL);
2214 slen = strlen (str);
2215 if ((p-buffer) + 10 + slen >= *buflen) {
2216 char *newbuf;
2217 *buflen *= 2;
2218 *buflen += slen;
2219 newbuf = (char *)g_realloc (buffer, *buflen);
2220 p = newbuf + (p-buffer);
2221 buffer = newbuf;
2223 mono_metadata_encode_value (slen, p, &p);
2224 memcpy (p, str, slen);
2225 p += slen;
2226 g_free (str);
2227 break;
2229 case MONO_TYPE_SZARRAY: {
2230 int len, i;
2231 MonoClass *eclass, *arg_eclass;
2233 if (!arg) {
2234 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
2235 break;
2237 len = mono_array_length_internal ((MonoArray*)arg);
2238 *p++ = len & 0xff;
2239 *p++ = (len >> 8) & 0xff;
2240 *p++ = (len >> 16) & 0xff;
2241 *p++ = (len >> 24) & 0xff;
2242 *retp = p;
2243 *retbuffer = buffer;
2244 eclass = type->data.klass;
2245 arg_eclass = mono_object_class (arg)->element_class;
2247 if (!eclass) {
2248 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
2249 eclass = mono_defaults.object_class;
2251 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
2252 char *elptr = mono_array_addr_internal ((MonoArray*)arg, char, 0);
2253 int elsize = mono_class_array_element_size (arg_eclass);
2254 for (i = 0; i < len; ++i) {
2255 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, m_class_get_byval_arg (arg_eclass), NULL, elptr, error);
2256 return_if_nok (error);
2257 elptr += elsize;
2259 } else if (eclass->valuetype && arg_eclass->valuetype) {
2260 char *elptr = mono_array_addr_internal ((MonoArray*)arg, char, 0);
2261 int elsize = mono_class_array_element_size (eclass);
2262 for (i = 0; i < len; ++i) {
2263 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, m_class_get_byval_arg (eclass), NULL, elptr, error);
2264 return_if_nok (error);
2265 elptr += elsize;
2267 } else {
2268 for (i = 0; i < len; ++i) {
2269 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, m_class_get_byval_arg (eclass), mono_array_get_internal ((MonoArray*)arg, MonoObject*, i), NULL, error);
2270 return_if_nok (error);
2273 break;
2275 case MONO_TYPE_OBJECT: {
2276 MonoClass *klass;
2277 char *str;
2278 guint32 slen;
2281 * The parameter type is 'object' but the type of the actual
2282 * argument is not. So we have to add type information to the blob
2283 * too. This is completely undocumented in the spec.
2286 if (arg == NULL) {
2287 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
2288 *p++ = 0xFF;
2289 break;
2292 klass = mono_object_class (arg);
2294 if (mono_object_isinst_checked (arg, mono_defaults.systemtype_class, error)) {
2295 *p++ = 0x50;
2296 goto handle_type;
2297 } else {
2298 return_if_nok (error);
2301 MonoType *klass_byval_arg = m_class_get_byval_arg (klass);
2302 if (klass->enumtype) {
2303 *p++ = 0x55;
2304 } else if (klass == mono_defaults.string_class) {
2305 simple_type = MONO_TYPE_STRING;
2306 *p++ = 0x0E;
2307 goto handle_enum;
2308 } else if (klass->rank == 1) {
2309 *p++ = 0x1D;
2310 if (m_class_get_byval_arg (m_class_get_element_class (klass))->type == MONO_TYPE_OBJECT)
2311 /* See Partition II, Appendix B3 */
2312 *p++ = 0x51;
2313 else
2314 *p++ = m_class_get_byval_arg (m_class_get_element_class (klass))->type;
2315 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, klass_byval_arg, arg, NULL, error);
2316 return_if_nok (error);
2317 break;
2318 } else if (klass_byval_arg->type >= MONO_TYPE_BOOLEAN && klass_byval_arg->type <= MONO_TYPE_R8) {
2319 *p++ = simple_type = klass_byval_arg->type;
2320 goto handle_enum;
2321 } else {
2322 mono_error_set_not_supported (error, "unhandled type in custom attr");
2323 break;
2325 str = type_get_qualified_name (m_class_get_byval_arg (klass), NULL);
2326 slen = strlen (str);
2327 if ((p-buffer) + 10 + slen >= *buflen) {
2328 char *newbuf;
2329 *buflen *= 2;
2330 *buflen += slen;
2331 newbuf = (char *)g_realloc (buffer, *buflen);
2332 p = newbuf + (p-buffer);
2333 buffer = newbuf;
2335 mono_metadata_encode_value (slen, p, &p);
2336 memcpy (p, str, slen);
2337 p += slen;
2338 g_free (str);
2339 simple_type = mono_class_enum_basetype_internal (klass)->type;
2340 goto handle_enum;
2342 default:
2343 mono_error_set_not_supported (error, "type 0x%02x not yet supported in custom attr encoder", simple_type);
2345 *retp = p;
2346 *retbuffer = buffer;
2349 static void
2350 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
2352 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
2353 char *str = type_get_qualified_name (type, NULL);
2354 int slen = strlen (str);
2356 *p++ = 0x55;
2358 * This seems to be optional...
2359 * *p++ = 0x80;
2361 mono_metadata_encode_value (slen, p, &p);
2362 memcpy (p, str, slen);
2363 p += slen;
2364 g_free (str);
2365 } else if (type->type == MONO_TYPE_OBJECT) {
2366 *p++ = 0x51;
2367 } else if (type->type == MONO_TYPE_CLASS) {
2368 /* it should be a type: encode_cattr_value () has the check */
2369 *p++ = 0x50;
2370 } else {
2371 mono_metadata_encode_value (type->type, p, &p);
2372 if (type->type == MONO_TYPE_SZARRAY)
2373 /* See the examples in Partition VI, Annex B */
2374 encode_field_or_prop_type (m_class_get_byval_arg (type->data.klass), p, &p);
2377 *retp = p;
2380 #ifndef DISABLE_REFLECTION_EMIT
2381 static void
2382 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value, MonoError *error)
2384 int len;
2386 error_init (error);
2388 /* Preallocate a large enough buffer */
2389 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
2390 char *str = type_get_qualified_name (type, NULL);
2391 len = strlen (str);
2392 g_free (str);
2393 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
2394 char *str = type_get_qualified_name (m_class_get_byval_arg (type->data.klass), NULL);
2395 len = strlen (str);
2396 g_free (str);
2397 } else {
2398 len = 0;
2400 len += strlen (name);
2402 if ((p-buffer) + 20 + len >= *buflen) {
2403 char *newbuf;
2404 *buflen *= 2;
2405 *buflen += len;
2406 newbuf = (char *)g_realloc (buffer, *buflen);
2407 p = newbuf + (p-buffer);
2408 buffer = newbuf;
2411 encode_field_or_prop_type (type, p, &p);
2413 len = strlen (name);
2414 mono_metadata_encode_value (len, p, &p);
2415 memcpy (p, name, len);
2416 p += len;
2417 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL, error);
2418 return_if_nok (error);
2419 *retp = p;
2420 *retbuffer = buffer;
2424 * mono_reflection_get_custom_attrs_blob:
2425 * \param ctor custom attribute constructor
2426 * \param ctorArgs arguments o the constructor
2427 * \param properties
2428 * \param propValues
2429 * \param fields
2430 * \param fieldValues
2431 * Creates the blob of data that needs to be saved in the metadata and that represents
2432 * the custom attributed described by \p ctor, \p ctorArgs etc.
2433 * \returns a \c Byte array representing the blob of data.
2435 MonoArray*
2436 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
2438 ERROR_DECL (error);
2439 MonoArray *result = mono_reflection_get_custom_attrs_blob_checked (assembly, ctor, ctorArgs, properties, propValues, fields, fieldValues, error);
2440 mono_error_cleanup (error);
2441 return result;
2445 * mono_reflection_get_custom_attrs_blob_checked:
2446 * \param ctor custom attribute constructor
2447 * \param ctorArgs arguments o the constructor
2448 * \param properties
2449 * \param propValues
2450 * \param fields
2451 * \param fieldValues
2452 * \param error set on error
2453 * Creates the blob of data that needs to be saved in the metadata and that represents
2454 * the custom attributed described by \p ctor, \p ctorArgs etc.
2455 * \returns a \c Byte array representing the blob of data. On failure returns NULL and sets \p error.
2457 MonoArray*
2458 mono_reflection_get_custom_attrs_blob_checked (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues, MonoError *error)
2460 MonoArray *result = NULL;
2461 MonoMethodSignature *sig;
2462 MonoObject *arg;
2463 char *buffer, *p;
2464 guint32 buflen, i;
2466 error_init (error);
2468 if (strcmp (ctor->vtable->klass->name, "RuntimeConstructorInfo")) {
2469 /* sig is freed later so allocate it in the heap */
2470 sig = ctor_builder_to_signature_raw (NULL, (MonoReflectionCtorBuilder*)ctor, error); /* FIXME use handles */
2471 if (!is_ok (error)) {
2472 g_free (sig);
2473 return NULL;
2475 } else {
2476 sig = mono_method_signature_internal (((MonoReflectionMethod*)ctor)->method);
2479 g_assert (mono_array_length_internal (ctorArgs) == sig->param_count);
2480 buflen = 256;
2481 p = buffer = (char *)g_malloc (buflen);
2482 /* write the prolog */
2483 *p++ = 1;
2484 *p++ = 0;
2485 for (i = 0; i < sig->param_count; ++i) {
2486 arg = mono_array_get_internal (ctorArgs, MonoObject*, i);
2487 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL, error);
2488 goto_if_nok (error, leave);
2490 i = 0;
2491 if (properties)
2492 i += mono_array_length_internal (properties);
2493 if (fields)
2494 i += mono_array_length_internal (fields);
2495 *p++ = i & 0xff;
2496 *p++ = (i >> 8) & 0xff;
2497 if (properties) {
2498 MonoObject *prop;
2499 for (i = 0; i < mono_array_length_internal (properties); ++i) {
2500 MonoType *ptype;
2501 char *pname;
2503 prop = (MonoObject *)mono_array_get_internal (properties, gpointer, i);
2504 get_prop_name_and_type (prop, &pname, &ptype, error);
2505 goto_if_nok (error, leave);
2506 *p++ = 0x54; /* PROPERTY signature */
2507 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get_internal (propValues, gpointer, i), error);
2508 g_free (pname);
2509 goto_if_nok (error, leave);
2513 if (fields) {
2514 MonoObject *field;
2515 for (i = 0; i < mono_array_length_internal (fields); ++i) {
2516 MonoType *ftype;
2517 char *fname;
2519 field = (MonoObject *)mono_array_get_internal (fields, gpointer, i);
2520 get_field_name_and_type (field, &fname, &ftype, error);
2521 goto_if_nok (error, leave);
2522 *p++ = 0x53; /* FIELD signature */
2523 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get_internal (fieldValues, gpointer, i), error);
2524 g_free (fname);
2525 goto_if_nok (error, leave);
2529 g_assert (p - buffer <= buflen);
2530 buflen = p - buffer;
2531 result = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, buflen, error);
2532 goto_if_nok (error, leave);
2533 p = mono_array_addr_internal (result, char, 0);
2534 memcpy (p, buffer, buflen);
2535 leave:
2536 g_free (buffer);
2537 if (strcmp (ctor->vtable->klass->name, "RuntimeConstructorInfo"))
2538 g_free (sig);
2539 return result;
2542 static gboolean
2543 reflection_setup_class_hierarchy (GHashTable *unparented, MonoError *error)
2545 error_init (error);
2547 mono_loader_lock ();
2549 MonoType *parent_type;
2550 MonoType *child_type;
2551 GHashTableIter iter;
2553 g_hash_table_iter_init (&iter, unparented);
2555 while (g_hash_table_iter_next (&iter, (gpointer *) &child_type, (gpointer *) &parent_type)) {
2556 MonoClass *child_class = mono_class_from_mono_type_internal (child_type);
2557 if (parent_type != NULL) {
2558 MonoClass *parent_class = mono_class_from_mono_type_internal (parent_type);
2559 child_class->parent = NULL;
2560 /* fool mono_class_setup_parent */
2561 child_class->supertypes = NULL;
2562 mono_class_setup_parent (child_class, parent_class);
2563 } else if (strcmp (child_class->name, "Object") == 0 && strcmp (child_class->name_space, "System") == 0) {
2564 const char *old_n = child_class->name;
2565 /* trick to get relative numbering right when compiling corlib */
2566 child_class->name = "BuildingObject";
2567 mono_class_setup_parent (child_class, mono_defaults.object_class);
2568 child_class->name = old_n;
2570 mono_class_setup_mono_type (child_class);
2571 mono_class_setup_supertypes (child_class);
2574 mono_loader_unlock ();
2575 return is_ok (error);
2578 static gboolean
2579 reflection_setup_internal_class_internal (MonoReflectionTypeBuilderHandle ref_tb, MonoError *error)
2581 HANDLE_FUNCTION_ENTER ();
2582 error_init (error);
2584 mono_loader_lock ();
2586 gint32 entering_state = MONO_HANDLE_GETVAL (MONO_HANDLE_CAST (MonoReflectionTypeBuilder, ref_tb), state);
2587 if (entering_state != MonoTypeBuilderNew) {
2588 g_assert (MONO_HANDLE_GETVAL (MONO_HANDLE_CAST (MonoReflectionType, ref_tb), type));
2589 goto leave;
2592 MONO_HANDLE_SETVAL (ref_tb, state, gint32/*MonoTypeBuilderState*/, MonoTypeBuilderEntered);
2593 MonoReflectionModuleBuilderHandle module_ref;
2594 module_ref = MONO_HANDLE_NEW_GET (MonoReflectionModuleBuilder, ref_tb, module);
2595 GHashTable *unparented_classes;
2596 unparented_classes = MONO_HANDLE_GETVAL(module_ref, unparented_classes);
2598 // If this type is already setup, exit. We'll fix the parenting later
2599 MonoType *type;
2600 type = MONO_HANDLE_GETVAL (MONO_HANDLE_CAST (MonoReflectionType, ref_tb), type);
2601 if (type)
2602 goto leave;
2604 MonoReflectionModuleBuilderHandle ref_module;
2605 ref_module = MONO_HANDLE_NEW_GET (MonoReflectionModuleBuilder, ref_tb, module);
2606 MonoDynamicImage *dynamic_image;
2607 dynamic_image = MONO_HANDLE_GETVAL (ref_module, dynamic_image);
2609 MonoStringHandle ref_name;
2610 ref_name = MONO_HANDLE_NEW_GET (MonoString, ref_tb, name);
2611 MonoStringHandle ref_nspace;
2612 ref_nspace = MONO_HANDLE_NEW_GET (MonoString, ref_tb, nspace);
2614 guint32 table_idx;
2615 table_idx = MONO_HANDLE_GETVAL (ref_tb, table_idx);
2617 * The size calculation here warrants some explaining.
2618 * reflection_setup_internal_class is called too early, well before we know whether the type will be a GTD or DEF,
2619 * meaning we need to alloc enough space to morth a def into a gtd.
2621 MonoClass *klass;
2622 klass = (MonoClass *)mono_image_alloc0 (&dynamic_image->image, MAX (sizeof (MonoClassDef), sizeof (MonoClassGtd)));
2623 klass->class_kind = MONO_CLASS_DEF;
2625 klass->image = &dynamic_image->image;
2627 klass->inited = 1; /* we lie to the runtime */
2628 klass->name = mono_string_to_utf8_image (klass->image, ref_name, error);
2629 goto_if_nok (error, leave);
2630 klass->name_space = mono_string_to_utf8_image (klass->image, ref_nspace, error);
2631 goto_if_nok (error, leave);
2632 klass->type_token = MONO_TOKEN_TYPE_DEF | table_idx;
2633 mono_class_set_flags (klass, MONO_HANDLE_GETVAL (ref_tb, attrs));
2635 MONO_PROFILER_RAISE (class_loading, (klass));
2637 klass->element_class = klass;
2639 g_assert (!mono_class_has_ref_info (klass));
2640 mono_class_set_ref_info (klass, MONO_HANDLE_CAST (MonoObject, ref_tb));
2642 MonoReflectionTypeHandle ref_nesting_type;
2643 ref_nesting_type = MONO_HANDLE_NEW_GET (MonoReflectionType, ref_tb, nesting_type);
2644 /* Put into cache so mono_class_get_checked () will find it.
2645 Skip nested types as those should not be available on the global scope. */
2646 if (MONO_HANDLE_IS_NULL (ref_nesting_type))
2647 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, table_idx);
2650 We must register all types as we cannot rely on the name_cache hashtable since we find the class
2651 by performing a mono_class_get which does the full resolution.
2653 Working around this semantics would require us to write a lot of code for no clear advantage.
2655 mono_image_append_class_to_reflection_info_set (klass);
2657 mono_dynamic_image_register_token (dynamic_image, MONO_TOKEN_TYPE_DEF | table_idx, MONO_HANDLE_CAST (MonoObject, ref_tb), MONO_DYN_IMAGE_TOK_NEW);
2659 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
2660 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
2661 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
2662 klass->instance_size = MONO_ABI_SIZEOF (MonoObject);
2663 klass->size_inited = 1;
2664 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
2667 mono_class_setup_mono_type (klass);
2670 * FIXME: handle interfaces.
2672 MonoReflectionTypeHandle ref_tb_type;
2673 ref_tb_type = MONO_HANDLE_CAST (MonoReflectionType, ref_tb);
2674 MONO_HANDLE_SETVAL (ref_tb_type, type, MonoType*, m_class_get_byval_arg (klass));
2675 MONO_HANDLE_SETVAL (ref_tb, state, gint32, MonoTypeBuilderFinished);
2677 reflection_init_generic_class (ref_tb, error);
2678 goto_if_nok (error, leave);
2680 // Do here so that the search inside of the parent can see the above type that's been set.
2681 MonoReflectionTypeHandle ref_parent;
2682 ref_parent = MONO_HANDLE_CAST (MonoReflectionType, MONO_HANDLE_NEW_GET (MonoObject, ref_tb, parent));
2683 MonoType *parent_type;
2684 parent_type = NULL;
2685 if (!MONO_HANDLE_IS_NULL (ref_parent)) {
2686 MonoClass *parent_klass = mono_handle_class (ref_parent);
2687 gboolean recursive_init = TRUE;
2689 if (is_sre_type_builder (parent_klass)) {
2690 MonoTypeBuilderState parent_state = (MonoTypeBuilderState)MONO_HANDLE_GETVAL (MONO_HANDLE_CAST (MonoReflectionTypeBuilder, ref_parent), state);
2692 if (parent_state != MonoTypeBuilderNew) {
2693 // Initialize types reachable from parent recursively
2694 // We'll fix the type hierarchy later
2695 recursive_init = FALSE;
2699 if (recursive_init) {
2700 // If we haven't encountered a cycle, force the creation of ref_parent's type
2701 mono_reflection_type_handle_mono_type (ref_parent, error);
2702 goto_if_nok (error, leave);
2705 parent_type = MONO_HANDLE_GETVAL (ref_parent, type);
2707 // If we failed to create the parent, fail the child
2708 if (!parent_type)
2709 goto leave;
2712 // Push the child type and parent type to process later
2713 // Note: parent_type may be null.
2714 g_assert (!g_hash_table_lookup (unparented_classes, m_class_get_byval_arg (klass)));
2715 g_hash_table_insert (unparented_classes, m_class_get_byval_arg (klass), parent_type);
2717 if (!MONO_HANDLE_IS_NULL (ref_nesting_type)) {
2718 if (!reflection_setup_internal_class (MONO_HANDLE_CAST (MonoReflectionTypeBuilder, ref_nesting_type), error))
2719 goto leave;
2721 MonoType *nesting_type = mono_reflection_type_handle_mono_type (ref_nesting_type, error);
2722 goto_if_nok (error, leave);
2723 klass->nested_in = mono_class_from_mono_type_internal (nesting_type);
2726 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
2728 MONO_PROFILER_RAISE (class_loaded, (klass));
2730 leave:
2731 mono_loader_unlock ();
2732 HANDLE_FUNCTION_RETURN_VAL (is_ok (error));
2736 * reflection_init_generic_class:
2737 * @tb: a TypeBuilder object
2738 * @error: set on error
2740 * Creates the generic class after all generic parameters have been added.
2741 * On success returns TRUE, on failure returns FALSE and sets @error.
2743 * This assumes that reflection_setup_internal_class has already set up
2744 * ref_tb
2746 static gboolean
2747 reflection_init_generic_class (MonoReflectionTypeBuilderHandle ref_tb, MonoError *error)
2749 HANDLE_FUNCTION_ENTER ();
2751 error_init (error);
2753 MonoTypeBuilderState ref_state = (MonoTypeBuilderState)MONO_HANDLE_GETVAL (ref_tb, state);
2754 g_assert (ref_state == MonoTypeBuilderFinished);
2756 MonoType *type = MONO_HANDLE_GETVAL (MONO_HANDLE_CAST (MonoReflectionType, ref_tb), type);
2757 MonoClass *klass = mono_class_from_mono_type_internal (type);
2759 MonoArrayHandle generic_params = MONO_HANDLE_NEW_GET (MonoArray, ref_tb, generic_params);
2760 int count = MONO_HANDLE_IS_NULL (generic_params) ? 0 : mono_array_handle_length (generic_params);
2762 if (count == 0)
2763 goto leave;
2765 if (mono_class_try_get_generic_container (klass) != NULL)
2766 goto leave; /* already setup */
2768 MonoGenericContainer *generic_container;
2769 generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
2771 generic_container->owner.klass = klass;
2772 generic_container->type_argc = count;
2773 generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
2775 klass->class_kind = MONO_CLASS_GTD;
2776 mono_class_set_generic_container (klass, generic_container);
2779 MonoReflectionGenericParamHandle ref_gparam;
2780 ref_gparam = MONO_HANDLE_NEW (MonoReflectionGenericParam, NULL);
2781 for (int i = 0; i < count; i++) {
2782 MONO_HANDLE_ARRAY_GETREF (ref_gparam, generic_params, i);
2783 MonoType *param_type = mono_reflection_type_handle_mono_type (MONO_HANDLE_CAST (MonoReflectionType, ref_gparam), error);
2784 goto_if_nok (error, leave);
2785 MonoGenericParamFull *param = (MonoGenericParamFull *) param_type->data.generic_param;
2786 generic_container->type_params [i] = *param;
2787 /*Make sure we are a diferent type instance */
2788 generic_container->type_params [i].owner = generic_container;
2789 generic_container->type_params [i].info.pklass = NULL;
2790 generic_container->type_params [i].info.flags = MONO_HANDLE_GETVAL (ref_gparam, attrs);
2792 g_assert (generic_container->type_params [i].owner);
2795 generic_container->context.class_inst = mono_get_shared_generic_inst (generic_container);
2796 MonoGenericContext* context;
2797 context = &generic_container->context;
2798 MonoType *canonical_inst;
2799 canonical_inst = &((MonoClassGtd*)klass)->canonical_inst;
2800 canonical_inst->type = MONO_TYPE_GENERICINST;
2801 canonical_inst->data.generic_class = mono_metadata_lookup_generic_class (klass, context->class_inst, FALSE);
2803 leave:
2804 HANDLE_FUNCTION_RETURN_VAL (is_ok (error));
2807 static MonoMarshalSpec*
2808 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
2809 MonoReflectionMarshal *minfo, MonoError *error)
2811 MonoMarshalSpec *res;
2813 error_init (error);
2815 res = image_g_new0 (image, MonoMarshalSpec, 1);
2816 res->native = (MonoMarshalNative)minfo->type;
2818 switch (minfo->type) {
2819 case MONO_NATIVE_LPARRAY:
2820 res->data.array_data.elem_type = (MonoMarshalNative)minfo->eltype;
2821 if (minfo->has_size) {
2822 res->data.array_data.param_num = minfo->param_num;
2823 res->data.array_data.num_elem = minfo->count;
2824 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
2826 else {
2827 res->data.array_data.param_num = -1;
2828 res->data.array_data.num_elem = -1;
2829 res->data.array_data.elem_mult = -1;
2831 break;
2833 case MONO_NATIVE_BYVALTSTR:
2834 case MONO_NATIVE_BYVALARRAY:
2835 res->data.array_data.num_elem = minfo->count;
2836 break;
2838 case MONO_NATIVE_CUSTOM:
2839 if (minfo->marshaltyperef) {
2840 MonoType *marshaltyperef = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, error);
2841 if (!is_ok (error)) {
2842 image_g_free (image, res);
2843 return NULL;
2845 res->data.custom_data.custom_name =
2846 type_get_fully_qualified_name (marshaltyperef);
2848 if (minfo->mcookie) {
2849 res->data.custom_data.cookie = mono_string_to_utf8_checked_internal (minfo->mcookie, error);
2850 if (!is_ok (error)) {
2851 image_g_free (image, res);
2852 return NULL;
2855 break;
2857 default:
2858 break;
2861 return res;
2863 #endif /* !DISABLE_REFLECTION_EMIT */
2865 MonoReflectionMarshalAsAttributeHandle
2866 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
2867 MonoMarshalSpec *spec, MonoError *error)
2869 error_init (error);
2871 MonoReflectionMarshalAsAttributeHandle minfo = MONO_HANDLE_CAST (MonoReflectionMarshalAsAttribute, mono_object_new_handle (domain, mono_class_get_marshal_as_attribute_class (), error));
2872 goto_if_nok (error, fail);
2873 guint32 utype;
2874 utype = spec->native;
2875 MONO_HANDLE_SETVAL (minfo, utype, guint32, utype);
2877 switch (utype) {
2878 case MONO_NATIVE_LPARRAY:
2879 MONO_HANDLE_SETVAL (minfo, array_subtype, guint32, spec->data.array_data.elem_type);
2880 if (spec->data.array_data.num_elem != -1)
2881 MONO_HANDLE_SETVAL (minfo, size_const, gint32, spec->data.array_data.num_elem);
2882 if (spec->data.array_data.param_num != -1)
2883 MONO_HANDLE_SETVAL (minfo, size_param_index, gint16, spec->data.array_data.param_num);
2884 break;
2886 case MONO_NATIVE_BYVALTSTR:
2887 case MONO_NATIVE_BYVALARRAY:
2888 if (spec->data.array_data.num_elem != -1)
2889 MONO_HANDLE_SETVAL (minfo, size_const, gint32, spec->data.array_data.num_elem);
2890 break;
2892 case MONO_NATIVE_CUSTOM:
2893 if (spec->data.custom_data.custom_name) {
2894 MonoType *mtype = mono_reflection_type_from_name_checked (spec->data.custom_data.custom_name, klass->image, error);
2895 goto_if_nok (error, fail);
2897 if (mtype) {
2898 MonoReflectionTypeHandle rt = mono_type_get_object_handle (domain, mtype, error);
2899 goto_if_nok (error, fail);
2901 MONO_HANDLE_SET (minfo, marshal_type_ref, rt);
2904 MonoStringHandle custom_name = mono_string_new_handle (domain, spec->data.custom_data.custom_name, error);
2905 goto_if_nok (error, fail);
2906 MONO_HANDLE_SET (minfo, marshal_type, custom_name);
2908 if (spec->data.custom_data.cookie) {
2909 MonoStringHandle cookie = mono_string_new_handle (domain, spec->data.custom_data.cookie, error);
2910 goto_if_nok (error, fail);
2911 MONO_HANDLE_SET (minfo, marshal_cookie, cookie);
2913 break;
2915 default:
2916 break;
2919 return minfo;
2920 fail:
2921 return MONO_HANDLE_NEW (MonoReflectionMarshalAsAttribute, NULL);
2924 #ifndef DISABLE_REFLECTION_EMIT
2925 static MonoMethod*
2926 reflection_methodbuilder_to_mono_method (MonoClass *klass,
2927 ReflectionMethodBuilder *rmb,
2928 MonoMethodSignature *sig,
2929 MonoError *error)
2931 MonoMethod *m;
2932 MonoMethodWrapper *wrapperm;
2933 MonoMarshalSpec **specs = NULL;
2934 MonoReflectionMethodAux *method_aux;
2935 MonoImage *image;
2936 gboolean dynamic;
2937 int i;
2939 error_init (error);
2941 * Methods created using a MethodBuilder should have their memory allocated
2942 * inside the image mempool, while dynamic methods should have their memory
2943 * malloc'd.
2945 dynamic = rmb->refs != NULL;
2946 image = dynamic ? NULL : klass->image;
2948 if (!dynamic)
2949 g_assert (!mono_class_is_ginst (klass));
2951 mono_loader_lock ();
2953 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
2954 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
2955 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
2956 else
2957 m = (MonoMethod *)image_g_new0 (image, MonoDynamicMethod, 1);
2959 wrapperm = (MonoMethodWrapper*)m;
2961 m->dynamic = dynamic;
2962 m->slot = -1;
2963 m->flags = rmb->attrs;
2964 m->iflags = rmb->iattrs;
2965 m->name = string_to_utf8_image_raw (image, rmb->name, error);
2966 goto_if_nok (error, fail);
2967 m->klass = klass;
2968 m->signature = sig;
2969 m->sre_method = TRUE;
2970 m->skip_visibility = rmb->skip_visibility;
2971 if (rmb->table_idx)
2972 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
2974 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
2975 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
2976 m->string_ctor = 1;
2978 m->signature->pinvoke = 1;
2979 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
2980 m->signature->pinvoke = 1;
2982 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
2984 method_aux->dllentry = rmb->dllentry ? string_to_utf8_image_raw (image, rmb->dllentry, error) : image_strdup (image, m->name);
2985 mono_error_assert_ok (error);
2986 method_aux->dll = string_to_utf8_image_raw (image, rmb->dll, error);
2987 mono_error_assert_ok (error);
2989 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
2991 if (image_is_dynamic (klass->image))
2992 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
2994 goto leave;
2996 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
2997 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
2998 MonoMethodHeader *header;
2999 guint32 code_size;
3000 gint32 max_stack, i;
3001 gint32 num_locals = 0;
3002 gint32 num_clauses = 0;
3003 guint8 *code;
3005 if (rmb->ilgen) {
3006 code = mono_array_addr_internal (rmb->ilgen->code, guint8, 0);
3007 code_size = rmb->ilgen->code_len;
3008 max_stack = rmb->ilgen->max_stack;
3009 num_locals = rmb->ilgen->locals ? mono_array_length_internal (rmb->ilgen->locals) : 0;
3010 if (rmb->ilgen->ex_handlers)
3011 num_clauses = mono_reflection_method_count_clauses (rmb->ilgen);
3012 } else {
3013 if (rmb->code) {
3014 code = mono_array_addr_internal (rmb->code, guint8, 0);
3015 code_size = mono_array_length_internal (rmb->code);
3016 /* we probably need to run a verifier on the code... */
3017 max_stack = 8;
3019 else {
3020 code = NULL;
3021 code_size = 0;
3022 max_stack = 8;
3026 header = (MonoMethodHeader *)mono_image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
3027 header->code_size = code_size;
3028 header->code = (const unsigned char *)image_g_malloc (image, code_size);
3029 memcpy ((char*)header->code, code, code_size);
3030 header->max_stack = max_stack;
3031 header->init_locals = rmb->init_locals;
3032 header->num_locals = num_locals;
3034 for (i = 0; i < num_locals; ++i) {
3035 MonoReflectionLocalBuilder *lb =
3036 mono_array_get_internal (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
3038 header->locals [i] = image_g_new0 (image, MonoType, 1);
3039 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)lb->type, error);
3040 mono_error_assert_ok (error);
3041 memcpy (header->locals [i], type, mono_sizeof_type (type));
3044 header->num_clauses = num_clauses;
3045 if (num_clauses) {
3046 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
3047 rmb->ilgen, num_clauses, error);
3048 mono_error_assert_ok (error);
3051 wrapperm->header = header;
3052 MonoDynamicMethod *dm = (MonoDynamicMethod*)wrapperm;
3053 dm->assembly = klass->image->assembly;
3056 if (rmb->generic_params) {
3057 int count = mono_array_length_internal (rmb->generic_params);
3058 MonoGenericContainer *container;
3060 container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
3061 container->is_method = TRUE;
3062 container->is_anonymous = FALSE;
3063 container->type_argc = count;
3064 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
3065 container->owner.method = m;
3067 m->is_generic = TRUE;
3068 mono_method_set_generic_container (m, container);
3070 for (i = 0; i < count; i++) {
3071 MonoReflectionGenericParam *gp =
3072 mono_array_get_internal (rmb->generic_params, MonoReflectionGenericParam*, i);
3073 MonoType *gp_type = mono_reflection_type_get_handle ((MonoReflectionType*)gp, error);
3074 mono_error_assert_ok (error);
3075 MonoGenericParamFull *param = (MonoGenericParamFull *) gp_type->data.generic_param;
3076 container->type_params [i] = *param;
3077 container->type_params [i].owner = container;
3079 gp->type.type->data.generic_param = (MonoGenericParam*)&container->type_params [i];
3081 MonoClass *gklass = mono_class_from_mono_type_internal (gp_type);
3082 gklass->wastypebuilder = TRUE;
3086 * The method signature might have pointers to generic parameters that belong to other methods.
3087 * This is a valid SRE case, but the resulting method signature must be encoded using the proper
3088 * generic parameters.
3090 for (i = 0; i < m->signature->param_count; ++i) {
3091 MonoType *t = m->signature->params [i];
3092 if (t->type == MONO_TYPE_MVAR) {
3093 MonoGenericParam *gparam = t->data.generic_param;
3094 if (gparam->num < count) {
3095 m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
3096 m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
3102 if (mono_class_is_gtd (klass)) {
3103 container->parent = mono_class_get_generic_container (klass);
3104 container->context.class_inst = mono_class_get_generic_container (klass)->context.class_inst;
3106 container->context.method_inst = mono_get_shared_generic_inst (container);
3109 if (rmb->refs) {
3110 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
3111 int i;
3112 void **data;
3114 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
3116 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
3117 data [0] = GUINT_TO_POINTER (rmb->nrefs);
3118 for (i = 0; i < rmb->nrefs; ++i)
3119 data [i + 1] = rmb->refs [i];
3122 method_aux = NULL;
3124 /* Parameter info */
3125 if (rmb->pinfo) {
3126 if (!method_aux)
3127 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
3128 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature_internal (m)->param_count + 1);
3129 for (i = 0; i <= m->signature->param_count; ++i) {
3130 MonoReflectionParamBuilder *pb;
3131 if ((pb = mono_array_get_internal (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
3132 if ((i > 0) && (pb->attrs)) {
3133 /* Make a copy since it might point to a shared type structure */
3134 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
3135 m->signature->params [i - 1]->attrs = pb->attrs;
3138 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
3139 MonoDynamicImage *assembly;
3140 guint32 idx, len;
3141 MonoTypeEnum def_type;
3142 char *p;
3143 const char *p2;
3145 if (!method_aux->param_defaults) {
3146 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
3147 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
3149 assembly = (MonoDynamicImage*)klass->image;
3150 idx = mono_dynimage_encode_constant (assembly, pb->def_value, &def_type);
3151 /* Copy the data from the blob since it might get realloc-ed */
3152 p = assembly->blob.data + idx;
3153 len = mono_metadata_decode_blob_size (p, &p2);
3154 len += p2 - p;
3155 method_aux->param_defaults [i] = (uint8_t *)image_g_malloc (image, len);
3156 method_aux->param_default_types [i] = def_type;
3157 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
3160 if (pb->name) {
3161 method_aux->param_names [i] = string_to_utf8_image_raw (image, pb->name, error);
3162 mono_error_assert_ok (error);
3164 if (pb->cattrs) {
3165 if (!method_aux->param_cattr)
3166 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
3167 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
3173 /* Parameter marshalling */
3174 if (rmb->pinfo)
3175 for (i = 0; i < mono_array_length_internal (rmb->pinfo); ++i) {
3176 MonoReflectionParamBuilder *pb;
3177 if ((pb = mono_array_get_internal (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
3178 if (pb->marshal_info) {
3179 if (specs == NULL)
3180 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
3181 specs [pb->position] =
3182 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info, error);
3183 goto_if_nok (error, fail);
3187 if (specs != NULL) {
3188 if (!method_aux)
3189 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
3190 method_aux->param_marshall = specs;
3193 if (image_is_dynamic (klass->image) && method_aux)
3194 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
3196 leave:
3197 mono_loader_unlock ();
3198 if (!m) // FIXME: This leaks if image is not NULL.
3199 image_g_free (image, specs);
3200 return m;
3202 fail:
3203 m = NULL;
3204 goto leave;
3207 static MonoMethod*
3208 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb, MonoError *error)
3210 ReflectionMethodBuilder rmb;
3211 MonoMethodSignature *sig;
3213 mono_loader_lock ();
3215 if (!mono_reflection_methodbuilder_from_ctor_builder (&rmb, mb, error)) {
3216 mono_loader_unlock ();
3217 return NULL;
3220 g_assert (klass->image != NULL);
3221 sig = ctor_builder_to_signature_raw (klass->image, mb, error); /* FIXME use handles */
3222 mono_loader_unlock ();
3223 return_val_if_nok (error, NULL);
3225 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
3226 return_val_if_nok (error, NULL);
3227 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
3229 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
3230 /* ilgen is no longer needed */
3231 mb->ilgen = NULL;
3234 return mb->mhandle;
3237 static MonoMethod*
3238 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilderHandle ref_mb, MonoError *error)
3240 ReflectionMethodBuilder rmb;
3241 MonoMethodSignature *sig;
3243 error_init (error);
3245 mono_loader_lock ();
3247 MonoReflectionMethodBuilder *mb = MONO_HANDLE_RAW (ref_mb); /* FIXME use handles */
3248 if (!mono_reflection_methodbuilder_from_method_builder (&rmb, mb, error)) {
3249 mono_loader_unlock ();
3250 return NULL;
3253 g_assert (klass->image != NULL);
3254 sig = method_builder_to_signature (klass->image, ref_mb, error);
3255 mono_loader_unlock ();
3256 return_val_if_nok (error, NULL);
3258 MonoMethod *method = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
3259 return_val_if_nok (error, NULL);
3260 MONO_HANDLE_SETVAL (ref_mb, mhandle, MonoMethod*, method);
3261 mono_save_custom_attrs (klass->image, method, mb->cattrs);
3263 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save)
3264 /* ilgen is no longer needed */
3265 mb->ilgen = NULL;
3266 return method;
3269 static MonoMethod*
3270 methodbuilder_to_mono_method_raw (MonoClass *klass, MonoReflectionMethodBuilder* mb_raw, MonoError *error)
3272 HANDLE_FUNCTION_ENTER (); /* FIXME change callers of methodbuilder_to_mono_method_raw to use handles */
3273 error_init (error);
3274 MONO_HANDLE_DCL (MonoReflectionMethodBuilder, mb);
3275 MonoMethod *result = methodbuilder_to_mono_method (klass, mb, error);
3276 HANDLE_FUNCTION_RETURN_VAL (result);
3279 #endif
3281 #ifndef DISABLE_REFLECTION_EMIT
3284 * fix_partial_generic_class:
3285 * @klass: a generic instantiation MonoClass
3286 * @error: set on error
3288 * Assumes that the generic container of @klass has its vtable
3289 * initialized, and updates the parent class, interfaces, methods and
3290 * fields of @klass by inflating the types using the generic context.
3292 * On success returns TRUE, on failure returns FALSE and sets @error.
3295 static gboolean
3296 fix_partial_generic_class (MonoClass *klass, MonoError *error)
3298 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
3299 int i;
3301 error_init (error);
3303 if (klass->wastypebuilder)
3304 return TRUE;
3306 if (klass->parent != gklass->parent) {
3307 MonoType *parent_type = mono_class_inflate_generic_type_checked (m_class_get_byval_arg (m_class_get_parent (gklass)), &mono_class_get_generic_class (klass)->context, error);
3308 if (mono_error_ok (error)) {
3309 MonoClass *parent = mono_class_from_mono_type_internal (parent_type);
3310 mono_metadata_free_type (parent_type);
3311 if (parent != klass->parent) {
3312 /*fool mono_class_setup_parent*/
3313 klass->supertypes = NULL;
3314 mono_class_setup_parent (klass, parent);
3316 } else {
3317 if (gklass->wastypebuilder)
3318 klass->wastypebuilder = TRUE;
3319 return FALSE;
3323 if (!mono_class_get_generic_class (klass)->need_sync)
3324 return TRUE;
3326 int mcount = mono_class_get_method_count (klass);
3327 int gmcount = mono_class_get_method_count (gklass);
3328 if (mcount != gmcount) {
3329 mono_class_set_method_count (klass, gmcount);
3330 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (gmcount + 1));
3332 for (i = 0; i < gmcount; i++) {
3333 klass->methods [i] = mono_class_inflate_generic_method_full_checked (
3334 gklass->methods [i], klass, mono_class_get_context (klass), error);
3335 mono_error_assert_ok (error);
3339 if (klass->interface_count && klass->interface_count != gklass->interface_count) {
3340 klass->interface_count = gklass->interface_count;
3341 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
3342 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
3344 MonoClass **gklass_interfaces = m_class_get_interfaces (gklass);
3345 for (i = 0; i < gklass->interface_count; ++i) {
3346 MonoType *iface_type = mono_class_inflate_generic_type_checked (m_class_get_byval_arg (gklass_interfaces [i]), mono_class_get_context (klass), error);
3347 return_val_if_nok (error, FALSE);
3349 klass->interfaces [i] = mono_class_from_mono_type_internal (iface_type);
3350 mono_metadata_free_type (iface_type);
3352 if (!ensure_runtime_vtable (klass->interfaces [i], error))
3353 return FALSE;
3355 klass->interfaces_inited = 1;
3358 int fcount = mono_class_get_field_count (klass);
3359 int gfcount = mono_class_get_field_count (gklass);
3360 if (fcount != gfcount) {
3361 mono_class_set_field_count (klass, gfcount);
3362 klass->fields = image_g_new0 (klass->image, MonoClassField, gfcount);
3364 for (i = 0; i < gfcount; i++) {
3365 klass->fields [i] = gklass->fields [i];
3366 klass->fields [i].parent = klass;
3367 klass->fields [i].type = mono_class_inflate_generic_type_checked (gklass->fields [i].type, mono_class_get_context (klass), error);
3368 return_val_if_nok (error, FALSE);
3372 /*We can only finish with this klass once it's parent has as well*/
3373 if (gklass->wastypebuilder)
3374 klass->wastypebuilder = TRUE;
3375 return TRUE;
3379 * ensure_generic_class_runtime_vtable:
3380 * @klass a generic class
3381 * @error set on error
3383 * Ensures that the generic container of @klass has a vtable and
3384 * returns TRUE on success. On error returns FALSE and sets @error.
3386 static gboolean
3387 ensure_generic_class_runtime_vtable (MonoClass *klass, MonoError *error)
3389 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
3391 error_init (error);
3393 if (!ensure_runtime_vtable (gklass, error))
3394 return FALSE;
3396 return fix_partial_generic_class (klass, error);
3400 * ensure_runtime_vtable:
3401 * @klass the class
3402 * @error set on error
3404 * Ensures that @klass has a vtable and returns TRUE on success. On
3405 * error returns FALSE and sets @error.
3407 static gboolean
3408 ensure_runtime_vtable (MonoClass *klass, MonoError *error)
3410 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info_raw (klass); /* FIXME use handles */
3411 int i, num, j;
3413 error_init (error);
3415 if (!image_is_dynamic (klass->image) || (!tb && !mono_class_is_ginst (klass)) || klass->wastypebuilder)
3416 return TRUE;
3417 if (klass->parent)
3418 if (!ensure_runtime_vtable (klass->parent, error))
3419 return FALSE;
3421 if (tb) {
3422 num = tb->ctors? mono_array_length_internal (tb->ctors): 0;
3423 num += tb->num_methods;
3424 mono_class_set_method_count (klass, num);
3425 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
3426 num = tb->ctors? mono_array_length_internal (tb->ctors): 0;
3427 for (i = 0; i < num; ++i) {
3428 MonoMethod *ctor = ctorbuilder_to_mono_method (klass, mono_array_get_internal (tb->ctors, MonoReflectionCtorBuilder*, i), error);
3429 if (!ctor)
3430 return FALSE;
3431 klass->methods [i] = ctor;
3433 num = tb->num_methods;
3434 j = i;
3435 for (i = 0; i < num; ++i) {
3436 MonoMethod *meth = methodbuilder_to_mono_method_raw (klass, mono_array_get_internal (tb->methods, MonoReflectionMethodBuilder*, i), error); /* FIXME use handles */
3437 if (!meth)
3438 return FALSE;
3439 klass->methods [j++] = meth;
3442 if (tb->interfaces) {
3443 klass->interface_count = mono_array_length_internal (tb->interfaces);
3444 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
3445 for (i = 0; i < klass->interface_count; ++i) {
3446 MonoType *iface = mono_type_array_get_and_resolve_raw (tb->interfaces, i, error); /* FIXME use handles */
3447 return_val_if_nok (error, FALSE);
3448 klass->interfaces [i] = mono_class_from_mono_type_internal (iface);
3449 if (!ensure_runtime_vtable (klass->interfaces [i], error))
3450 return FALSE;
3452 klass->interfaces_inited = 1;
3454 } else if (mono_class_is_ginst (klass)){
3455 if (!ensure_generic_class_runtime_vtable (klass, error)) {
3456 mono_class_set_type_load_failure (klass, "Could not initialize vtable for generic class due to: %s", mono_error_get_message (error));
3457 return FALSE;
3461 if (mono_class_is_interface (klass) && !mono_class_is_ginst (klass)) {
3462 int slot_num = 0;
3463 int mcount = mono_class_get_method_count (klass);
3464 for (i = 0; i < mcount; ++i) {
3465 MonoMethod *im = klass->methods [i];
3466 if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
3467 im->slot = slot_num++;
3470 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
3471 mono_class_setup_interface_offsets (klass);
3472 mono_class_setup_interface_id (klass);
3476 * The generic vtable is needed even if image->run is not set since some
3477 * runtime code like ves_icall_Type_GetMethodsByName depends on
3478 * method->slot being defined.
3482 * tb->methods could not be freed since it is used for determining
3483 * overrides during dynamic vtable construction.
3486 return TRUE;
3489 static MonoMethod*
3490 mono_reflection_method_get_handle (MonoObject *method, MonoError *error)
3492 error_init (error);
3493 MonoClass *klass = mono_object_class (method);
3494 if (is_sr_mono_method (klass)) {
3495 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
3496 return sr_method->method;
3498 if (is_sre_method_builder (klass)) {
3499 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
3500 return mb->mhandle;
3502 if (mono_is_sre_method_on_tb_inst (klass)) {
3503 MonoClass *handle_class;
3505 MonoMethod *result = (MonoMethod*)mono_reflection_resolve_object (NULL, method, &handle_class, NULL, error);
3506 return_val_if_nok (error, NULL);
3508 return result;
3511 g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
3512 return NULL;
3515 void
3516 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides, MonoError *error)
3518 MonoReflectionTypeBuilder *tb;
3519 int i, j, onum;
3520 MonoReflectionMethod *m;
3522 error_init (error);
3523 *overrides = NULL;
3524 *num_overrides = 0;
3526 g_assert (image_is_dynamic (klass->image));
3528 if (!mono_class_has_ref_info (klass))
3529 return;
3531 tb = mono_class_get_ref_info_raw (klass); /* FIXME use handles */
3532 g_assert (strcmp (mono_object_class (tb)->name, "TypeBuilder") == 0);
3534 onum = 0;
3535 if (tb->methods) {
3536 for (i = 0; i < tb->num_methods; ++i) {
3537 MonoReflectionMethodBuilder *mb =
3538 mono_array_get_internal (tb->methods, MonoReflectionMethodBuilder*, i);
3539 if (mb->override_methods)
3540 onum += mono_array_length_internal (mb->override_methods);
3544 if (onum) {
3545 *overrides = g_new0 (MonoMethod*, onum * 2);
3547 onum = 0;
3548 for (i = 0; i < tb->num_methods; ++i) {
3549 MonoReflectionMethodBuilder *mb =
3550 mono_array_get_internal (tb->methods, MonoReflectionMethodBuilder*, i);
3551 if (mb->override_methods) {
3552 for (j = 0; j < mono_array_length_internal (mb->override_methods); ++j) {
3553 m = mono_array_get_internal (mb->override_methods, MonoReflectionMethod*, j);
3555 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m, error);
3556 return_if_nok (error);
3557 (*overrides) [onum * 2 + 1] = mb->mhandle;
3559 g_assert (mb->mhandle);
3561 onum ++;
3567 *num_overrides = onum;
3570 static gint32
3571 modulebuilder_get_next_table_index (MonoReflectionModuleBuilder *mb, gint32 table, gint32 num_fields, MonoError *error)
3573 error_init (error);
3575 if (mb->table_indexes == NULL) {
3576 MonoArray *arr = mono_array_new_checked (mono_object_domain (&mb->module.obj), mono_defaults.int_class, 64, error);
3577 return_val_if_nok (error, 0);
3578 for (int i = 0; i < 64; i++) {
3579 mono_array_set_internal (arr, int, i, 1);
3581 MONO_OBJECT_SETREF_INTERNAL (mb, table_indexes, arr);
3583 gint32 index = mono_array_get_internal (mb->table_indexes, gint32, table);
3584 gint32 next_index = index + num_fields;
3585 mono_array_set_internal (mb->table_indexes, gint32, table, next_index);
3586 return index;
3589 /* This initializes the same data as mono_class_setup_fields () */
3590 static void
3591 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
3593 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info_raw (klass); /* FIXME use handles */
3594 MonoReflectionFieldBuilder *fb;
3595 MonoClassField *field;
3596 MonoFieldDefaultValue *def_values;
3597 MonoImage *image = klass->image;
3598 const char *p, *p2;
3599 int i, instance_size, packing_size = 0;
3600 guint32 len, idx;
3602 error_init (error);
3604 if (klass->parent) {
3605 if (!klass->parent->size_inited)
3606 mono_class_init_internal (klass->parent);
3607 instance_size = klass->parent->instance_size;
3608 } else {
3609 instance_size = MONO_ABI_SIZEOF (MonoObject);
3612 int fcount = tb->num_fields;
3613 mono_class_set_field_count (klass, fcount);
3615 gint32 first_idx = 0;
3616 if (tb->num_fields > 0) {
3617 first_idx = modulebuilder_get_next_table_index (tb->module, MONO_TABLE_FIELD, (gint32)tb->num_fields, error);
3618 return_if_nok (error);
3620 mono_class_set_first_field_idx (klass, first_idx - 1); /* Why do we subtract 1? because mono_class_create_from_typedef does it, too. */
3622 if (tb->class_size) {
3623 packing_size = tb->packing_size;
3624 instance_size += tb->class_size;
3627 klass->fields = image_g_new0 (image, MonoClassField, fcount);
3628 def_values = image_g_new0 (image, MonoFieldDefaultValue, fcount);
3629 mono_class_set_field_def_values (klass, def_values);
3631 This is, guess what, a hack.
3632 The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
3633 On the static path no field class is resolved, only types are built. This is the right thing to do
3634 but we suck.
3635 Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
3637 klass->size_inited = 1;
3639 for (i = 0; i < fcount; ++i) {
3640 MonoArray *rva_data;
3641 fb = (MonoReflectionFieldBuilder *)mono_array_get_internal (tb->fields, gpointer, i);
3642 field = &klass->fields [i];
3643 field->parent = klass;
3644 field->name = string_to_utf8_image_raw (image, fb->name, error); /* FIXME use handles */
3645 if (!mono_error_ok (error))
3646 return;
3647 if (fb->attrs) {
3648 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
3649 return_if_nok (error);
3650 field->type = mono_metadata_type_dup (klass->image, type);
3651 field->type->attrs = fb->attrs;
3652 } else {
3653 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
3654 return_if_nok (error);
3657 if (!klass->enumtype && !mono_type_get_underlying_type (field->type)) {
3658 mono_class_set_type_load_failure (klass, "Field '%s' is an enum type with a bad underlying type", field->name);
3659 continue;
3662 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
3663 char *base = mono_array_addr_internal (rva_data, char, 0);
3664 size_t size = mono_array_length_internal (rva_data);
3665 char *data = (char *)mono_image_alloc (klass->image, size);
3666 memcpy (data, base, size);
3667 def_values [i].data = data;
3669 if (fb->offset != -1)
3670 field->offset = fb->offset;
3671 fb->handle = field;
3672 mono_save_custom_attrs (klass->image, field, fb->cattrs);
3674 if (fb->def_value) {
3675 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
3676 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
3677 idx = mono_dynimage_encode_constant (assembly, fb->def_value, &def_values [i].def_type);
3678 /* Copy the data from the blob since it might get realloc-ed */
3679 p = assembly->blob.data + idx;
3680 len = mono_metadata_decode_blob_size (p, &p2);
3681 len += p2 - p;
3682 def_values [i].data = (const char *)mono_image_alloc (image, len);
3683 memcpy ((gpointer)def_values [i].data, p, len);
3686 MonoObjectHandle field_builder_handle = MONO_HANDLE_CAST (MonoObject, MONO_HANDLE_NEW (MonoReflectionFieldBuilder, fb));
3687 mono_dynamic_image_register_token (tb->module->dynamic_image, mono_metadata_make_token (MONO_TABLE_FIELD, first_idx + i), field_builder_handle, MONO_DYN_IMAGE_TOK_NEW);
3690 if (!mono_class_has_failure (klass))
3691 mono_class_layout_fields (klass, instance_size, packing_size, tb->class_size, TRUE);
3694 static void
3695 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
3697 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info_raw (klass); /* FIXME use handles */
3698 MonoReflectionPropertyBuilder *pb;
3699 MonoImage *image = klass->image;
3700 MonoProperty *properties;
3701 MonoClassPropertyInfo *info;
3702 int i;
3704 error_init (error);
3706 info = (MonoClassPropertyInfo*)mono_class_get_property_info (klass);
3707 if (!info) {
3708 info = mono_class_alloc0 (klass, sizeof (MonoClassPropertyInfo));
3709 mono_class_set_property_info (klass, info);
3712 info->count = tb->properties ? mono_array_length_internal (tb->properties) : 0;
3713 info->first = 0;
3715 properties = image_g_new0 (image, MonoProperty, info->count);
3716 info->properties = properties;
3717 for (i = 0; i < info->count; ++i) {
3718 pb = mono_array_get_internal (tb->properties, MonoReflectionPropertyBuilder*, i);
3719 properties [i].parent = klass;
3720 properties [i].attrs = pb->attrs;
3721 properties [i].name = string_to_utf8_image_raw (image, pb->name, error); /* FIXME use handles */
3722 if (!mono_error_ok (error))
3723 return;
3724 if (pb->get_method)
3725 properties [i].get = pb->get_method->mhandle;
3726 if (pb->set_method)
3727 properties [i].set = pb->set_method->mhandle;
3729 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
3730 if (pb->def_value) {
3731 guint32 len, idx;
3732 const char *p, *p2;
3733 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
3734 if (!info->def_values)
3735 info->def_values = image_g_new0 (image, MonoFieldDefaultValue, info->count);
3736 properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
3737 idx = mono_dynimage_encode_constant (assembly, pb->def_value, &info->def_values [i].def_type);
3738 /* Copy the data from the blob since it might get realloc-ed */
3739 p = assembly->blob.data + idx;
3740 len = mono_metadata_decode_blob_size (p, &p2);
3741 len += p2 - p;
3742 info->def_values [i].data = (const char *)mono_image_alloc (image, len);
3743 memcpy ((gpointer)info->def_values [i].data, p, len);
3748 static void
3749 typebuilder_setup_events (MonoClass *klass, MonoError *error)
3751 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info_raw (klass); /* FIXME use handles */
3752 MonoReflectionEventBuilder *eb;
3753 MonoImage *image = klass->image;
3754 MonoEvent *events;
3755 MonoClassEventInfo *info;
3756 int i;
3758 error_init (error);
3760 info = mono_class_alloc0 (klass, sizeof (MonoClassEventInfo));
3761 mono_class_set_event_info (klass, info);
3763 info->count = tb->events ? mono_array_length_internal (tb->events) : 0;
3764 info->first = 0;
3766 events = image_g_new0 (image, MonoEvent, info->count);
3767 info->events = events;
3768 for (i = 0; i < info->count; ++i) {
3769 eb = mono_array_get_internal (tb->events, MonoReflectionEventBuilder*, i);
3770 events [i].parent = klass;
3771 events [i].attrs = eb->attrs;
3772 events [i].name = string_to_utf8_image_raw (image, eb->name, error); /* FIXME use handles */
3773 if (!mono_error_ok (error))
3774 return;
3775 if (eb->add_method)
3776 events [i].add = eb->add_method->mhandle;
3777 if (eb->remove_method)
3778 events [i].remove = eb->remove_method->mhandle;
3779 if (eb->raise_method)
3780 events [i].raise = eb->raise_method->mhandle;
3782 #ifndef MONO_SMALL_CONFIG
3783 if (eb->other_methods) {
3784 int j;
3785 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length_internal (eb->other_methods) + 1);
3786 for (j = 0; j < mono_array_length_internal (eb->other_methods); ++j) {
3787 MonoReflectionMethodBuilder *mb =
3788 mono_array_get_internal (eb->other_methods,
3789 MonoReflectionMethodBuilder*, j);
3790 events [i].other [j] = mb->mhandle;
3793 #endif
3794 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
3798 struct remove_instantiations_user_data
3800 MonoClass *klass;
3801 MonoError *error;
3804 static gboolean
3805 remove_instantiations_of_and_ensure_contents (gpointer key,
3806 gpointer value,
3807 gpointer user_data)
3809 struct remove_instantiations_user_data *data = (struct remove_instantiations_user_data*)user_data;
3810 MonoType *type = (MonoType*)key;
3811 MonoClass *klass = data->klass;
3812 gboolean already_failed = !is_ok (data->error);
3813 ERROR_DECL (lerror);
3814 MonoError *error = already_failed ? lerror : data->error;
3816 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
3817 MonoClass *inst_klass = mono_class_from_mono_type_internal (type);
3818 //Ensure it's safe to use it.
3819 if (!fix_partial_generic_class (inst_klass, error)) {
3820 mono_class_set_type_load_failure (inst_klass, "Could not initialized generic type instance due to: %s", mono_error_get_message (error));
3821 // Marked the class with failure, but since some other instantiation already failed,
3822 // just report that one, and swallow the error from this one.
3823 if (already_failed)
3824 mono_error_cleanup (error);
3826 return TRUE;
3827 } else
3828 return FALSE;
3832 * reflection_setup_internal_class:
3833 * @tb: a TypeBuilder object
3834 * @error: set on error
3836 * Creates a MonoClass that represents the TypeBuilder.
3837 * This is a trick that lets us simplify a lot of reflection code
3838 * (and will allow us to support Build and Run assemblies easier).
3840 * Returns TRUE on success. On failure, returns FALSE and sets @error.
3842 static gboolean
3843 reflection_setup_internal_class (MonoReflectionTypeBuilderHandle ref_tb, MonoError *error)
3845 MonoReflectionModuleBuilderHandle module_ref = MONO_HANDLE_NEW_GET (MonoReflectionModuleBuilder, ref_tb, module);
3846 GHashTable *unparented_classes = MONO_HANDLE_GETVAL(module_ref, unparented_classes);
3848 if (unparented_classes) {
3849 return reflection_setup_internal_class_internal (ref_tb, error);
3850 } else {
3851 // If we're not being called recursively
3852 unparented_classes = g_hash_table_new (NULL, NULL);
3853 MONO_HANDLE_SETVAL (module_ref, unparented_classes, GHashTable *, unparented_classes);
3855 gboolean ret_val = reflection_setup_internal_class_internal (ref_tb, error);
3856 mono_error_assert_ok (error);
3858 // Fix the relationship between the created classes and their parents
3859 reflection_setup_class_hierarchy (unparented_classes, error);
3860 mono_error_assert_ok (error);
3862 g_hash_table_destroy (unparented_classes);
3863 MONO_HANDLE_SETVAL (module_ref, unparented_classes, GHashTable *, NULL);
3865 return ret_val;
3869 MonoReflectionTypeHandle
3870 ves_icall_TypeBuilder_create_runtime_class (MonoReflectionTypeBuilderHandle ref_tb, MonoError *error)
3872 error_init (error);
3874 reflection_setup_internal_class (ref_tb, error);
3875 mono_error_assert_ok (error);
3877 MonoDomain *domain = MONO_HANDLE_DOMAIN (ref_tb);
3878 MonoType *type = MONO_HANDLE_GETVAL (MONO_HANDLE_CAST (MonoReflectionType, ref_tb), type);
3879 MonoClass *klass = mono_class_from_mono_type_internal (type);
3881 MonoArrayHandle cattrs = MONO_HANDLE_NEW_GET (MonoArray, ref_tb, cattrs);
3882 mono_save_custom_attrs (klass->image, klass, MONO_HANDLE_RAW (cattrs)); /* FIXME use handles */
3885 * we need to lock the domain because the lock will be taken inside
3886 * So, we need to keep the locking order correct.
3888 mono_loader_lock ();
3889 mono_domain_lock (domain);
3890 if (klass->wastypebuilder) {
3891 mono_domain_unlock (domain);
3892 mono_loader_unlock ();
3894 return mono_type_get_object_handle (domain, m_class_get_byval_arg (klass), error);
3897 * Fields to set in klass:
3898 * the various flags: delegate/unicode/contextbound etc.
3900 mono_class_set_flags (klass, MONO_HANDLE_GETVAL (ref_tb, attrs));
3901 klass->has_cctor = 1;
3903 mono_class_setup_parent (klass, klass->parent);
3904 /* fool mono_class_setup_supertypes */
3905 klass->supertypes = NULL;
3906 mono_class_setup_supertypes (klass);
3907 mono_class_setup_mono_type (klass);
3909 /* enums are done right away */
3910 if (!klass->enumtype)
3911 if (!ensure_runtime_vtable (klass, error))
3912 goto failure;
3914 MonoArrayHandle nested_types;
3915 nested_types = MONO_HANDLE_NEW_GET (MonoArray, ref_tb, subtypes);
3916 if (!MONO_HANDLE_IS_NULL (nested_types)) {
3917 GList *nested = NULL;
3918 int num_nested = mono_array_handle_length (nested_types);
3919 MonoReflectionTypeHandle nested_tb = MONO_HANDLE_NEW (MonoReflectionType, NULL);
3920 for (int i = 0; i < num_nested; ++i) {
3921 MONO_HANDLE_ARRAY_GETREF (nested_tb, nested_types, i);
3923 if (MONO_HANDLE_GETVAL (nested_tb, type) == NULL) {
3924 reflection_setup_internal_class (MONO_HANDLE_CAST (MonoReflectionTypeBuilder, nested_tb), error);
3925 mono_error_assert_ok (error);
3928 MonoType *subtype = mono_reflection_type_handle_mono_type (nested_tb, error);
3929 goto_if_nok (error, failure);
3930 nested = mono_g_list_prepend_image (klass->image, nested, mono_class_from_mono_type_internal (subtype));
3932 mono_class_set_nested_classes_property (klass, nested);
3935 klass->nested_classes_inited = TRUE;
3937 typebuilder_setup_fields (klass, error);
3938 goto_if_nok (error, failure);
3939 typebuilder_setup_properties (klass, error);
3940 goto_if_nok (error, failure);
3942 typebuilder_setup_events (klass, error);
3943 goto_if_nok (error, failure);
3945 klass->wastypebuilder = TRUE;
3947 MonoArrayHandle generic_params;
3948 generic_params = MONO_HANDLE_NEW_GET (MonoArray, ref_tb, generic_params);
3949 if (!MONO_HANDLE_IS_NULL (generic_params)) {
3950 int num_params = mono_array_handle_length (generic_params);
3951 MonoReflectionTypeHandle ref_gparam = MONO_HANDLE_NEW (MonoReflectionType, NULL);
3952 for (int i = 0; i < num_params; i++) {
3953 MONO_HANDLE_ARRAY_GETREF (ref_gparam, generic_params, i);
3954 MonoType *param_type = mono_reflection_type_handle_mono_type (ref_gparam, error);
3955 goto_if_nok (error, failure);
3956 MonoClass *gklass = mono_class_from_mono_type_internal (param_type);
3958 gklass->wastypebuilder = TRUE;
3963 * If we are a generic TypeBuilder, there might be instantiations in the type cache
3964 * which have type System.Reflection.MonoGenericClass, but after the type is created,
3965 * we want to return normal System.MonoType objects, so clear these out from the cache.
3967 * Together with this we must ensure the contents of all instances to match the created type.
3969 if (domain->type_hash && mono_class_is_gtd (klass)) {
3970 struct remove_instantiations_user_data data;
3971 data.klass = klass;
3972 data.error = error;
3973 mono_error_assert_ok (error);
3974 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, &data);
3975 goto_if_nok (error, failure);
3978 mono_domain_unlock (domain);
3979 mono_loader_unlock ();
3981 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
3982 mono_class_set_type_load_failure (klass, "Not a valid enumeration");
3983 mono_error_set_type_load_class (error, klass, "Not a valid enumeration");
3984 goto failure_unlocked;
3987 MonoReflectionTypeHandle res;
3988 res = mono_type_get_object_handle (domain, m_class_get_byval_arg (klass), error);
3989 goto_if_nok (error, failure_unlocked);
3991 return res;
3993 failure:
3994 mono_class_set_type_load_failure (klass, "TypeBuilder could not create runtime class due to: %s", mono_error_get_message (error));
3995 klass->wastypebuilder = TRUE;
3996 mono_domain_unlock (domain);
3997 mono_loader_unlock ();
3998 failure_unlocked:
3999 return MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE);
4002 typedef struct {
4003 MonoMethod *handle;
4004 MonoDomain *domain;
4005 } DynamicMethodReleaseData;
4008 * The runtime automatically clean up those after finalization.
4010 static MonoReferenceQueue *dynamic_method_queue;
4012 static void
4013 free_dynamic_method (void *dynamic_method)
4015 DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
4016 MonoDomain *domain = data->domain;
4017 MonoMethod *method = data->handle;
4018 guint32 dis_link;
4020 mono_domain_lock (domain);
4021 dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
4022 g_hash_table_remove (domain->method_to_dyn_method, method);
4023 mono_domain_unlock (domain);
4024 g_assert (dis_link);
4025 mono_gchandle_free_internal (dis_link);
4027 mono_runtime_free_method (domain, method);
4028 g_free (data);
4031 static gboolean
4032 reflection_create_dynamic_method (MonoReflectionDynamicMethodHandle ref_mb, MonoError *error)
4034 MonoReferenceQueue *queue;
4035 MonoMethod *handle;
4036 DynamicMethodReleaseData *release_data;
4037 ReflectionMethodBuilder rmb;
4038 MonoMethodSignature *sig;
4039 MonoClass *klass;
4040 MonoDomain *domain;
4041 GSList *l;
4042 int i;
4044 error_init (error);
4046 if (mono_runtime_is_shutting_down ()) {
4047 mono_error_set_generic_error (error, "System", "InvalidOperationException", "");
4048 return FALSE;
4051 if (!(queue = dynamic_method_queue)) {
4052 mono_loader_lock ();
4053 if (!(queue = dynamic_method_queue))
4054 queue = dynamic_method_queue = mono_gc_reference_queue_new_internal (free_dynamic_method);
4055 mono_loader_unlock ();
4058 sig = dynamic_method_to_signature (ref_mb, error);
4059 return_val_if_nok (error, FALSE);
4061 MonoReflectionDynamicMethod *mb = MONO_HANDLE_RAW (ref_mb); /* FIXME convert reflection_create_dynamic_method to use handles */
4062 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
4065 * Resolve references.
4068 * Every second entry in the refs array is reserved for storing handle_class,
4069 * which is needed by the ldtoken implementation in the JIT.
4071 rmb.nrefs = mb->nrefs;
4072 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
4073 for (i = 0; i < mb->nrefs; i += 2) {
4074 MonoClass *handle_class;
4075 gpointer ref;
4076 MonoObject *obj = mono_array_get_internal (mb->refs, MonoObject*, i);
4078 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
4079 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
4081 * The referenced DynamicMethod should already be created by the managed
4082 * code, except in the case of circular references. In that case, we store
4083 * method in the refs array, and fix it up later when the referenced
4084 * DynamicMethod is created.
4086 if (method->mhandle) {
4087 ref = method->mhandle;
4088 } else {
4089 /* FIXME: GC object stored in unmanaged memory */
4090 ref = method;
4092 /* FIXME: GC object stored in unmanaged memory */
4093 method->referenced_by = g_slist_append (method->referenced_by, mb);
4095 handle_class = mono_defaults.methodhandle_class;
4096 } else {
4097 MonoException *ex = NULL;
4098 ref = mono_reflection_resolve_object (mb->module->image, obj, &handle_class, NULL, error);
4099 if (!is_ok (error)) {
4100 g_free (rmb.refs);
4101 return FALSE;
4103 if (!ref)
4104 ex = mono_get_exception_type_load (NULL, NULL);
4105 else if (mono_security_core_clr_enabled ())
4106 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
4108 if (ex) {
4109 g_free (rmb.refs);
4110 mono_error_set_exception_instance (error, ex);
4111 return FALSE;
4115 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
4116 rmb.refs [i + 1] = handle_class;
4119 MonoAssembly *ass = NULL;
4120 if (mb->owner) {
4121 MonoType *owner_type = mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner, error);
4122 if (!is_ok (error)) {
4123 g_free (rmb.refs);
4124 return FALSE;
4126 klass = mono_class_from_mono_type_internal (owner_type);
4127 ass = klass->image->assembly;
4128 } else {
4129 klass = mono_defaults.object_class;
4130 ass = (mb->module && mb->module->image) ? mb->module->image->assembly : NULL;
4133 mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
4134 ((MonoDynamicMethod*)handle)->assembly = ass;
4135 g_free (rmb.refs);
4136 return_val_if_nok (error, FALSE);
4138 release_data = g_new (DynamicMethodReleaseData, 1);
4139 release_data->handle = handle;
4140 release_data->domain = mono_object_get_domain_internal ((MonoObject*)mb);
4141 if (!mono_gc_reference_queue_add_internal (queue, (MonoObject*)mb, release_data))
4142 g_free (release_data);
4144 /* Fix up refs entries pointing at us */
4145 for (l = mb->referenced_by; l; l = l->next) {
4146 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
4147 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
4148 gpointer *data;
4150 g_assert (method->mhandle);
4152 data = (gpointer*)wrapper->method_data;
4153 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
4154 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
4155 data [i + 1] = mb->mhandle;
4158 g_slist_free (mb->referenced_by);
4160 /* ilgen is no longer needed */
4161 mb->ilgen = NULL;
4163 domain = mono_domain_get ();
4164 mono_domain_lock (domain);
4165 if (!domain->method_to_dyn_method)
4166 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
4167 g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref_internal ((MonoObject *)mb, TRUE));
4168 mono_domain_unlock (domain);
4170 return TRUE;
4173 void
4174 ves_icall_DynamicMethod_create_dynamic_method (MonoReflectionDynamicMethodHandle mb, MonoError *error)
4176 (void) reflection_create_dynamic_method (mb, error);
4179 #endif /* DISABLE_REFLECTION_EMIT */
4181 MonoMethodSignature *
4182 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
4184 MonoMethodSignature *sig;
4185 g_assert (image_is_dynamic (image));
4187 error_init (error);
4189 sig = (MonoMethodSignature *)g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
4190 if (sig)
4191 return sig;
4193 return mono_method_signature_checked (method, error);
4196 #ifndef DISABLE_REFLECTION_EMIT
4199 * ensure_complete_type:
4201 * Ensure that KLASS is completed if it is a dynamic type, or references
4202 * dynamic types.
4204 static void
4205 ensure_complete_type (MonoClass *klass, MonoError *error)
4207 HANDLE_FUNCTION_ENTER ();
4209 error_init (error);
4211 if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_has_ref_info (klass)) {
4212 MonoReflectionTypeBuilderHandle tb = mono_class_get_ref_info (klass);
4214 mono_domain_try_type_resolve_typebuilder (mono_domain_get (), tb, error);
4215 goto_if_nok (error, exit);
4217 // Asserting here could break a lot of code
4218 //g_assert (klass->wastypebuilder);
4221 if (mono_class_is_ginst (klass)) {
4222 MonoGenericInst *inst = mono_class_get_generic_class (klass)->context.class_inst;
4223 int i;
4225 for (i = 0; i < inst->type_argc; ++i) {
4226 ensure_complete_type (mono_class_from_mono_type_internal (inst->type_argv [i]), error);
4227 goto_if_nok (error, exit);
4231 exit:
4232 HANDLE_FUNCTION_RETURN ();
4235 gpointer
4236 mono_reflection_resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
4238 HANDLE_FUNCTION_ENTER ();
4240 MonoClass *oklass = obj->vtable->klass;
4241 gpointer result = NULL;
4243 error_init (error);
4245 if (strcmp (oklass->name, "String") == 0) {
4246 result = MONO_HANDLE_RAW (mono_string_intern_checked (MONO_HANDLE_NEW (MonoString, (MonoString*)obj), error));
4247 goto_if_nok (error, return_null);
4248 *handle_class = mono_defaults.string_class;
4249 g_assert (result);
4250 } else if (strcmp (oklass->name, "RuntimeType") == 0) {
4251 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
4252 goto_if_nok (error, return_null);
4253 MonoClass *mc = mono_class_from_mono_type_internal (type);
4254 if (!mono_class_init_internal (mc)) {
4255 mono_error_set_for_class_failure (error, mc);
4256 goto return_null;
4259 if (context) {
4260 MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, error);
4261 goto_if_nok (error, return_null);
4263 result = mono_class_from_mono_type_internal (inflated);
4264 mono_metadata_free_type (inflated);
4265 } else {
4266 result = mono_class_from_mono_type_internal (type);
4268 *handle_class = mono_defaults.typehandle_class;
4269 g_assert (result);
4270 } else if (strcmp (oklass->name, "RuntimeMethodInfo") == 0 ||
4271 strcmp (oklass->name, "RuntimeConstructorInfo") == 0) {
4272 result = ((MonoReflectionMethod*)obj)->method;
4273 if (context) {
4274 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
4275 mono_error_assert_ok (error);
4277 *handle_class = mono_defaults.methodhandle_class;
4278 g_assert (result);
4279 } else if (strcmp (oklass->name, "RuntimeFieldInfo") == 0) {
4280 MonoClassField *field = ((MonoReflectionField*)obj)->field;
4282 ensure_complete_type (field->parent, error);
4283 goto_if_nok (error, return_null);
4285 if (context) {
4286 MonoType *inflated = mono_class_inflate_generic_type_checked (m_class_get_byval_arg (field->parent), context, error);
4287 goto_if_nok (error, return_null);
4289 MonoClass *klass;
4290 klass = mono_class_from_mono_type_internal (inflated);
4291 MonoClassField *inflated_field;
4292 gpointer iter = NULL;
4293 mono_metadata_free_type (inflated);
4294 while ((inflated_field = mono_class_get_fields_internal (klass, &iter))) {
4295 if (!strcmp (field->name, inflated_field->name))
4296 break;
4298 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
4299 result = inflated_field;
4300 } else {
4301 result = field;
4303 *handle_class = mono_defaults.fieldhandle_class;
4304 g_assert (result);
4305 } else if (strcmp (oklass->name, "TypeBuilder") == 0) {
4306 MonoReflectionTypeBuilderHandle tb = MONO_HANDLE_NEW (MonoReflectionTypeBuilder, (MonoReflectionTypeBuilder*)obj);
4307 MonoType *type = mono_reflection_type_get_handle (&MONO_HANDLE_RAW (tb)->type, error);
4308 goto_if_nok (error, return_null);
4309 MonoClass *klass;
4311 klass = type->data.klass;
4312 if (klass->wastypebuilder) {
4313 /* Already created */
4314 result = klass;
4316 else {
4317 mono_domain_try_type_resolve_typebuilder (mono_domain_get (), tb, error);
4318 goto_if_nok (error, return_null);
4319 result = type->data.klass;
4320 g_assert (result);
4322 *handle_class = mono_defaults.typehandle_class;
4323 } else if (strcmp (oklass->name, "SignatureHelper") == 0) {
4324 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
4325 MonoMethodSignature *sig;
4326 int nargs, i;
4328 if (helper->arguments)
4329 nargs = mono_array_length_internal (helper->arguments);
4330 else
4331 nargs = 0;
4333 sig = mono_metadata_signature_alloc (image, nargs);
4334 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
4335 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
4337 if (helper->unmanaged_call_conv) { /* unmanaged */
4338 sig->call_convention = helper->unmanaged_call_conv - 1;
4339 sig->pinvoke = TRUE;
4340 } else if (helper->call_conv & 0x02) {
4341 sig->call_convention = MONO_CALL_VARARG;
4342 } else {
4343 sig->call_convention = MONO_CALL_DEFAULT;
4346 sig->param_count = nargs;
4347 /* TODO: Copy type ? */
4348 sig->ret = helper->return_type->type;
4349 for (i = 0; i < nargs; ++i) {
4350 sig->params [i] = mono_type_array_get_and_resolve_raw (helper->arguments, i, error); /* FIXME use handles */
4351 if (!is_ok (error)) {
4352 image_g_free (image, sig);
4353 goto return_null;
4357 result = sig;
4358 *handle_class = NULL;
4359 } else if (strcmp (oklass->name, "DynamicMethod") == 0) {
4360 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
4361 /* Already created by the managed code */
4362 g_assert (method->mhandle);
4363 result = method->mhandle;
4364 *handle_class = mono_defaults.methodhandle_class;
4365 } else if (strcmp (oklass->name, "MonoArrayMethod") == 0) {
4366 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
4367 MonoType *mtype;
4368 MonoClass *klass;
4369 MonoMethod *method;
4370 gpointer iter;
4371 char *name;
4373 mtype = mono_reflection_type_get_handle (m->parent, error);
4374 goto_if_nok (error, return_null);
4375 klass = mono_class_from_mono_type_internal (mtype);
4377 /* Find the method */
4379 name = mono_string_to_utf8_checked_internal (m->name, error);
4380 goto_if_nok (error, return_null);
4381 iter = NULL;
4382 while ((method = mono_class_get_methods (klass, &iter))) {
4383 if (!strcmp (method->name, name))
4384 break;
4386 g_free (name);
4388 // FIXME:
4389 g_assert (method);
4390 // FIXME: Check parameters/return value etc. match
4392 result = method;
4393 *handle_class = mono_defaults.methodhandle_class;
4394 } else if (is_sre_method_builder (oklass) ||
4395 mono_is_sre_ctor_builder (oklass) ||
4396 is_sre_field_builder (oklass) ||
4397 is_sre_gparam_builder (oklass) ||
4398 is_sre_generic_instance (oklass) ||
4399 is_sre_array (oklass) ||
4400 is_sre_byref (oklass) ||
4401 is_sre_pointer (oklass) ||
4402 !strcmp (oklass->name, "FieldOnTypeBuilderInst") ||
4403 !strcmp (oklass->name, "MethodOnTypeBuilderInst") ||
4404 !strcmp (oklass->name, "ConstructorOnTypeBuilderInst")) {
4405 static MonoMethod *resolve_method;
4406 if (!resolve_method) {
4407 MonoMethod *m = mono_class_get_method_from_name_checked (mono_class_get_module_builder_class (), "RuntimeResolve", 1, 0, error);
4408 mono_error_assert_ok (error);
4409 g_assert (m);
4410 mono_memory_barrier ();
4411 resolve_method = m;
4413 void *args [16];
4414 args [0] = obj;
4415 obj = mono_runtime_invoke_checked (resolve_method, NULL, args, error);
4416 goto_if_nok (error, return_null);
4417 g_assert (obj);
4418 result = mono_reflection_resolve_object (image, obj, handle_class, context, error);
4419 goto exit;
4420 } else {
4421 g_print ("%s\n", obj->vtable->klass->name);
4422 g_assert_not_reached ();
4425 goto exit;
4426 return_null:
4427 result = NULL;
4428 goto exit;
4429 exit:
4430 HANDLE_FUNCTION_RETURN_VAL (result);
4433 gpointer
4434 mono_reflection_resolve_object_handle (MonoImage *image, MonoObjectHandle obj, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
4436 return mono_reflection_resolve_object (image, MONO_HANDLE_RAW (obj), handle_class, context, error);
4439 #else /* DISABLE_REFLECTION_EMIT */
4441 MonoArray*
4442 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
4444 g_assert_not_reached ();
4445 return NULL;
4448 void
4449 mono_reflection_dynimage_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4451 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
4454 static gboolean
4455 mono_image_module_basic_init (MonoReflectionModuleBuilderHandle moduleb, MonoError *error)
4457 g_assert_not_reached ();
4458 return FALSE;
4461 guint32
4462 mono_image_insert_string (MonoReflectionModuleBuilderHandle module, MonoStringHandle str, MonoError *error)
4464 g_assert_not_reached ();
4465 return 0;
4468 guint32
4469 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObjectHandle obj, MonoArrayHandle opt_param_types, MonoError *error)
4471 g_assert_not_reached ();
4472 return 0;
4475 guint32
4476 mono_image_create_token (MonoDynamicImage *assembly, MonoObjectHandle obj,
4477 gboolean create_open_instance, gboolean register_token, MonoError *error)
4479 g_assert_not_reached ();
4480 return 0;
4483 void
4484 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides, MonoError *error)
4486 error_init (error);
4487 *overrides = NULL;
4488 *num_overrides = 0;
4491 MonoReflectionTypeHandle
4492 ves_icall_TypeBuilder_create_runtime_class (MonoReflectionTypeBuilderHandle tb, MonoError *error)
4494 g_assert_not_reached ();
4495 return MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE);
4498 void
4499 ves_icall_DynamicMethod_create_dynamic_method (MonoReflectionDynamicMethodHandle mb, MonoError *error)
4501 error_init (error);
4504 MonoType*
4505 mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
4507 error_init (error);
4508 if (!ref)
4509 return NULL;
4510 return ref->type;
4513 MonoType*
4514 mono_reflection_type_handle_mono_type (MonoReflectionTypeHandle ref, MonoError *error)
4516 error_init (error);
4517 if (MONO_HANDLE_IS_NULL (ref))
4518 return NULL;
4519 return MONO_HANDLE_GETVAL (ref, type);
4523 #endif /* DISABLE_REFLECTION_EMIT */
4525 void
4526 mono_sre_generic_param_table_entry_free (GenericParamTableEntry *entry)
4528 MONO_GC_UNREGISTER_ROOT_IF_MOVING (entry->gparam);
4529 g_free (entry);
4532 gint32
4533 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilderHandle mb, MonoObjectHandle obj, MonoBoolean create_open_instance, MonoError *error)
4535 error_init (error);
4536 if (MONO_HANDLE_IS_NULL (obj)) {
4537 mono_error_set_argument_null (error, "obj", "");
4538 return 0;
4540 return mono_image_create_token (MONO_HANDLE_GETVAL (mb, dynamic_image), obj, create_open_instance, TRUE, error);
4543 gint32
4544 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilderHandle mb,
4545 MonoReflectionMethodHandle method,
4546 MonoArrayHandle opt_param_types,
4547 MonoError *error)
4549 error_init (error);
4550 if (MONO_HANDLE_IS_NULL (method)) {
4551 mono_error_set_argument_null (error, "method", "");
4552 return 0;
4555 return mono_image_create_method_token (MONO_HANDLE_GETVAL (mb, dynamic_image), MONO_HANDLE_CAST (MonoObject, method), opt_param_types, error);
4558 void
4559 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
4561 ERROR_DECL (error);
4562 mono_image_create_pefile (mb, file, error);
4563 mono_error_set_pending_exception (error);
4566 void
4567 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
4569 ERROR_DECL (error);
4570 mono_image_build_metadata (mb, error);
4571 mono_error_set_pending_exception (error);
4574 void
4575 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilderHandle mb, MonoObjectHandle obj, guint32 token, MonoError *error)
4577 error_init (error);
4578 /* This function may be called by ModuleBuilder.FixupTokens to update
4579 * an existing token, so replace is okay here. */
4580 mono_dynamic_image_register_token (MONO_HANDLE_GETVAL (mb, dynamic_image), token, obj, MONO_DYN_IMAGE_TOK_REPLACE);
4583 MonoObjectHandle
4584 ves_icall_ModuleBuilder_GetRegisteredToken (MonoReflectionModuleBuilderHandle mb, guint32 token, MonoError *error)
4586 MonoDynamicImage *dynamic_image = MONO_HANDLE_GETVAL (mb, dynamic_image);
4587 return mono_dynamic_image_get_registered_token (dynamic_image, token, error);
4590 #ifndef DISABLE_REFLECTION_EMIT
4591 MonoArray*
4592 ves_icall_CustomAttributeBuilder_GetBlob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
4594 ERROR_DECL (error);
4595 MonoArray *result = mono_reflection_get_custom_attrs_blob_checked (assembly, ctor, ctorArgs, properties, propValues, fields, fieldValues, error);
4596 mono_error_set_pending_exception (error);
4597 return result;
4599 #endif
4601 void
4602 ves_icall_AssemblyBuilder_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4604 mono_reflection_dynimage_basic_init (assemblyb);
4607 void
4608 ves_icall_AssemblyBuilder_UpdateNativeCustomAttributes (MonoReflectionAssemblyBuilderHandle assemblyb, MonoError *error)
4610 MonoArrayHandle cattrs = MONO_HANDLE_NEW_GET (MonoArray, assemblyb, cattrs);
4612 MonoReflectionAssemblyHandle assembly_handle = MONO_HANDLE_CAST (MonoReflectionAssembly, assemblyb);
4613 MonoAssembly *assembly = MONO_HANDLE_GETVAL (assembly_handle, assembly);
4614 g_assert (assembly);
4616 mono_save_custom_attrs (assembly->image, assembly, MONO_HANDLE_RAW (cattrs));
4619 void
4620 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionTypeHandle enumtype,
4621 MonoReflectionTypeHandle t,
4622 MonoError *error)
4624 error_init (error);
4625 MONO_HANDLE_SETVAL (enumtype, type, MonoType*, MONO_HANDLE_GETVAL (t, type));
4628 void
4629 ves_icall_ModuleBuilder_basic_init (MonoReflectionModuleBuilderHandle moduleb, MonoError *error)
4631 error_init (error);
4632 mono_image_module_basic_init (moduleb, error);
4635 guint32
4636 ves_icall_ModuleBuilder_getUSIndex (MonoReflectionModuleBuilderHandle module, MonoStringHandle str, MonoError *error)
4638 return mono_image_insert_string (module, str, error);
4641 void
4642 ves_icall_ModuleBuilder_set_wrappers_type (MonoReflectionModuleBuilderHandle moduleb, MonoReflectionTypeHandle ref_type, MonoError *error)
4644 error_init (error);
4645 MonoDynamicImage *image = MONO_HANDLE_GETVAL (moduleb, dynamic_image);
4646 MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
4648 g_assert (type);
4649 image->wrappers_type = mono_class_from_mono_type_internal (type);