[cxx] Fix WebAssembly/C++ (ICALL_EXPORT) (#11359)
[mono-project.git] / mono / metadata / sre.c
blob3d6a0571a4d26228da3a705888786761d627c71d
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
50 static GENERATE_GET_CLASS_WITH_CACHE (marshal_as_attribute, "System.Runtime.InteropServices", "MarshalAsAttribute");
51 static GENERATE_GET_CLASS_WITH_CACHE (module_builder, "System.Reflection.Emit", "ModuleBuilder");
53 static char* string_to_utf8_image_raw (MonoImage *image, MonoString *s, MonoError *error);
55 #ifndef DISABLE_REFLECTION_EMIT
56 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelperHandle helper, MonoError *error);
57 static gboolean ensure_runtime_vtable (MonoClass *klass, MonoError *error);
58 static void reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb);
59 static gboolean reflection_setup_internal_class (MonoReflectionTypeBuilderHandle tb, MonoError *error);
60 static gboolean reflection_init_generic_class (MonoReflectionTypeBuilderHandle tb, MonoError *error);
61 static gboolean reflection_setup_class_hierarchy (GHashTable *unparented, MonoError *error);
64 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
65 #endif
67 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
68 static MonoReflectionTypeHandle mono_reflection_type_get_underlying_system_type (MonoReflectionTypeHandle t, MonoError *error);
69 static gboolean is_sre_array (MonoClass *klass);
70 static gboolean is_sre_byref (MonoClass *klass);
71 static gboolean is_sre_pointer (MonoClass *klass);
72 static gboolean is_sre_generic_instance (MonoClass *klass);
73 static gboolean is_sre_type_builder (MonoClass *klass);
74 static gboolean is_sre_method_builder (MonoClass *klass);
75 static gboolean is_sre_field_builder (MonoClass *klass);
76 static gboolean is_sre_gparam_builder (MonoClass *klass);
77 static gboolean is_sre_enum_builder (MonoClass *klass);
78 static gboolean is_sr_mono_method (MonoClass *klass);
79 static gboolean is_sr_mono_field (MonoClass *klass);
81 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
82 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
83 static guint32 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObjectHandle obj, MonoArrayHandle opt_param_types, MonoError *error);
86 #ifndef DISABLE_REFLECTION_EMIT
87 static MonoType* mono_type_array_get_and_resolve_raw (MonoArray* array, int idx, MonoError* error);
88 #endif
90 static gboolean mono_image_module_basic_init (MonoReflectionModuleBuilderHandle module, MonoError *error);
92 void
93 mono_reflection_emit_init (void)
95 mono_dynamic_images_init ();
98 char*
99 string_to_utf8_image_raw (MonoImage *image, MonoString *s_raw, MonoError *error)
101 /* FIXME all callers to string_to_utf8_image_raw should use handles */
102 HANDLE_FUNCTION_ENTER ();
103 char* result = NULL;
104 error_init (error);
105 MONO_HANDLE_DCL (MonoString, s);
106 result = mono_string_to_utf8_image (image, s, error);
107 HANDLE_FUNCTION_RETURN_VAL (result);
110 static char*
111 type_get_fully_qualified_name (MonoType *type)
113 MONO_REQ_GC_NEUTRAL_MODE;
115 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
118 static char*
119 type_get_qualified_name (MonoType *type, MonoAssembly *ass)
121 MONO_REQ_GC_UNSAFE_MODE;
123 MonoClass *klass;
124 MonoAssembly *ta;
126 klass = mono_class_from_mono_type_internal (type);
127 if (!klass)
128 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
129 ta = klass->image->assembly;
130 if (assembly_is_dynamic (ta) || (ta == ass)) {
131 if (mono_class_is_ginst (klass) || mono_class_is_gtd (klass))
132 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
133 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
134 else
135 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
138 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
141 #ifndef DISABLE_REFLECTION_EMIT
143 * mp_g_alloc:
145 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
146 * from the C heap.
148 static gpointer
149 image_g_malloc (MonoImage *image, guint size)
151 MONO_REQ_GC_NEUTRAL_MODE;
153 if (image)
154 return mono_image_alloc (image, size);
155 else
156 return g_malloc (size);
158 #endif /* !DISABLE_REFLECTION_EMIT */
161 * image_g_alloc0:
163 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
164 * from the C heap.
166 gpointer
167 (mono_image_g_malloc0) (MonoImage *image, guint size)
169 MONO_REQ_GC_NEUTRAL_MODE;
171 if (image)
172 return mono_image_alloc0 (image, size);
173 else
174 return g_malloc0 (size);
178 * image_g_free:
179 * @image: a MonoImage
180 * @ptr: pointer
182 * If @image is NULL, free @ptr, otherwise do nothing.
184 static void
185 image_g_free (MonoImage *image, gpointer ptr)
187 if (image == NULL)
188 g_free (ptr);
191 #ifndef DISABLE_REFLECTION_EMIT
192 static char*
193 image_strdup (MonoImage *image, const char *s)
195 MONO_REQ_GC_NEUTRAL_MODE;
197 if (image)
198 return mono_image_strdup (image, s);
199 else
200 return g_strdup (s);
202 #endif
204 #define image_g_new(image,struct_type, n_structs) \
205 ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
207 #define image_g_new0(image,struct_type, n_structs) \
208 ((struct_type *) mono_image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
211 static void
212 alloc_table (MonoDynamicTable *table, guint nrows)
214 mono_dynimage_alloc_table (table, nrows);
217 static guint32
218 string_heap_insert (MonoDynamicStream *sh, const char *str)
220 return mono_dynstream_insert_string (sh, str);
223 static guint32
224 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
226 return mono_dynstream_add_data (stream, data, len);
230 * Despite the name, we handle also TypeSpec (with the above helper).
232 static guint32
233 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
235 return mono_dynimage_encode_typedef_or_ref_full (assembly, type, TRUE);
239 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
240 * dest may be misaligned.
242 static void
243 swap_with_size (gpointer void_dest, gconstpointer void_val, int len, int nelem)
245 char *dest = (char*)void_dest;
246 const char* val = (const char*)void_val;
247 MONO_REQ_GC_NEUTRAL_MODE;
248 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
249 int elem;
251 for (elem = 0; elem < nelem; ++elem) {
252 switch (len) {
253 case 1:
254 *dest = *val;
255 break;
256 case 2:
257 dest [0] = val [1];
258 dest [1] = val [0];
259 break;
260 case 4:
261 dest [0] = val [3];
262 dest [1] = val [2];
263 dest [2] = val [1];
264 dest [3] = val [0];
265 break;
266 case 8:
267 dest [0] = val [7];
268 dest [1] = val [6];
269 dest [2] = val [5];
270 dest [3] = val [4];
271 dest [4] = val [3];
272 dest [5] = val [2];
273 dest [6] = val [1];
274 dest [7] = val [0];
275 break;
276 default:
277 g_assert_not_reached ();
279 dest += len;
280 val += len;
282 #else
283 memcpy (dest, val, len * nelem);
284 #endif
287 guint32
288 mono_reflection_method_count_clauses (MonoReflectionILGen *ilgen)
290 MONO_REQ_GC_UNSAFE_MODE;
292 guint32 num_clauses = 0;
293 int i;
295 MonoILExceptionInfo *ex_info;
296 for (i = 0; i < mono_array_length_internal (ilgen->ex_handlers); ++i) {
297 ex_info = (MonoILExceptionInfo*)mono_array_addr_internal (ilgen->ex_handlers, MonoILExceptionInfo, i);
298 if (ex_info->handlers)
299 num_clauses += mono_array_length_internal (ex_info->handlers);
300 else
301 num_clauses++;
304 return num_clauses;
307 #ifndef DISABLE_REFLECTION_EMIT
308 static MonoExceptionClause*
309 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses, MonoError *error)
311 MONO_REQ_GC_UNSAFE_MODE;
313 error_init (error);
315 MonoExceptionClause *clauses;
316 MonoExceptionClause *clause;
317 MonoILExceptionInfo *ex_info;
318 MonoILExceptionBlock *ex_block;
319 guint32 finally_start;
320 int i, j, clause_index;;
322 clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
324 clause_index = 0;
325 for (i = mono_array_length_internal (ilgen->ex_handlers) - 1; i >= 0; --i) {
326 ex_info = (MonoILExceptionInfo*)mono_array_addr_internal (ilgen->ex_handlers, MonoILExceptionInfo, i);
327 finally_start = ex_info->start + ex_info->len;
328 if (!ex_info->handlers)
329 continue;
330 for (j = 0; j < mono_array_length_internal (ex_info->handlers); ++j) {
331 ex_block = (MonoILExceptionBlock*)mono_array_addr_internal (ex_info->handlers, MonoILExceptionBlock, j);
332 clause = &(clauses [clause_index]);
334 clause->flags = ex_block->type;
335 clause->try_offset = ex_info->start;
337 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
338 clause->try_len = finally_start - ex_info->start;
339 else
340 clause->try_len = ex_info->len;
341 clause->handler_offset = ex_block->start;
342 clause->handler_len = ex_block->len;
343 if (ex_block->extype) {
344 MonoType *extype = mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype, error);
346 if (!is_ok (error)) {
347 image_g_free (image, clauses);
348 return NULL;
350 clause->data.catch_class = mono_class_from_mono_type_internal (extype);
351 } else {
352 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
353 clause->data.filter_offset = ex_block->filter_offset;
354 else
355 clause->data.filter_offset = 0;
357 finally_start = ex_block->start + ex_block->len;
359 clause_index ++;
363 return clauses;
365 #endif /* !DISABLE_REFLECTION_EMIT */
367 #ifndef DISABLE_REFLECTION_EMIT
369 * LOCKING: Acquires the loader lock.
371 static void
372 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
374 MONO_REQ_GC_UNSAFE_MODE;
376 MonoCustomAttrInfo *ainfo, *tmp;
378 if (!cattrs || !mono_array_length_internal (cattrs))
379 return;
381 ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
383 mono_loader_lock ();
384 tmp = (MonoCustomAttrInfo *)mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
385 if (tmp)
386 mono_custom_attrs_free (tmp);
387 mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
388 mono_loader_unlock ();
391 #else
392 //FIXME some code compiled under DISABLE_REFLECTION_EMIT depends on this function, we should be more aggressively disabling things
393 static void
394 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
397 #endif
399 guint32
400 mono_reflection_resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
402 MONO_REQ_GC_UNSAFE_MODE;
404 MonoDynamicTable *table;
405 guint32 token;
406 guint32 *values;
407 guint32 cols [MONO_ASSEMBLY_SIZE];
408 const char *pubkey;
409 guint32 publen;
411 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
412 return token;
414 if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
415 table = &assembly->tables [MONO_TABLE_MODULEREF];
416 token = table->next_idx ++;
417 table->rows ++;
418 alloc_table (table, table->rows);
419 values = table->values + token * MONO_MODULEREF_SIZE;
420 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
422 token <<= MONO_RESOLUTION_SCOPE_BITS;
423 token |= MONO_RESOLUTION_SCOPE_MODULEREF;
424 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
426 return token;
429 if (assembly_is_dynamic (image->assembly))
430 /* FIXME: */
431 memset (cols, 0, sizeof (cols));
432 else {
433 /* image->assembly->image is the manifest module */
434 image = image->assembly->image;
435 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
438 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
439 token = table->next_idx ++;
440 table->rows ++;
441 alloc_table (table, table->rows);
442 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
443 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
444 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
445 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
446 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
447 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
448 values [MONO_ASSEMBLYREF_FLAGS] = 0;
449 values [MONO_ASSEMBLYREF_CULTURE] = 0;
450 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
452 if (strcmp ("", image->assembly->aname.culture)) {
453 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
454 image->assembly->aname.culture);
457 if ((pubkey = mono_image_get_public_key (image, &publen))) {
458 guchar pubtoken [9];
459 pubtoken [0] = 8;
460 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
461 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
462 } else {
463 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
465 token <<= MONO_RESOLUTION_SCOPE_BITS;
466 token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
467 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
468 return token;
471 #ifndef DISABLE_REFLECTION_EMIT
472 gboolean
473 mono_reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error)
475 MONO_REQ_GC_UNSAFE_MODE;
477 error_init (error);
478 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
480 rmb->ilgen = mb->ilgen;
481 rmb->rtype = (MonoReflectionType*)mb->rtype;
482 return_val_if_nok (error, FALSE);
483 rmb->parameters = mb->parameters;
484 rmb->generic_params = mb->generic_params;
485 rmb->generic_container = mb->generic_container;
486 rmb->opt_types = NULL;
487 rmb->pinfo = mb->pinfo;
488 rmb->attrs = mb->attrs;
489 rmb->iattrs = mb->iattrs;
490 rmb->call_conv = mb->call_conv;
491 rmb->code = mb->code;
492 rmb->type = mb->type;
493 rmb->name = mb->name;
494 rmb->table_idx = &mb->table_idx;
495 rmb->init_locals = mb->init_locals;
496 rmb->skip_visibility = FALSE;
497 rmb->return_modreq = mb->return_modreq;
498 rmb->return_modopt = mb->return_modopt;
499 rmb->param_modreq = mb->param_modreq;
500 rmb->param_modopt = mb->param_modopt;
501 rmb->permissions = mb->permissions;
502 rmb->mhandle = mb->mhandle;
503 rmb->nrefs = 0;
504 rmb->refs = NULL;
506 if (mb->dll) {
507 rmb->charset = mb->charset;
508 rmb->extra_flags = mb->extra_flags;
509 rmb->native_cc = mb->native_cc;
510 rmb->dllentry = mb->dllentry;
511 rmb->dll = mb->dll;
514 return TRUE;
517 gboolean
518 mono_reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error)
520 MONO_REQ_GC_UNSAFE_MODE;
522 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
524 error_init (error);
526 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
528 rmb->ilgen = mb->ilgen;
529 rmb->rtype = mono_type_get_object_checked (mono_domain_get (), mono_get_void_type (), error);
530 return_val_if_nok (error, FALSE);
531 rmb->parameters = mb->parameters;
532 rmb->generic_params = NULL;
533 rmb->generic_container = NULL;
534 rmb->opt_types = NULL;
535 rmb->pinfo = mb->pinfo;
536 rmb->attrs = mb->attrs;
537 rmb->iattrs = mb->iattrs;
538 rmb->call_conv = mb->call_conv;
539 rmb->code = NULL;
540 rmb->type = mb->type;
541 rmb->name = mono_string_new_checked (mono_domain_get (), name, error);
542 return_val_if_nok (error, FALSE);
543 rmb->table_idx = &mb->table_idx;
544 rmb->init_locals = mb->init_locals;
545 rmb->skip_visibility = FALSE;
546 rmb->return_modreq = NULL;
547 rmb->return_modopt = NULL;
548 rmb->param_modreq = mb->param_modreq;
549 rmb->param_modopt = mb->param_modopt;
550 rmb->permissions = mb->permissions;
551 rmb->mhandle = mb->mhandle;
552 rmb->nrefs = 0;
553 rmb->refs = NULL;
555 return TRUE;
558 static void
559 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
561 MONO_REQ_GC_UNSAFE_MODE;
563 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
565 rmb->ilgen = mb->ilgen;
566 rmb->rtype = mb->rtype;
567 rmb->parameters = mb->parameters;
568 rmb->generic_params = NULL;
569 rmb->generic_container = NULL;
570 rmb->opt_types = NULL;
571 rmb->pinfo = NULL;
572 rmb->attrs = mb->attrs;
573 rmb->iattrs = 0;
574 rmb->call_conv = mb->call_conv;
575 rmb->code = NULL;
576 rmb->type = (MonoObject *) mb->owner;
577 rmb->name = mb->name;
578 rmb->table_idx = NULL;
579 rmb->init_locals = mb->init_locals;
580 rmb->skip_visibility = mb->skip_visibility;
581 rmb->return_modreq = NULL;
582 rmb->return_modopt = NULL;
583 rmb->param_modreq = NULL;
584 rmb->param_modopt = NULL;
585 rmb->permissions = NULL;
586 rmb->mhandle = mb->mhandle;
587 rmb->nrefs = 0;
588 rmb->refs = NULL;
590 #else /* DISABLE_REFLECTION_EMIT */
591 gboolean
592 mono_reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error) {
593 g_assert_not_reached ();
594 return FALSE;
596 gboolean
597 mono_reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error)
599 g_assert_not_reached ();
600 return FALSE;
602 #endif /* DISABLE_REFLECTION_EMIT */
604 #ifndef DISABLE_REFLECTION_EMIT
605 static guint32
606 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
608 MONO_REQ_GC_NEUTRAL_MODE;
610 MonoDynamicTable *table;
611 guint32 *values;
612 guint32 token, pclass;
614 switch (parent & MONO_TYPEDEFORREF_MASK) {
615 case MONO_TYPEDEFORREF_TYPEREF:
616 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
617 break;
618 case MONO_TYPEDEFORREF_TYPESPEC:
619 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
620 break;
621 case MONO_TYPEDEFORREF_TYPEDEF:
622 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
623 break;
624 default:
625 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
626 return 0;
628 /* extract the index */
629 parent >>= MONO_TYPEDEFORREF_BITS;
631 table = &assembly->tables [MONO_TABLE_MEMBERREF];
633 if (assembly->save) {
634 alloc_table (table, table->rows + 1);
635 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
636 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
637 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
638 values [MONO_MEMBERREF_SIGNATURE] = sig;
641 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
642 table->next_idx ++;
644 return token;
648 * Insert a memberef row into the metadata: the token that point to the memberref
649 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
650 * mono_image_get_fieldref_token()).
651 * The sig param is an index to an already built signature.
653 static guint32
654 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
656 MONO_REQ_GC_NEUTRAL_MODE;
658 guint32 parent = mono_image_typedef_or_ref (assembly, type);
659 return mono_image_add_memberef_row (assembly, parent, name, sig);
663 guint32
664 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
666 MONO_REQ_GC_NEUTRAL_MODE;
668 guint32 token;
669 MonoMethodSignature *sig;
671 create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
673 if (create_typespec) {
674 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
675 if (token)
676 return token;
679 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
680 if (token && !create_typespec)
681 return token;
683 g_assert (!method->is_inflated);
684 if (!token) {
686 * A methodref signature can't contain an unmanaged calling convention.
688 sig = mono_metadata_signature_dup (mono_method_signature_internal (method));
689 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
690 sig->call_convention = MONO_CALL_DEFAULT;
691 token = mono_image_get_memberref_token (assembly, m_class_get_byval_arg (method->klass),
692 method->name, mono_dynimage_encode_method_signature (assembly, sig));
693 g_free (sig);
694 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
697 if (create_typespec) {
698 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
699 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
700 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
702 if (assembly->save) {
703 guint32 *values;
705 alloc_table (table, table->rows + 1);
706 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
707 values [MONO_METHODSPEC_METHOD] = token;
708 values [MONO_METHODSPEC_SIGNATURE] = mono_dynimage_encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
711 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
712 table->next_idx ++;
713 /*methodspec and memberef tokens are diferent, */
714 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
715 return token;
717 return token;
720 static guint32
721 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
722 const gchar *name, guint32 sig)
724 MonoDynamicTable *table;
725 guint32 token;
726 guint32 *values;
728 table = &assembly->tables [MONO_TABLE_MEMBERREF];
730 if (assembly->save) {
731 alloc_table (table, table->rows + 1);
732 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
733 values [MONO_MEMBERREF_CLASS] = original;
734 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
735 values [MONO_MEMBERREF_SIGNATURE] = sig;
738 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
739 table->next_idx ++;
741 return token;
744 #else /* DISABLE_REFLECTION_EMIT */
746 guint32
747 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
749 g_assert_not_reached ();
750 return -1;
752 #endif
754 static gboolean
755 is_field_on_inst (MonoClassField *field)
757 return mono_class_is_ginst (field->parent) && mono_class_get_generic_class (field->parent)->is_dynamic;
760 static gboolean
761 is_field_on_gtd (MonoClassField *field)
763 return mono_class_is_gtd (field->parent);
766 #ifndef DISABLE_REFLECTION_EMIT
767 static guint32
768 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoClassField *field)
770 MonoType *type;
771 guint32 token;
773 g_assert (field);
774 g_assert (field->parent);
776 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, field));
777 if (token)
778 return token;
780 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) {
781 int index = field - field->parent->fields;
782 type = mono_field_get_type_internal (&mono_class_get_generic_class (field->parent)->container_class->fields [index]);
783 } else {
784 type = mono_field_get_type_internal (field);
786 token = mono_image_get_memberref_token (assembly, m_class_get_byval_arg (field->parent),
787 mono_field_get_name (field),
788 mono_dynimage_encode_fieldref_signature (assembly, field->parent->image, type));
789 g_hash_table_insert (assembly->handleref, field, GUINT_TO_POINTER(token));
790 return token;
793 static guint32
794 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
796 MonoDynamicTable *table;
797 guint32 *values;
798 guint32 token, mtoken = 0, sig;
799 MonoMethodInflated *imethod;
800 MonoMethod *declaring;
802 table = &assembly->tables [MONO_TABLE_METHODSPEC];
804 g_assert (method->is_inflated);
805 imethod = (MonoMethodInflated *) method;
806 declaring = imethod->declaring;
808 sig = mono_dynimage_encode_method_signature (assembly, mono_method_signature_internal (declaring));
809 mtoken = mono_image_get_memberref_token (assembly, m_class_get_byval_arg (method->klass), declaring->name, sig);
811 if (!mono_method_signature_internal (declaring)->generic_param_count)
812 return mtoken;
814 switch (mono_metadata_token_table (mtoken)) {
815 case MONO_TABLE_MEMBERREF:
816 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
817 break;
818 case MONO_TABLE_METHOD:
819 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
820 break;
821 default:
822 g_assert_not_reached ();
825 sig = mono_dynimage_encode_generic_method_sig (assembly, mono_method_get_context (method));
827 if (assembly->save) {
828 alloc_table (table, table->rows + 1);
829 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
830 values [MONO_METHODSPEC_METHOD] = mtoken;
831 values [MONO_METHODSPEC_SIGNATURE] = sig;
834 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
835 table->next_idx ++;
837 return token;
840 static guint32
841 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
843 MonoMethodInflated *imethod;
844 guint32 token;
846 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
847 if (token)
848 return token;
850 g_assert (method->is_inflated);
851 imethod = (MonoMethodInflated *) method;
853 if (mono_method_signature_internal (imethod->declaring)->generic_param_count) {
854 token = method_encode_methodspec (assembly, method);
855 } else {
856 guint32 sig = mono_dynimage_encode_method_signature (
857 assembly, mono_method_signature_internal (imethod->declaring));
858 token = mono_image_get_memberref_token (
859 assembly, m_class_get_byval_arg (method->klass), method->name, sig);
862 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
863 return token;
866 static guint32
867 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
869 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
870 guint32 sig, token;
872 sig = mono_dynimage_encode_method_signature (assembly, mono_method_signature_internal (imethod->declaring));
873 token = mono_image_get_memberref_token (
874 assembly, m_class_get_byval_arg (m->klass), m->name, sig);
876 return token;
879 static guint32
880 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelperHandle helper, MonoError *error)
882 guint32 idx;
883 MonoDynamicTable *table;
884 guint32 *values;
886 error_init (error);
888 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
889 idx = table->next_idx ++;
890 table->rows ++;
891 alloc_table (table, table->rows);
892 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
894 values [MONO_STAND_ALONE_SIGNATURE] =
895 mono_dynimage_encode_reflection_sighelper (assembly, helper, error);
896 return_val_if_nok (error, 0);
898 return idx;
901 static int
902 reflection_cc_to_file (int call_conv) {
903 switch (call_conv & 0x3) {
904 case 0:
905 case 1: return MONO_CALL_DEFAULT;
906 case 2: return MONO_CALL_VARARG;
907 default:
908 g_assert_not_reached ();
910 return 0;
912 #endif /* !DISABLE_REFLECTION_EMIT */
914 struct _ArrayMethod {
915 MonoType *parent;
916 MonoMethodSignature *sig;
917 char *name;
918 guint32 token;
921 void
922 mono_sre_array_method_free (ArrayMethod *am)
924 g_free (am->sig);
925 g_free (am->name);
926 g_free (am);
929 #ifndef DISABLE_REFLECTION_EMIT
930 static guint32
931 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethodHandle m, MonoError *error)
933 MonoMethodSignature *sig = NULL;
934 char *name = NULL;
936 error_init (error);
938 MonoArrayHandle parameters = MONO_HANDLE_NEW_GET (MonoArray, m, parameters);
939 guint32 nparams = mono_array_handle_length (parameters);
940 sig = (MonoMethodSignature *)g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
941 sig->hasthis = 1;
942 sig->sentinelpos = -1;
943 sig->call_convention = reflection_cc_to_file (MONO_HANDLE_GETVAL (m, call_conv));
944 sig->param_count = nparams;
945 MonoReflectionTypeHandle ret = MONO_HANDLE_NEW_GET (MonoReflectionType, m, ret);
946 if (!MONO_HANDLE_IS_NULL (ret)) {
947 sig->ret = mono_reflection_type_handle_mono_type (ret, error);
948 goto_if_nok (error, fail);
949 } else
950 sig->ret = mono_get_void_type ();
952 MonoReflectionTypeHandle parent;
953 parent = MONO_HANDLE_NEW_GET (MonoReflectionType, m, parent);
954 MonoType *mtype;
955 mtype = mono_reflection_type_handle_mono_type (parent, error);
956 goto_if_nok (error, fail);
958 for (int i = 0; i < nparams; ++i) {
959 sig->params [i] = mono_type_array_get_and_resolve (parameters, i, error);
960 goto_if_nok (error, fail);
963 MonoStringHandle mname;
964 mname = MONO_HANDLE_NEW_GET (MonoString, m, name);
965 name = mono_string_handle_to_utf8 (mname, error);
966 goto_if_nok (error, fail);
968 ArrayMethod *am;
969 am = NULL;
970 for (GList *tmp = assembly->array_methods; tmp; tmp = tmp->next) {
971 am = (ArrayMethod *)tmp->data;
972 if (strcmp (name, am->name) == 0 &&
973 mono_metadata_type_equal (am->parent, mtype) &&
974 mono_metadata_signature_equal (am->sig, sig)) {
975 g_free (name);
976 g_free (sig);
977 MONO_HANDLE_SETVAL (m, table_idx, guint32, am->token & 0xffffff);
978 return am->token;
981 am = g_new0 (ArrayMethod, 1);
982 am->name = name;
983 am->sig = sig;
984 am->parent = mtype;
985 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
986 mono_dynimage_encode_method_signature (assembly, sig));
987 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
988 MONO_HANDLE_SETVAL (m, table_idx, guint32, am->token & 0xffffff);
989 return am->token;
990 fail:
991 g_free (name);
992 g_free (sig);
993 return 0;
996 #endif
998 #ifndef DISABLE_REFLECTION_EMIT
1001 * mono_image_insert_string:
1002 * @module: module builder object
1003 * @str: a string
1005 * Insert @str into the user string stream of @module.
1007 guint32
1008 mono_image_insert_string (MonoReflectionModuleBuilderHandle ref_module, MonoStringHandle str, MonoError *error)
1010 HANDLE_FUNCTION_ENTER ();
1011 guint32 idx;
1012 char buf [16];
1013 char *b = buf;
1014 guint32 token = 0;
1016 MonoDynamicImage *assembly = MONO_HANDLE_GETVAL (ref_module, dynamic_image);
1017 if (!assembly) {
1018 if (!mono_image_module_basic_init (ref_module, error))
1019 goto leave;
1021 assembly = MONO_HANDLE_GETVAL (ref_module, dynamic_image);
1023 g_assert (assembly != NULL);
1025 if (assembly->save) {
1026 int32_t length = mono_string_length_internal (MONO_HANDLE_RAW (str));
1027 mono_metadata_encode_value (1 | (length * 2), b, &b);
1028 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
1029 /* pinned */
1030 uint32_t gchandle = mono_gchandle_from_handle (MONO_HANDLE_CAST (MonoObject, str), TRUE);
1031 const char *p = (const char*)mono_string_chars_internal (MONO_HANDLE_RAW (str));
1032 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1034 char *swapped = g_malloc (2 * length);
1036 swap_with_size (swapped, p, 2, length);
1037 mono_image_add_stream_data (&assembly->us, swapped, length * 2);
1038 g_free (swapped);
1040 #else
1041 mono_image_add_stream_data (&assembly->us, p, length * 2);
1042 #endif
1043 mono_gchandle_free_internal (gchandle);
1044 mono_image_add_stream_data (&assembly->us, "", 1);
1045 } else {
1046 idx = assembly->us.index ++;
1049 token = MONO_TOKEN_STRING | idx;
1050 mono_dynamic_image_register_token (assembly, token, MONO_HANDLE_CAST (MonoObject, str), MONO_DYN_IMAGE_TOK_NEW);
1052 leave:
1053 HANDLE_FUNCTION_RETURN_VAL (token);
1056 static guint32
1057 create_method_token (MonoDynamicImage *assembly, MonoMethod *method, MonoArrayHandle opt_param_types, MonoError *error)
1059 guint32 sig_token, parent;
1062 int nargs = mono_array_handle_length (opt_param_types);
1063 MonoMethodSignature *old = mono_method_signature_internal (method);
1064 MonoMethodSignature *sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
1066 sig->hasthis = old->hasthis;
1067 sig->explicit_this = old->explicit_this;
1068 sig->call_convention = old->call_convention;
1069 sig->generic_param_count = old->generic_param_count;
1070 sig->param_count = old->param_count + nargs;
1071 sig->sentinelpos = old->param_count;
1072 sig->ret = old->ret;
1074 for (int i = 0; i < old->param_count; i++)
1075 sig->params [i] = old->params [i];
1077 MonoReflectionTypeHandle rt = MONO_HANDLE_NEW (MonoReflectionType, NULL);
1078 for (int i = 0; i < nargs; i++) {
1079 MONO_HANDLE_ARRAY_GETREF (rt, opt_param_types, i);
1080 sig->params [old->param_count + i] = mono_reflection_type_handle_mono_type (rt, error);
1081 goto_if_nok (error, fail);
1084 parent = mono_image_typedef_or_ref (assembly, m_class_get_byval_arg (method->klass));
1085 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
1086 parent >>= MONO_TYPEDEFORREF_BITS;
1088 parent <<= MONO_MEMBERREF_PARENT_BITS;
1089 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
1091 sig_token = mono_dynimage_encode_method_signature (assembly, sig);
1092 guint32 token;
1093 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
1094 g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
1095 return token;
1096 fail:
1097 return 0;
1100 guint32
1101 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObjectHandle obj, MonoArrayHandle opt_param_types, MonoError *error)
1103 guint32 token = 0;
1105 error_init (error);
1107 MonoClass *klass = mono_handle_class (obj);
1108 if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
1109 MonoReflectionMethodHandle ref_method = MONO_HANDLE_CAST (MonoReflectionMethod, obj);
1110 MonoMethod *method = MONO_HANDLE_GETVAL (ref_method, method);
1111 g_assert (!MONO_HANDLE_IS_NULL (opt_param_types) && (mono_method_signature_internal (method)->sentinelpos >= 0));
1112 token = create_method_token (assembly, method, opt_param_types, error);
1113 goto_if_nok (error, fail);
1114 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
1115 g_assert_not_reached ();
1116 } else {
1117 g_error ("requested method token for %s\n", klass->name);
1120 mono_dynamic_image_register_token (assembly, token, obj, MONO_DYN_IMAGE_TOK_NEW);
1121 return token;
1122 fail:
1123 g_assert (!mono_error_ok (error));
1124 return 0;
1128 * mono_image_create_token:
1129 * @assembly: a dynamic assembly
1130 * @obj:
1131 * @register_token: Whenever to register the token in the assembly->tokens hash.
1133 * Get a token to insert in the IL code stream for the given MemberInfo.
1134 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
1135 * the table_idx-es were recomputed, so registering the token would overwrite an existing
1136 * entry.
1138 guint32
1139 mono_image_create_token (MonoDynamicImage *assembly, MonoObjectHandle obj,
1140 gboolean create_open_instance, gboolean register_token,
1141 MonoError *error)
1143 HANDLE_FUNCTION_ENTER ();
1144 guint32 token = 0;
1146 error_init (error);
1148 MonoClass *klass = mono_handle_class (obj);
1149 MonoObjectHandle register_obj = MONO_HANDLE_NEW (MonoObject, NULL);
1150 MONO_HANDLE_ASSIGN (register_obj, obj);
1152 /* Check for user defined reflection objects */
1153 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
1154 if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0)) {
1155 mono_error_set_not_supported (error, "User defined subclasses of System.Type are not yet supported");
1156 goto leave;
1159 /* This function is called from ModuleBuilder:getToken multiple times for the same objects */
1160 int how_collide;
1161 how_collide = MONO_DYN_IMAGE_TOK_SAME_OK;
1163 if (strcmp (klass->name, "RuntimeType") == 0) {
1164 MonoType *type = mono_reflection_type_handle_mono_type (MONO_HANDLE_CAST (MonoReflectionType, obj), error);
1165 goto_if_nok (error, leave);
1166 MonoClass *mc = mono_class_from_mono_type_internal (type);
1167 token = mono_metadata_token_from_dor (
1168 mono_dynimage_encode_typedef_or_ref_full (assembly, type, !mono_class_is_gtd (mc) || create_open_instance));
1169 /* If it's a RuntimeType now, we could have registered a
1170 * TypeBuilder for it before, so replacing is okay. */
1171 how_collide = MONO_DYN_IMAGE_TOK_REPLACE;
1172 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
1173 strcmp (klass->name, "MonoMethod") == 0) {
1174 MonoReflectionMethodHandle m = MONO_HANDLE_CAST (MonoReflectionMethod, obj);
1175 MonoMethod *method = MONO_HANDLE_GETVAL (m, method);
1176 if (method->is_inflated) {
1177 if (create_open_instance) {
1178 guint32 methodspec_token = mono_image_get_methodspec_token (assembly, method);
1179 MonoReflectionMethodHandle canonical_obj =
1180 mono_method_get_object_handle (MONO_HANDLE_DOMAIN (obj), method, NULL, error);
1181 goto_if_nok (error, leave);
1182 MONO_HANDLE_ASSIGN (register_obj, canonical_obj);
1183 token = methodspec_token;
1184 } else
1185 token = mono_image_get_inflated_method_token (assembly, method);
1186 } else if ((method->klass->image == &assembly->image) &&
1187 !mono_class_is_ginst (method->klass) &&
1188 !mono_class_is_gtd (method->klass)) {
1189 static guint32 method_table_idx = 0xffffff;
1190 if (method->klass->wastypebuilder) {
1191 /* we use the same token as the one that was assigned
1192 * to the Methodbuilder.
1193 * FIXME: do the equivalent for Fields.
1195 token = method->token;
1196 how_collide = MONO_DYN_IMAGE_TOK_REPLACE;
1197 } else {
1199 * Each token should have a unique index, but the indexes are
1200 * assigned by managed code, so we don't know about them. An
1201 * easy solution is to count backwards...
1203 method_table_idx --;
1204 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
1205 how_collide = MONO_DYN_IMAGE_TOK_NEW;
1207 } else {
1208 guint32 methodref_token = mono_image_get_methodref_token (assembly, method, create_open_instance);
1209 /* We need to register a 'canonical' object. The same
1210 * MonoMethod could have been reflected via different
1211 * classes so the MonoReflectionMethod:reftype could be
1212 * different, and the object lookup in
1213 * dynamic_image_register_token would assert assert. So
1214 * we pick the MonoReflectionMethod object that has the
1215 * reflected type as NULL (ie, take the declaring type
1216 * of the method) */
1217 MonoReflectionMethodHandle canonical_obj =
1218 mono_method_get_object_handle (MONO_HANDLE_DOMAIN (obj), method, NULL, error);
1219 goto_if_nok (error, leave);
1220 MONO_HANDLE_ASSIGN (register_obj, canonical_obj);
1221 token = methodref_token;
1223 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
1224 } else if (strcmp (klass->name, "MonoField") == 0) {
1225 MonoReflectionFieldHandle f = MONO_HANDLE_CAST (MonoReflectionField, obj);
1226 MonoClassField *field = MONO_HANDLE_GETVAL (f, field);
1227 if ((field->parent->image == &assembly->image) &&
1228 !is_field_on_gtd (field) &&
1229 !is_field_on_inst (field)) {
1230 static guint32 field_table_idx = 0xffffff;
1231 field_table_idx --;
1232 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
1233 g_assert (!mono_class_is_gtd (field->parent));
1234 how_collide = MONO_DYN_IMAGE_TOK_NEW;
1235 } else {
1236 guint32 fieldref_token = mono_image_get_fieldref_token (assembly, field);
1237 /* Same as methodref: get a canonical object to
1238 * register with the token. */
1239 MonoReflectionFieldHandle canonical_obj =
1240 mono_field_get_object_handle (MONO_HANDLE_DOMAIN (obj), field->parent, field, error);
1241 goto_if_nok (error, leave);
1242 MONO_HANDLE_ASSIGN (register_obj, canonical_obj);
1243 token = fieldref_token;
1245 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
1246 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
1247 MonoReflectionArrayMethodHandle m = MONO_HANDLE_CAST (MonoReflectionArrayMethod, obj);
1248 /* mono_image_get_array_token caches tokens by signature */
1249 guint32 array_token = mono_image_get_array_token (assembly, m, error);
1250 goto_if_nok (error, leave);
1251 token = array_token;
1252 /* ModuleBuilder:GetArrayMethod() always returns a fresh
1253 * MonoArrayMethod instance even given the same method name and
1254 * signature. But they're all interchangeable, so it's okay to
1255 * replace.
1257 how_collide = MONO_DYN_IMAGE_TOK_REPLACE;
1258 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
1259 MonoReflectionSigHelperHandle s = MONO_HANDLE_CAST (MonoReflectionSigHelper, obj);
1260 /* always returns a fresh token */
1261 guint32 sig_token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s, error);
1262 goto_if_nok (error, leave);
1263 token = sig_token;
1264 how_collide = MONO_DYN_IMAGE_TOK_NEW;
1265 } else {
1266 g_error ("requested token for %s\n", klass->name);
1269 if (register_token)
1270 mono_dynamic_image_register_token (assembly, token, register_obj, how_collide);
1272 leave:
1273 HANDLE_FUNCTION_RETURN_VAL (token);
1277 #endif
1279 #ifndef DISABLE_REFLECTION_EMIT
1281 static gboolean
1282 assemblybuilderaccess_can_refonlyload (guint32 access)
1284 return (access & 0x4) != 0;
1287 static gboolean
1288 assemblybuilderaccess_can_run (guint32 access)
1290 return (access & MonoAssemblyBuilderAccess_Run) != 0;
1293 static gboolean
1294 assemblybuilderaccess_can_save (guint32 access)
1296 return (access & MonoAssemblyBuilderAccess_Save) != 0;
1301 * mono_reflection_dynimage_basic_init:
1302 * @assembly: an assembly builder object
1304 * Create the MonoImage that represents the assembly builder and setup some
1305 * of the helper hash table and the basic metadata streams.
1307 void
1308 mono_reflection_dynimage_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
1310 ERROR_DECL (error);
1311 MonoDynamicAssembly *assembly;
1312 MonoDynamicImage *image;
1313 MonoDomain *domain = mono_object_domain (assemblyb);
1315 if (assemblyb->dynamic_assembly)
1316 return;
1318 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
1320 MONO_PROFILER_RAISE (assembly_loading, (&assembly->assembly));
1322 assembly->assembly.ref_count = 1;
1323 assembly->assembly.dynamic = TRUE;
1324 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
1325 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
1326 assembly->assembly.basedir = mono_string_to_utf8_checked_internal (assemblyb->dir, error);
1327 if (mono_error_set_pending_exception (error))
1328 return;
1329 if (assemblyb->culture) {
1330 assembly->assembly.aname.culture = mono_string_to_utf8_checked_internal (assemblyb->culture, error);
1331 if (mono_error_set_pending_exception (error))
1332 return;
1333 } else
1334 assembly->assembly.aname.culture = g_strdup ("");
1336 if (assemblyb->version) {
1337 char *vstr = mono_string_to_utf8_checked_internal (assemblyb->version, error);
1338 if (mono_error_set_pending_exception (error))
1339 return;
1340 char **version = g_strsplit (vstr, ".", 4);
1341 char **parts = version;
1342 assembly->assembly.aname.major = atoi (*parts++);
1343 assembly->assembly.aname.minor = atoi (*parts++);
1344 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
1345 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
1347 g_strfreev (version);
1348 g_free (vstr);
1349 } else {
1350 assembly->assembly.aname.major = 0;
1351 assembly->assembly.aname.minor = 0;
1352 assembly->assembly.aname.build = 0;
1353 assembly->assembly.aname.revision = 0;
1356 /* SRE assemblies are loaded into the individual loading context, ie,
1357 * they only fire AssemblyResolve events, they don't cause probing for
1358 * referenced assemblies to happen. */
1359 assembly->assembly.context.kind = assemblybuilderaccess_can_refonlyload (assemblyb->access) ? MONO_ASMCTX_REFONLY : MONO_ASMCTX_INDIVIDUAL;
1360 assembly->run = assemblybuilderaccess_can_run (assemblyb->access);
1361 assembly->save = assemblybuilderaccess_can_save (assemblyb->access);
1362 assembly->domain = domain;
1364 char *assembly_name = mono_string_to_utf8_checked_internal (assemblyb->name, error);
1365 if (mono_error_set_pending_exception (error))
1366 return;
1367 image = mono_dynamic_image_create (assembly, assembly_name, g_strdup ("RefEmit_YouForgotToDefineAModule"));
1368 image->initial_image = TRUE;
1369 assembly->assembly.aname.name = image->image.name;
1370 assembly->assembly.image = &image->image;
1371 if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
1372 /* -1 to correct for the trailing NULL byte */
1373 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
1374 g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
1376 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr_internal (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);
1379 mono_domain_assemblies_lock (domain);
1380 domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
1381 mono_domain_assemblies_unlock (domain);
1383 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
1385 MONO_PROFILER_RAISE (assembly_loaded, (&assembly->assembly));
1387 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
1390 #endif /* !DISABLE_REFLECTION_EMIT */
1392 #ifndef DISABLE_REFLECTION_EMIT
1393 static gpointer
1394 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
1396 return CACHE_OBJECT (MonoReflectionAssembly *, assembly, &res->object, NULL);
1399 static MonoReflectionModuleBuilderHandle
1400 register_module (MonoDomain *domain, MonoReflectionModuleBuilderHandle res, MonoDynamicImage *module)
1402 return CACHE_OBJECT_HANDLE (MonoReflectionModuleBuilder, module, MONO_HANDLE_CAST (MonoObject, res), NULL);
1405 static gboolean
1406 image_module_basic_init (MonoReflectionModuleBuilderHandle moduleb, MonoError *error)
1408 error_init (error);
1409 MonoDomain *domain = MONO_HANDLE_DOMAIN (moduleb);
1410 MonoDynamicImage *image = MONO_HANDLE_GETVAL (moduleb, dynamic_image);
1411 MonoReflectionAssemblyBuilderHandle ab = MONO_HANDLE_NEW (MonoReflectionAssemblyBuilder, NULL);
1412 MONO_HANDLE_GET (ab, moduleb, assemblyb);
1413 if (!image) {
1415 * FIXME: we already created an image in mono_reflection_dynimage_basic_init (), but
1416 * we don't know which module it belongs to, since that is only
1417 * determined at assembly save time.
1419 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
1420 MonoStringHandle abname = MONO_HANDLE_NEW_GET (MonoString, ab, name);
1421 char *name = mono_string_handle_to_utf8 (abname, error);
1422 return_val_if_nok (error, FALSE);
1423 MonoStringHandle modfqname = MONO_HANDLE_NEW_GET (MonoString, MONO_HANDLE_CAST (MonoReflectionModule, moduleb), fqname);
1424 char *fqname = mono_string_handle_to_utf8 (modfqname, error);
1425 if (!is_ok (error)) {
1426 g_free (name);
1427 return FALSE;
1429 MonoDynamicAssembly *dynamic_assembly = MONO_HANDLE_GETVAL (ab, dynamic_assembly);
1430 image = mono_dynamic_image_create (dynamic_assembly, name, fqname);
1432 MONO_HANDLE_SETVAL (MONO_HANDLE_CAST (MonoReflectionModule, moduleb), image, MonoImage*, &image->image);
1433 MONO_HANDLE_SETVAL (moduleb, dynamic_image, MonoDynamicImage*, image);
1434 register_module (domain, moduleb, image);
1436 /* register the module with the assembly */
1437 MonoImage *ass = dynamic_assembly->assembly.image;
1438 int module_count = ass->module_count;
1439 MonoImage **new_modules = g_new0 (MonoImage *, module_count + 1);
1441 if (ass->modules)
1442 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
1443 new_modules [module_count] = &image->image;
1444 mono_image_addref (&image->image);
1446 g_free (ass->modules);
1447 ass->modules = new_modules;
1448 ass->module_count ++;
1450 return TRUE;
1453 static gboolean
1454 mono_image_module_basic_init (MonoReflectionModuleBuilderHandle moduleb, MonoError *error)
1456 error_init (error);
1457 return image_module_basic_init (moduleb, error);
1460 #endif
1462 static gboolean
1463 is_corlib_type (MonoClass *klass)
1465 return klass->image == mono_defaults.corlib;
1468 #define check_corlib_type_cached(_class, _namespace, _name) do { \
1469 static MonoClass *cached_class; \
1470 if (cached_class) \
1471 return cached_class == _class; \
1472 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
1473 cached_class = _class; \
1474 return TRUE; \
1476 return FALSE; \
1477 } while (0) \
1480 MonoType*
1481 mono_type_array_get_and_resolve (MonoArrayHandle array, int idx, MonoError *error)
1483 HANDLE_FUNCTION_ENTER();
1484 error_init (error);
1485 MonoReflectionTypeHandle t = MONO_HANDLE_NEW (MonoReflectionType, NULL);
1486 MONO_HANDLE_ARRAY_GETREF (t, array, idx);
1487 MonoType *result = mono_reflection_type_handle_mono_type (t, error);
1488 HANDLE_FUNCTION_RETURN_VAL (result);
1491 static MonoType *
1492 add_custom_modifiers_to_type (MonoType *without_mods, MonoArrayHandle req_array, MonoArrayHandle opt_array, MonoImage *image, MonoError *error)
1494 HANDLE_FUNCTION_ENTER();
1495 error_init (error);
1497 int num_req_mods = 0;
1498 if (!MONO_HANDLE_IS_NULL (req_array))
1499 num_req_mods = mono_array_handle_length (req_array);
1501 int num_opt_mods = 0;
1502 if (!MONO_HANDLE_IS_NULL (opt_array))
1503 num_opt_mods = mono_array_handle_length (opt_array);
1505 if (!(num_opt_mods || num_req_mods))
1506 return without_mods;
1508 MonoTypeWithModifiers *result;
1509 result = mono_image_g_malloc0 (image, mono_sizeof_type_with_mods (num_req_mods + num_opt_mods));
1510 memcpy (result, without_mods, MONO_SIZEOF_TYPE);
1511 result->unmodified.has_cmods = 1;
1512 MonoCustomModContainer *cmods = mono_type_get_cmods ((MonoType *)result);
1513 g_assert (cmods);
1514 cmods->count = num_req_mods + num_opt_mods;
1515 cmods->image = image;
1517 g_assert (image_is_dynamic (image));
1518 MonoDynamicImage *allocator = (MonoDynamicImage *) image;
1520 int modifier_index = 0;
1522 MonoObjectHandle mod_handle = MONO_HANDLE_NEW (MonoObject, NULL);
1523 for (int i=0; i < num_req_mods; i++) {
1524 cmods->modifiers [modifier_index].required = TRUE;
1525 MONO_HANDLE_ARRAY_GETREF (mod_handle, req_array, i);
1526 cmods->modifiers [modifier_index].token = mono_image_create_token (allocator, mod_handle, FALSE, TRUE, error);
1527 modifier_index++;
1530 for (int i=0; i < num_opt_mods; i++) {
1531 cmods->modifiers [modifier_index].required = FALSE;
1532 MONO_HANDLE_ARRAY_GETREF (mod_handle, opt_array, i);
1533 cmods->modifiers [modifier_index].token = mono_image_create_token (allocator, mod_handle, FALSE, TRUE, error);
1534 modifier_index++;
1537 HANDLE_FUNCTION_RETURN_VAL ((MonoType *) result);
1540 static
1541 MonoType *
1542 mono_type_array_get_and_resolve_with_modifiers (MonoArrayHandle types, MonoArrayHandle required_modifiers, MonoArrayHandle optional_modifiers, int idx, MonoImage *image, MonoError *error)
1544 HANDLE_FUNCTION_ENTER();
1545 error_init (error);
1546 MonoReflectionTypeHandle type = MONO_HANDLE_NEW (MonoReflectionType, NULL);
1547 MonoArrayHandle req_mods_handle = MONO_HANDLE_NEW (MonoArray, NULL);
1548 MonoArrayHandle opt_mods_handle = MONO_HANDLE_NEW (MonoArray, NULL);
1550 if (!MONO_HANDLE_IS_NULL (required_modifiers))
1551 MONO_HANDLE_ARRAY_GETREF (req_mods_handle, required_modifiers, idx);
1553 if (!MONO_HANDLE_IS_NULL (optional_modifiers))
1554 MONO_HANDLE_ARRAY_GETREF (opt_mods_handle, optional_modifiers, idx);
1556 MONO_HANDLE_ARRAY_GETREF (type, types, idx);
1558 MonoType *result = mono_reflection_type_handle_mono_type (type, error);
1559 result = (MonoType *) add_custom_modifiers_to_type (result, req_mods_handle, opt_mods_handle, image, error);
1561 HANDLE_FUNCTION_RETURN_VAL (result);
1565 #ifndef DISABLE_REFLECTION_EMIT
1566 static gboolean
1567 is_sre_array (MonoClass *klass)
1569 check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
1572 static gboolean
1573 is_sre_byref (MonoClass *klass)
1575 check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
1578 static gboolean
1579 is_sre_pointer (MonoClass *klass)
1581 check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
1584 static gboolean
1585 is_sre_generic_instance (MonoClass *klass)
1587 check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilderInstantiation");
1590 static gboolean
1591 is_sre_type_builder (MonoClass *klass)
1593 check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
1596 static gboolean
1597 is_sre_method_builder (MonoClass *klass)
1599 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
1602 gboolean
1603 mono_is_sre_ctor_builder (MonoClass *klass)
1605 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
1608 static gboolean
1609 is_sre_field_builder (MonoClass *klass)
1611 check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
1614 static gboolean
1615 is_sre_gparam_builder (MonoClass *klass)
1617 check_corlib_type_cached (klass, "System.Reflection.Emit", "GenericTypeParameterBuilder");
1620 static gboolean
1621 is_sre_enum_builder (MonoClass *klass)
1623 check_corlib_type_cached (klass, "System.Reflection.Emit", "EnumBuilder");
1626 gboolean
1627 mono_is_sre_method_on_tb_inst (MonoClass *klass)
1629 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
1632 gboolean
1633 mono_is_sre_ctor_on_tb_inst (MonoClass *klass)
1635 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
1638 static MonoReflectionTypeHandle
1639 mono_reflection_type_get_underlying_system_type (MonoReflectionTypeHandle t, MonoError *error)
1641 static MonoMethod *method_get_underlying_system_type = NULL;
1642 HANDLE_FUNCTION_ENTER ();
1644 error_init (error);
1646 if (!method_get_underlying_system_type) {
1647 method_get_underlying_system_type = mono_class_get_method_from_name_checked (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0, 0, error);
1648 mono_error_assert_ok (error);
1651 MonoReflectionTypeHandle rt = MONO_HANDLE_NEW (MonoReflectionType, NULL);
1653 MonoMethod *usertype_method = mono_object_handle_get_virtual_method (MONO_HANDLE_CAST (MonoObject, t), method_get_underlying_system_type, error);
1654 goto_if_nok (error, leave);
1656 MONO_HANDLE_ASSIGN (rt, MONO_HANDLE_CAST (MonoReflectionType, MONO_HANDLE_NEW (MonoObject, mono_runtime_invoke_checked (usertype_method, MONO_HANDLE_RAW (t), NULL, error))));
1658 leave:
1659 HANDLE_FUNCTION_RETURN_REF (MonoReflectionType, rt);
1662 MonoType*
1663 mono_reflection_type_get_handle (MonoReflectionType* ref_raw, MonoError *error)
1665 HANDLE_FUNCTION_ENTER ();
1666 error_init (error);
1667 MONO_HANDLE_DCL (MonoReflectionType, ref);
1668 MonoType *result = mono_reflection_type_handle_mono_type (ref, error);
1669 HANDLE_FUNCTION_RETURN_VAL (result);
1672 static MonoType*
1673 reflection_instance_handle_mono_type (MonoReflectionGenericClassHandle ref_gclass, MonoError *error)
1675 HANDLE_FUNCTION_ENTER ();
1676 MonoType *result = NULL;
1677 MonoType **types = NULL;
1679 MonoArrayHandle typeargs = MONO_HANDLE_NEW_GET (MonoArray, ref_gclass, type_arguments);
1680 int count = mono_array_handle_length (typeargs);
1681 types = g_new0 (MonoType*, count);
1682 MonoReflectionTypeHandle t = MONO_HANDLE_NEW (MonoReflectionType, NULL);
1683 for (int i = 0; i < count; ++i) {
1684 MONO_HANDLE_ARRAY_GETREF (t, typeargs, i);
1685 types [i] = mono_reflection_type_handle_mono_type (t, error);
1686 if (!types[i] || !is_ok (error)) {
1687 goto leave;
1690 /* Need to resolve the generic_type in order for it to create its generic context. */
1691 MonoReflectionTypeHandle ref_gtd;
1692 ref_gtd = MONO_HANDLE_NEW_GET (MonoReflectionType, ref_gclass, generic_type);
1693 MonoType *gtd;
1694 gtd = mono_reflection_type_handle_mono_type (ref_gtd, error);
1695 goto_if_nok (error, leave);
1696 MonoClass *gtd_klass;
1697 gtd_klass = mono_class_from_mono_type_internal (gtd);
1698 if (is_sre_type_builder (mono_handle_class (ref_gtd))) {
1699 reflection_setup_internal_class (MONO_HANDLE_CAST (MonoReflectionTypeBuilder, ref_gtd), error);
1700 goto_if_nok (error, leave);
1702 g_assert (count == 0 || mono_class_is_gtd (gtd_klass));
1703 result = mono_reflection_bind_generic_parameters (ref_gtd, count, types, error);
1704 goto_if_nok (error, leave);
1705 g_assert (result);
1706 MONO_HANDLE_SETVAL (MONO_HANDLE_CAST (MonoReflectionType, ref_gclass), type, MonoType*, result);
1707 leave:
1708 g_free (types);
1709 HANDLE_FUNCTION_RETURN_VAL (result);
1712 static MonoType*
1713 reflection_param_handle_mono_type (MonoReflectionGenericParamHandle ref_gparam, MonoError *error)
1715 HANDLE_FUNCTION_ENTER ();
1716 error_init (error);
1717 MonoType *result = NULL;
1720 MonoReflectionTypeBuilderHandle ref_tbuilder = MONO_HANDLE_NEW_GET (MonoReflectionTypeBuilder, ref_gparam, tbuilder);
1721 MonoReflectionModuleBuilderHandle ref_module = MONO_HANDLE_NEW_GET (MonoReflectionModuleBuilder, ref_tbuilder, module);
1722 MonoDynamicImage *dynamic_image = MONO_HANDLE_GETVAL (ref_module, dynamic_image);
1723 MonoImage *image = &dynamic_image->image;
1725 MonoGenericParamFull *param = mono_image_new0 (image, MonoGenericParamFull, 1);
1727 MonoStringHandle ref_name = MONO_HANDLE_NEW_GET (MonoString, ref_gparam, name);
1728 param->info.name = mono_string_to_utf8_image (image, ref_name, error);
1729 mono_error_assert_ok (error);
1730 param->num = MONO_HANDLE_GETVAL (ref_gparam, index);
1732 MonoReflectionMethodBuilderHandle ref_mbuilder = MONO_HANDLE_NEW_GET (MonoReflectionMethodBuilder, ref_gparam, mbuilder);
1733 if (!MONO_HANDLE_IS_NULL (ref_mbuilder)) {
1734 MonoGenericContainer *generic_container = MONO_HANDLE_GETVAL (ref_mbuilder, generic_container);
1735 if (!generic_container) {
1736 generic_container = (MonoGenericContainer *)mono_image_alloc0 (image, sizeof (MonoGenericContainer));
1737 generic_container->is_method = TRUE;
1739 * Cannot set owner.method, since the MonoMethod is not created yet.
1740 * Set the image field instead, so type_in_image () works.
1742 generic_container->is_anonymous = TRUE;
1743 generic_container->owner.image = image;
1744 MONO_HANDLE_SETVAL (ref_mbuilder, generic_container, MonoGenericContainer*, generic_container);
1746 param->owner = generic_container;
1747 } else {
1748 MonoType *type = mono_reflection_type_handle_mono_type (MONO_HANDLE_CAST (MonoReflectionType, ref_tbuilder), error);
1749 goto_if_nok (error, leave);
1750 MonoClass *owner;
1751 owner = mono_class_from_mono_type_internal (type);
1752 g_assert (mono_class_is_gtd (owner));
1753 param->owner = mono_class_get_generic_container (owner);
1756 MonoClass *pklass;
1757 pklass = mono_class_create_generic_parameter ((MonoGenericParam *) param);
1759 result = m_class_get_byval_arg (pklass);
1761 mono_class_set_ref_info (pklass, MONO_HANDLE_CAST (MonoObject, ref_gparam));
1762 mono_image_append_class_to_reflection_info_set (pklass);
1764 MONO_HANDLE_SETVAL (MONO_HANDLE_CAST (MonoReflectionType, ref_gparam), type, MonoType*, result);
1766 leave:
1767 HANDLE_FUNCTION_RETURN_VAL (result);
1770 static MonoType*
1771 mono_type_array_get_and_resolve_raw (MonoArray* array_raw, int idx, MonoError *error)
1773 HANDLE_FUNCTION_ENTER(); /* FIXME callers of mono_type_array_get_and_resolve_raw should use handles */
1774 error_init (error);
1775 MONO_HANDLE_DCL (MonoArray, array);
1776 MonoType *result = mono_type_array_get_and_resolve (array, idx, error);
1777 HANDLE_FUNCTION_RETURN_VAL (result);
1780 MonoType*
1781 mono_reflection_type_handle_mono_type (MonoReflectionTypeHandle ref, MonoError *error)
1783 HANDLE_FUNCTION_ENTER ();
1784 error_init (error);
1786 MonoType* result = NULL;
1788 g_assert (!MONO_HANDLE_IS_NULL (ref));
1789 if (MONO_HANDLE_IS_NULL (ref))
1790 goto leave;
1791 MonoType *t;
1792 t = MONO_HANDLE_GETVAL (ref, type);
1793 if (t) {
1794 result = t;
1795 goto leave;
1798 if (mono_reflection_is_usertype (ref)) {
1799 MONO_HANDLE_ASSIGN (ref, mono_reflection_type_get_underlying_system_type (ref, error));
1800 if (!is_ok (error) || MONO_HANDLE_IS_NULL (ref) || mono_reflection_is_usertype (ref))
1801 goto leave;
1802 t = MONO_HANDLE_GETVAL (ref, type);
1803 if (t) {
1804 result = t;
1805 goto leave;
1809 MonoClass *klass;
1810 klass = mono_handle_class (ref);
1812 if (is_sre_array (klass)) {
1813 MonoReflectionArrayTypeHandle sre_array = MONO_HANDLE_CAST (MonoReflectionArrayType, ref);
1814 MonoReflectionTypeHandle ref_element = MONO_HANDLE_NEW_GET (MonoReflectionType, sre_array, element_type);
1815 MonoType *base = mono_reflection_type_handle_mono_type (ref_element, error);
1816 goto_if_nok (error, leave);
1817 g_assert (base);
1818 gint32 rank = MONO_HANDLE_GETVAL (sre_array, rank);
1819 MonoClass *eclass = mono_class_from_mono_type_internal (base);
1820 result = mono_image_new0 (eclass->image, MonoType, 1);
1821 if (rank == 0) {
1822 result->type = MONO_TYPE_SZARRAY;
1823 result->data.klass = eclass;
1824 } else {
1825 MonoArrayType *at = (MonoArrayType *)mono_image_alloc0 (eclass->image, sizeof (MonoArrayType));
1826 result->type = MONO_TYPE_ARRAY;
1827 result->data.array = at;
1828 at->eklass = eclass;
1829 at->rank = rank;
1831 MONO_HANDLE_SETVAL (ref, type, MonoType*, result);
1832 } else if (is_sre_byref (klass)) {
1833 MonoReflectionDerivedTypeHandle sre_byref = MONO_HANDLE_CAST (MonoReflectionDerivedType, ref);
1834 MonoReflectionTypeHandle ref_element = MONO_HANDLE_NEW_GET (MonoReflectionType, sre_byref, element_type);
1835 MonoType *base = mono_reflection_type_handle_mono_type (ref_element, error);
1836 goto_if_nok (error, leave);
1837 g_assert (base);
1838 result = &mono_class_from_mono_type_internal (base)->this_arg;
1839 MONO_HANDLE_SETVAL (ref, type, MonoType*, result);
1840 } else if (is_sre_pointer (klass)) {
1841 MonoReflectionDerivedTypeHandle sre_pointer = MONO_HANDLE_CAST (MonoReflectionDerivedType, ref);
1842 MonoReflectionTypeHandle ref_element = MONO_HANDLE_NEW_GET (MonoReflectionType, sre_pointer, 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 = m_class_get_byval_arg (mono_class_create_ptr (base));
1847 MONO_HANDLE_SETVAL (ref, type, MonoType*, result);
1848 } else if (is_sre_generic_instance (klass)) {
1849 result = reflection_instance_handle_mono_type (MONO_HANDLE_CAST (MonoReflectionGenericClass, ref), error);
1850 } else if (is_sre_gparam_builder (klass)) {
1851 result = reflection_param_handle_mono_type (MONO_HANDLE_CAST (MonoReflectionGenericParam, ref), error);
1852 } else if (is_sre_enum_builder (klass)) {
1853 MonoReflectionEnumBuilderHandle ref_ebuilder = MONO_HANDLE_CAST (MonoReflectionEnumBuilder, ref);
1855 MonoReflectionTypeHandle ref_tb = MONO_HANDLE_CAST (MonoReflectionType, MONO_HANDLE_NEW_GET (MonoReflectionTypeBuilder, ref_ebuilder, tb));
1856 result = mono_reflection_type_handle_mono_type (ref_tb, error);
1857 } else if (is_sre_type_builder (klass)) {
1858 MonoReflectionTypeBuilderHandle ref_tb = MONO_HANDLE_CAST (MonoReflectionTypeBuilder, ref);
1860 /* This happens when a finished type references an unfinished one. Have to create the minimal type */
1861 reflection_setup_internal_class (ref_tb, error);
1862 mono_error_assert_ok (error);
1863 result = MONO_HANDLE_GETVAL (ref, type);
1864 } else {
1865 g_error ("Cannot handle corlib user type %s", mono_type_full_name (m_class_get_byval_arg (mono_handle_class (ref))));
1867 leave:
1868 HANDLE_FUNCTION_RETURN_VAL (result);
1872 * LOCKING: Assumes the loader lock is held.
1874 static MonoMethodSignature*
1875 parameters_to_signature (MonoImage *image, MonoArrayHandle parameters, MonoArrayHandle required_modifiers, MonoArrayHandle optional_modifiers, MonoError *error) {
1876 MonoMethodSignature *sig;
1877 int count, i;
1879 error_init (error);
1881 count = MONO_HANDLE_IS_NULL (parameters) ? 0 : mono_array_handle_length (parameters);
1883 sig = (MonoMethodSignature *)mono_image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
1884 sig->param_count = count;
1885 sig->sentinelpos = -1; /* FIXME */
1886 for (i = 0; i < count; ++i) {
1887 sig->params [i] = mono_type_array_get_and_resolve_with_modifiers (parameters, required_modifiers, optional_modifiers, i, image, error);
1888 if (!is_ok (error)) {
1889 image_g_free (image, sig);
1890 return NULL;
1893 return sig;
1897 * LOCKING: Assumes the loader lock is held.
1899 static MonoMethodSignature*
1900 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilderHandle ctor, MonoError *error) {
1901 MonoMethodSignature *sig;
1903 error_init (error);
1904 MonoArrayHandle params = MONO_HANDLE_NEW_GET(MonoArray, ctor, parameters);
1905 MonoArrayHandle required_modifiers = MONO_HANDLE_NEW_GET(MonoArray, ctor, param_modreq);
1906 MonoArrayHandle optional_modifiers = MONO_HANDLE_NEW_GET(MonoArray, ctor, param_modopt);
1908 sig = parameters_to_signature (image, params, required_modifiers, optional_modifiers, error);
1909 return_val_if_nok (error, NULL);
1910 sig->hasthis = MONO_HANDLE_GETVAL (ctor, attrs) & METHOD_ATTRIBUTE_STATIC? 0: 1;
1911 sig->ret = mono_get_void_type ();
1912 return sig;
1915 static MonoMethodSignature*
1916 ctor_builder_to_signature_raw (MonoImage *image, MonoReflectionCtorBuilder* ctor_raw, MonoError *error) {
1917 HANDLE_FUNCTION_ENTER();
1918 MONO_HANDLE_DCL (MonoReflectionCtorBuilder, ctor);
1919 MonoMethodSignature *sig = ctor_builder_to_signature (image, ctor, error);
1920 HANDLE_FUNCTION_RETURN_VAL (sig);
1923 * LOCKING: Assumes the loader lock is held.
1925 static MonoMethodSignature*
1926 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilderHandle method, MonoError *error) {
1927 MonoMethodSignature *sig;
1929 error_init (error);
1930 MonoArrayHandle params = MONO_HANDLE_NEW_GET(MonoArray, method, parameters);
1931 MonoArrayHandle required_modifiers = MONO_HANDLE_NEW_GET(MonoArray, method, param_modreq);
1932 MonoArrayHandle optional_modifiers = MONO_HANDLE_NEW_GET(MonoArray, method, param_modopt);
1934 sig = parameters_to_signature (image, params, required_modifiers, optional_modifiers, error);
1935 return_val_if_nok (error, NULL);
1936 sig->hasthis = MONO_HANDLE_GETVAL (method, attrs) & METHOD_ATTRIBUTE_STATIC? 0: 1;
1937 MonoReflectionTypeHandle rtype;
1938 rtype = MONO_HANDLE_CAST (MonoReflectionType, MONO_HANDLE_NEW_GET (MonoObject, method, rtype));
1939 if (!MONO_HANDLE_IS_NULL (rtype)) {
1940 sig->ret = mono_reflection_type_handle_mono_type (rtype, error);
1941 if (!is_ok (error)) {
1942 image_g_free (image, sig);
1943 return NULL;
1945 } else {
1946 sig->ret = mono_get_void_type ();
1948 MonoArrayHandle generic_params = MONO_HANDLE_NEW_GET (MonoArray, method, generic_params);
1949 sig->generic_param_count = MONO_HANDLE_IS_NULL (generic_params) ? 0 : mono_array_handle_length (generic_params);
1950 return sig;
1953 static MonoMethodSignature*
1954 dynamic_method_to_signature (MonoReflectionDynamicMethodHandle method, MonoError *error)
1956 HANDLE_FUNCTION_ENTER ();
1957 MonoMethodSignature *sig = NULL;
1959 error_init (error);
1961 sig = parameters_to_signature (NULL, MONO_HANDLE_NEW_GET (MonoArray, method, parameters),
1962 MONO_HANDLE_CAST (MonoArray, NULL_HANDLE), MONO_HANDLE_CAST (MonoArray, NULL_HANDLE), error);
1963 goto_if_nok (error, leave);
1964 sig->hasthis = MONO_HANDLE_GETVAL (method, attrs) & METHOD_ATTRIBUTE_STATIC? 0: 1;
1965 MonoReflectionTypeHandle rtype;
1966 rtype = MONO_HANDLE_NEW_GET (MonoReflectionType, method, rtype);
1967 if (!MONO_HANDLE_IS_NULL (rtype)) {
1968 sig->ret = mono_reflection_type_handle_mono_type (rtype, error);
1969 if (!is_ok (error)) {
1970 g_free (sig);
1971 sig = NULL;
1972 goto leave;
1974 } else {
1975 sig->ret = mono_get_void_type ();
1977 sig->generic_param_count = 0;
1978 leave:
1979 HANDLE_FUNCTION_RETURN_VAL (sig);
1982 static void
1983 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type, MonoError *error)
1985 error_init (error);
1986 MonoClass *klass = mono_object_class (prop);
1987 if (strcmp (klass->name, "PropertyBuilder") == 0) {
1988 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
1989 *name = mono_string_to_utf8_checked_internal (pb->name, error);
1990 return_if_nok (error);
1991 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type, error);
1992 } else {
1993 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
1994 *name = g_strdup (p->property->name);
1995 if (p->property->get)
1996 *type = mono_method_signature_internal (p->property->get)->ret;
1997 else
1998 *type = mono_method_signature_internal (p->property->set)->params [mono_method_signature_internal (p->property->set)->param_count - 1];
2002 static void
2003 get_field_name_and_type (MonoObject *field, char **name, MonoType **type, MonoError *error)
2005 error_init (error);
2006 MonoClass *klass = mono_object_class (field);
2007 if (strcmp (klass->name, "FieldBuilder") == 0) {
2008 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
2009 *name = mono_string_to_utf8_checked_internal (fb->name, error);
2010 return_if_nok (error);
2011 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
2012 } else {
2013 MonoReflectionField *f = (MonoReflectionField *)field;
2014 *name = g_strdup (mono_field_get_name (f->field));
2015 *type = f->field->type;
2019 #else /* DISABLE_REFLECTION_EMIT */
2021 static gboolean
2022 is_sre_type_builder (MonoClass *klass)
2024 return FALSE;
2027 static gboolean
2028 is_sre_generic_instance (MonoClass *klass)
2030 return FALSE;
2033 gboolean
2034 mono_is_sre_ctor_builder (MonoClass *klass)
2036 return FALSE;
2039 gboolean
2040 mono_is_sre_method_on_tb_inst (MonoClass *klass)
2042 return FALSE;
2045 gboolean
2046 mono_is_sre_ctor_on_tb_inst (MonoClass *klass)
2048 return FALSE;
2051 #endif /* !DISABLE_REFLECTION_EMIT */
2054 static gboolean
2055 is_sr_mono_field (MonoClass *klass)
2057 check_corlib_type_cached (klass, "System.Reflection", "MonoField");
2060 gboolean
2061 mono_is_sr_mono_property (MonoClass *klass)
2063 check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
2066 static gboolean
2067 is_sr_mono_method (MonoClass *klass)
2069 check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
2072 gboolean
2073 mono_is_sr_mono_cmethod (MonoClass *klass)
2075 check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
2078 gboolean
2079 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
2081 return is_sr_mono_method (klass) || mono_is_sr_mono_cmethod (klass);
2084 gboolean
2085 mono_is_sre_type_builder (MonoClass *klass)
2087 return is_sre_type_builder (klass);
2090 gboolean
2091 mono_is_sre_generic_instance (MonoClass *klass)
2093 return is_sre_generic_instance (klass);
2099 * encode_cattr_value:
2100 * Encode a value in a custom attribute stream of bytes.
2101 * The value to encode is either supplied as an object in argument val
2102 * (valuetypes are boxed), or as a pointer to the data in the
2103 * argument argval.
2104 * @type represents the type of the value
2105 * @buffer is the start of the buffer
2106 * @p the current position in the buffer
2107 * @buflen contains the size of the buffer and is used to return the new buffer size
2108 * if this needs to be realloced.
2109 * @retbuffer and @retp return the start and the position of the buffer
2110 * @error set on error.
2112 static void
2113 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, gconstpointer void_argval, MonoError *error)
2115 const char *argval = (const char*)void_argval;
2116 MonoTypeEnum simple_type;
2118 error_init (error);
2119 if ((p-buffer) + 10 >= *buflen) {
2120 char *newbuf;
2121 *buflen *= 2;
2122 newbuf = (char *)g_realloc (buffer, *buflen);
2123 p = newbuf + (p-buffer);
2124 buffer = newbuf;
2126 if (!argval)
2127 argval = (const char*)mono_object_get_data (arg);
2128 simple_type = type->type;
2129 handle_enum:
2130 switch (simple_type) {
2131 case MONO_TYPE_BOOLEAN:
2132 case MONO_TYPE_U1:
2133 case MONO_TYPE_I1:
2134 *p++ = *argval;
2135 break;
2136 case MONO_TYPE_CHAR:
2137 case MONO_TYPE_U2:
2138 case MONO_TYPE_I2:
2139 swap_with_size (p, argval, 2, 1);
2140 p += 2;
2141 break;
2142 case MONO_TYPE_U4:
2143 case MONO_TYPE_I4:
2144 case MONO_TYPE_R4:
2145 swap_with_size (p, argval, 4, 1);
2146 p += 4;
2147 break;
2148 case MONO_TYPE_R8:
2149 swap_with_size (p, argval, 8, 1);
2150 p += 8;
2151 break;
2152 case MONO_TYPE_U8:
2153 case MONO_TYPE_I8:
2154 swap_with_size (p, argval, 8, 1);
2155 p += 8;
2156 break;
2157 case MONO_TYPE_VALUETYPE:
2158 if (type->data.klass->enumtype) {
2159 simple_type = mono_class_enum_basetype_internal (type->data.klass)->type;
2160 goto handle_enum;
2161 } else {
2162 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
2164 break;
2165 case MONO_TYPE_STRING: {
2166 char *str;
2167 guint32 slen;
2168 if (!arg) {
2169 *p++ = 0xFF;
2170 break;
2172 str = mono_string_to_utf8_checked_internal ((MonoString*)arg, error);
2173 return_if_nok (error);
2174 slen = strlen (str);
2175 if ((p-buffer) + 10 + slen >= *buflen) {
2176 char *newbuf;
2177 *buflen *= 2;
2178 *buflen += slen;
2179 newbuf = (char *)g_realloc (buffer, *buflen);
2180 p = newbuf + (p-buffer);
2181 buffer = newbuf;
2183 mono_metadata_encode_value (slen, p, &p);
2184 memcpy (p, str, slen);
2185 p += slen;
2186 g_free (str);
2187 break;
2189 case MONO_TYPE_CLASS: {
2190 char *str;
2191 guint32 slen;
2192 MonoType *arg_type;
2193 if (!arg) {
2194 *p++ = 0xFF;
2195 break;
2197 handle_type:
2198 arg_type = mono_reflection_type_get_handle ((MonoReflectionType*)arg, error);
2199 return_if_nok (error);
2201 str = type_get_qualified_name (arg_type, NULL);
2202 slen = strlen (str);
2203 if ((p-buffer) + 10 + slen >= *buflen) {
2204 char *newbuf;
2205 *buflen *= 2;
2206 *buflen += slen;
2207 newbuf = (char *)g_realloc (buffer, *buflen);
2208 p = newbuf + (p-buffer);
2209 buffer = newbuf;
2211 mono_metadata_encode_value (slen, p, &p);
2212 memcpy (p, str, slen);
2213 p += slen;
2214 g_free (str);
2215 break;
2217 case MONO_TYPE_SZARRAY: {
2218 int len, i;
2219 MonoClass *eclass, *arg_eclass;
2221 if (!arg) {
2222 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
2223 break;
2225 len = mono_array_length_internal ((MonoArray*)arg);
2226 *p++ = len & 0xff;
2227 *p++ = (len >> 8) & 0xff;
2228 *p++ = (len >> 16) & 0xff;
2229 *p++ = (len >> 24) & 0xff;
2230 *retp = p;
2231 *retbuffer = buffer;
2232 eclass = type->data.klass;
2233 arg_eclass = mono_object_class (arg)->element_class;
2235 if (!eclass) {
2236 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
2237 eclass = mono_defaults.object_class;
2239 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
2240 char *elptr = mono_array_addr_internal ((MonoArray*)arg, char, 0);
2241 int elsize = mono_class_array_element_size (arg_eclass);
2242 for (i = 0; i < len; ++i) {
2243 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, m_class_get_byval_arg (arg_eclass), NULL, elptr, error);
2244 return_if_nok (error);
2245 elptr += elsize;
2247 } else if (eclass->valuetype && arg_eclass->valuetype) {
2248 char *elptr = mono_array_addr_internal ((MonoArray*)arg, char, 0);
2249 int elsize = mono_class_array_element_size (eclass);
2250 for (i = 0; i < len; ++i) {
2251 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, m_class_get_byval_arg (eclass), NULL, elptr, error);
2252 return_if_nok (error);
2253 elptr += elsize;
2255 } else {
2256 for (i = 0; i < len; ++i) {
2257 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);
2258 return_if_nok (error);
2261 break;
2263 case MONO_TYPE_OBJECT: {
2264 MonoClass *klass;
2265 char *str;
2266 guint32 slen;
2269 * The parameter type is 'object' but the type of the actual
2270 * argument is not. So we have to add type information to the blob
2271 * too. This is completely undocumented in the spec.
2274 if (arg == NULL) {
2275 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
2276 *p++ = 0xFF;
2277 break;
2280 klass = mono_object_class (arg);
2282 if (mono_object_isinst_checked (arg, mono_defaults.systemtype_class, error)) {
2283 *p++ = 0x50;
2284 goto handle_type;
2285 } else {
2286 return_if_nok (error);
2289 MonoType *klass_byval_arg = m_class_get_byval_arg (klass);
2290 if (klass->enumtype) {
2291 *p++ = 0x55;
2292 } else if (klass == mono_defaults.string_class) {
2293 simple_type = MONO_TYPE_STRING;
2294 *p++ = 0x0E;
2295 goto handle_enum;
2296 } else if (klass->rank == 1) {
2297 *p++ = 0x1D;
2298 if (m_class_get_byval_arg (m_class_get_element_class (klass))->type == MONO_TYPE_OBJECT)
2299 /* See Partition II, Appendix B3 */
2300 *p++ = 0x51;
2301 else
2302 *p++ = m_class_get_byval_arg (m_class_get_element_class (klass))->type;
2303 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, klass_byval_arg, arg, NULL, error);
2304 return_if_nok (error);
2305 break;
2306 } else if (klass_byval_arg->type >= MONO_TYPE_BOOLEAN && klass_byval_arg->type <= MONO_TYPE_R8) {
2307 *p++ = simple_type = klass_byval_arg->type;
2308 goto handle_enum;
2309 } else {
2310 g_error ("unhandled type in custom attr");
2312 str = type_get_qualified_name (m_class_get_byval_arg (klass), NULL);
2313 slen = strlen (str);
2314 if ((p-buffer) + 10 + slen >= *buflen) {
2315 char *newbuf;
2316 *buflen *= 2;
2317 *buflen += slen;
2318 newbuf = (char *)g_realloc (buffer, *buflen);
2319 p = newbuf + (p-buffer);
2320 buffer = newbuf;
2322 mono_metadata_encode_value (slen, p, &p);
2323 memcpy (p, str, slen);
2324 p += slen;
2325 g_free (str);
2326 simple_type = mono_class_enum_basetype_internal (klass)->type;
2327 goto handle_enum;
2329 default:
2330 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
2332 *retp = p;
2333 *retbuffer = buffer;
2336 static void
2337 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
2339 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
2340 char *str = type_get_qualified_name (type, NULL);
2341 int slen = strlen (str);
2343 *p++ = 0x55;
2345 * This seems to be optional...
2346 * *p++ = 0x80;
2348 mono_metadata_encode_value (slen, p, &p);
2349 memcpy (p, str, slen);
2350 p += slen;
2351 g_free (str);
2352 } else if (type->type == MONO_TYPE_OBJECT) {
2353 *p++ = 0x51;
2354 } else if (type->type == MONO_TYPE_CLASS) {
2355 /* it should be a type: encode_cattr_value () has the check */
2356 *p++ = 0x50;
2357 } else {
2358 mono_metadata_encode_value (type->type, p, &p);
2359 if (type->type == MONO_TYPE_SZARRAY)
2360 /* See the examples in Partition VI, Annex B */
2361 encode_field_or_prop_type (m_class_get_byval_arg (type->data.klass), p, &p);
2364 *retp = p;
2367 #ifndef DISABLE_REFLECTION_EMIT
2368 static void
2369 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value, MonoError *error)
2371 int len;
2373 error_init (error);
2375 /* Preallocate a large enough buffer */
2376 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
2377 char *str = type_get_qualified_name (type, NULL);
2378 len = strlen (str);
2379 g_free (str);
2380 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
2381 char *str = type_get_qualified_name (m_class_get_byval_arg (type->data.klass), NULL);
2382 len = strlen (str);
2383 g_free (str);
2384 } else {
2385 len = 0;
2387 len += strlen (name);
2389 if ((p-buffer) + 20 + len >= *buflen) {
2390 char *newbuf;
2391 *buflen *= 2;
2392 *buflen += len;
2393 newbuf = (char *)g_realloc (buffer, *buflen);
2394 p = newbuf + (p-buffer);
2395 buffer = newbuf;
2398 encode_field_or_prop_type (type, p, &p);
2400 len = strlen (name);
2401 mono_metadata_encode_value (len, p, &p);
2402 memcpy (p, name, len);
2403 p += len;
2404 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL, error);
2405 return_if_nok (error);
2406 *retp = p;
2407 *retbuffer = buffer;
2411 * mono_reflection_get_custom_attrs_blob:
2412 * \param ctor custom attribute constructor
2413 * \param ctorArgs arguments o the constructor
2414 * \param properties
2415 * \param propValues
2416 * \param fields
2417 * \param fieldValues
2418 * Creates the blob of data that needs to be saved in the metadata and that represents
2419 * the custom attributed described by \p ctor, \p ctorArgs etc.
2420 * \returns a \c Byte array representing the blob of data.
2422 MonoArray*
2423 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
2425 ERROR_DECL (error);
2426 MonoArray *result = mono_reflection_get_custom_attrs_blob_checked (assembly, ctor, ctorArgs, properties, propValues, fields, fieldValues, error);
2427 mono_error_cleanup (error);
2428 return result;
2432 * mono_reflection_get_custom_attrs_blob_checked:
2433 * \param ctor custom attribute constructor
2434 * \param ctorArgs arguments o the constructor
2435 * \param properties
2436 * \param propValues
2437 * \param fields
2438 * \param fieldValues
2439 * \param error set on error
2440 * Creates the blob of data that needs to be saved in the metadata and that represents
2441 * the custom attributed described by \p ctor, \p ctorArgs etc.
2442 * \returns a \c Byte array representing the blob of data. On failure returns NULL and sets \p error.
2444 MonoArray*
2445 mono_reflection_get_custom_attrs_blob_checked (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues, MonoError *error)
2447 MonoArray *result = NULL;
2448 MonoMethodSignature *sig;
2449 MonoObject *arg;
2450 char *buffer, *p;
2451 guint32 buflen, i;
2453 error_init (error);
2455 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
2456 /* sig is freed later so allocate it in the heap */
2457 sig = ctor_builder_to_signature_raw (NULL, (MonoReflectionCtorBuilder*)ctor, error); /* FIXME use handles */
2458 if (!is_ok (error)) {
2459 g_free (sig);
2460 return NULL;
2462 } else {
2463 sig = mono_method_signature_internal (((MonoReflectionMethod*)ctor)->method);
2466 g_assert (mono_array_length_internal (ctorArgs) == sig->param_count);
2467 buflen = 256;
2468 p = buffer = (char *)g_malloc (buflen);
2469 /* write the prolog */
2470 *p++ = 1;
2471 *p++ = 0;
2472 for (i = 0; i < sig->param_count; ++i) {
2473 arg = mono_array_get_internal (ctorArgs, MonoObject*, i);
2474 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL, error);
2475 goto_if_nok (error, leave);
2477 i = 0;
2478 if (properties)
2479 i += mono_array_length_internal (properties);
2480 if (fields)
2481 i += mono_array_length_internal (fields);
2482 *p++ = i & 0xff;
2483 *p++ = (i >> 8) & 0xff;
2484 if (properties) {
2485 MonoObject *prop;
2486 for (i = 0; i < mono_array_length_internal (properties); ++i) {
2487 MonoType *ptype;
2488 char *pname;
2490 prop = (MonoObject *)mono_array_get_internal (properties, gpointer, i);
2491 get_prop_name_and_type (prop, &pname, &ptype, error);
2492 goto_if_nok (error, leave);
2493 *p++ = 0x54; /* PROPERTY signature */
2494 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get_internal (propValues, gpointer, i), error);
2495 g_free (pname);
2496 goto_if_nok (error, leave);
2500 if (fields) {
2501 MonoObject *field;
2502 for (i = 0; i < mono_array_length_internal (fields); ++i) {
2503 MonoType *ftype;
2504 char *fname;
2506 field = (MonoObject *)mono_array_get_internal (fields, gpointer, i);
2507 get_field_name_and_type (field, &fname, &ftype, error);
2508 goto_if_nok (error, leave);
2509 *p++ = 0x53; /* FIELD signature */
2510 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get_internal (fieldValues, gpointer, i), error);
2511 g_free (fname);
2512 goto_if_nok (error, leave);
2516 g_assert (p - buffer <= buflen);
2517 buflen = p - buffer;
2518 result = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, buflen, error);
2519 goto_if_nok (error, leave);
2520 p = mono_array_addr_internal (result, char, 0);
2521 memcpy (p, buffer, buflen);
2522 leave:
2523 g_free (buffer);
2524 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
2525 g_free (sig);
2526 return result;
2529 static gboolean
2530 reflection_setup_class_hierarchy (GHashTable *unparented, MonoError *error)
2532 error_init (error);
2534 mono_loader_lock ();
2536 MonoType *parent_type;
2537 MonoType *child_type;
2538 GHashTableIter iter;
2540 g_hash_table_iter_init (&iter, unparented);
2542 while (g_hash_table_iter_next (&iter, (gpointer *) &child_type, (gpointer *) &parent_type)) {
2543 MonoClass *child_class = mono_class_from_mono_type_internal (child_type);
2544 if (parent_type != NULL) {
2545 MonoClass *parent_class = mono_class_from_mono_type_internal (parent_type);
2546 child_class->parent = NULL;
2547 /* fool mono_class_setup_parent */
2548 child_class->supertypes = NULL;
2549 mono_class_setup_parent (child_class, parent_class);
2550 } else if (strcmp (child_class->name, "Object") == 0 && strcmp (child_class->name_space, "System") == 0) {
2551 const char *old_n = child_class->name;
2552 /* trick to get relative numbering right when compiling corlib */
2553 child_class->name = "BuildingObject";
2554 mono_class_setup_parent (child_class, mono_defaults.object_class);
2555 child_class->name = old_n;
2557 mono_class_setup_mono_type (child_class);
2558 mono_class_setup_supertypes (child_class);
2561 mono_loader_unlock ();
2562 return is_ok (error);
2565 static gboolean
2566 reflection_setup_internal_class_internal (MonoReflectionTypeBuilderHandle ref_tb, MonoError *error)
2568 HANDLE_FUNCTION_ENTER ();
2569 error_init (error);
2571 mono_loader_lock ();
2573 gint32 entering_state = MONO_HANDLE_GETVAL (MONO_HANDLE_CAST (MonoReflectionTypeBuilder, ref_tb), state);
2574 if (entering_state != MonoTypeBuilderNew) {
2575 g_assert (MONO_HANDLE_GETVAL (MONO_HANDLE_CAST (MonoReflectionType, ref_tb), type));
2576 goto leave;
2579 MONO_HANDLE_SETVAL (ref_tb, state, MonoTypeBuilderState, MonoTypeBuilderEntered);
2580 MonoReflectionModuleBuilderHandle module_ref;
2581 module_ref = MONO_HANDLE_NEW_GET (MonoReflectionModuleBuilder, ref_tb, module);
2582 GHashTable *unparented_classes;
2583 unparented_classes = MONO_HANDLE_GETVAL(module_ref, unparented_classes);
2585 // If this type is already setup, exit. We'll fix the parenting later
2586 MonoType *type;
2587 type = MONO_HANDLE_GETVAL (MONO_HANDLE_CAST (MonoReflectionType, ref_tb), type);
2588 if (type)
2589 goto leave;
2591 MonoReflectionModuleBuilderHandle ref_module;
2592 ref_module = MONO_HANDLE_NEW_GET (MonoReflectionModuleBuilder, ref_tb, module);
2593 MonoDynamicImage *dynamic_image;
2594 dynamic_image = MONO_HANDLE_GETVAL (ref_module, dynamic_image);
2596 MonoStringHandle ref_name;
2597 ref_name = MONO_HANDLE_NEW_GET (MonoString, ref_tb, name);
2598 MonoStringHandle ref_nspace;
2599 ref_nspace = MONO_HANDLE_NEW_GET (MonoString, ref_tb, nspace);
2601 guint32 table_idx;
2602 table_idx = MONO_HANDLE_GETVAL (ref_tb, table_idx);
2604 * The size calculation here warrants some explaining.
2605 * reflection_setup_internal_class is called too early, well before we know whether the type will be a GTD or DEF,
2606 * meaning we need to alloc enough space to morth a def into a gtd.
2608 MonoClass *klass;
2609 klass = (MonoClass *)mono_image_alloc0 (&dynamic_image->image, MAX (sizeof (MonoClassDef), sizeof (MonoClassGtd)));
2610 klass->class_kind = MONO_CLASS_DEF;
2612 klass->image = &dynamic_image->image;
2614 klass->inited = 1; /* we lie to the runtime */
2615 klass->name = mono_string_to_utf8_image (klass->image, ref_name, error);
2616 goto_if_nok (error, leave);
2617 klass->name_space = mono_string_to_utf8_image (klass->image, ref_nspace, error);
2618 goto_if_nok (error, leave);
2619 klass->type_token = MONO_TOKEN_TYPE_DEF | table_idx;
2620 mono_class_set_flags (klass, MONO_HANDLE_GETVAL (ref_tb, attrs));
2622 MONO_PROFILER_RAISE (class_loading, (klass));
2624 klass->element_class = klass;
2626 g_assert (!mono_class_has_ref_info (klass));
2627 mono_class_set_ref_info (klass, MONO_HANDLE_CAST (MonoObject, ref_tb));
2629 MonoReflectionTypeHandle ref_nesting_type;
2630 ref_nesting_type = MONO_HANDLE_NEW_GET (MonoReflectionType, ref_tb, nesting_type);
2631 /* Put into cache so mono_class_get_checked () will find it.
2632 Skip nested types as those should not be available on the global scope. */
2633 if (MONO_HANDLE_IS_NULL (ref_nesting_type))
2634 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, table_idx);
2637 We must register all types as we cannot rely on the name_cache hashtable since we find the class
2638 by performing a mono_class_get which does the full resolution.
2640 Working around this semantics would require us to write a lot of code for no clear advantage.
2642 mono_image_append_class_to_reflection_info_set (klass);
2644 mono_dynamic_image_register_token (dynamic_image, MONO_TOKEN_TYPE_DEF | table_idx, MONO_HANDLE_CAST (MonoObject, ref_tb), MONO_DYN_IMAGE_TOK_NEW);
2646 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
2647 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
2648 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
2649 klass->instance_size = MONO_ABI_SIZEOF (MonoObject);
2650 klass->size_inited = 1;
2651 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
2654 mono_class_setup_mono_type (klass);
2657 * FIXME: handle interfaces.
2659 MonoReflectionTypeHandle ref_tb_type;
2660 ref_tb_type = MONO_HANDLE_CAST (MonoReflectionType, ref_tb);
2661 MONO_HANDLE_SETVAL (ref_tb_type, type, MonoType*, m_class_get_byval_arg (klass));
2662 MONO_HANDLE_SETVAL (ref_tb, state, gint32, MonoTypeBuilderFinished);
2664 reflection_init_generic_class (ref_tb, error);
2665 goto_if_nok (error, leave);
2667 // Do here so that the search inside of the parent can see the above type that's been set.
2668 MonoReflectionTypeHandle ref_parent;
2669 ref_parent = MONO_HANDLE_CAST (MonoReflectionType, MONO_HANDLE_NEW_GET (MonoObject, ref_tb, parent));
2670 MonoType *parent_type;
2671 parent_type = NULL;
2672 if (!MONO_HANDLE_IS_NULL (ref_parent)) {
2673 MonoClass *parent_klass = mono_handle_class (ref_parent);
2674 gboolean recursive_init = TRUE;
2676 if (is_sre_type_builder (parent_klass)) {
2677 MonoTypeBuilderState parent_state = (MonoTypeBuilderState)MONO_HANDLE_GETVAL (MONO_HANDLE_CAST (MonoReflectionTypeBuilder, ref_parent), state);
2679 if (parent_state != MonoTypeBuilderNew) {
2680 // Initialize types reachable from parent recursively
2681 // We'll fix the type hierarchy later
2682 recursive_init = FALSE;
2686 if (recursive_init) {
2687 // If we haven't encountered a cycle, force the creation of ref_parent's type
2688 mono_reflection_type_handle_mono_type (ref_parent, error);
2689 goto_if_nok (error, leave);
2692 parent_type = MONO_HANDLE_GETVAL (ref_parent, type);
2694 // If we failed to create the parent, fail the child
2695 if (!parent_type)
2696 goto leave;
2699 // Push the child type and parent type to process later
2700 // Note: parent_type may be null.
2701 g_assert (!g_hash_table_lookup (unparented_classes, m_class_get_byval_arg (klass)));
2702 g_hash_table_insert (unparented_classes, m_class_get_byval_arg (klass), parent_type);
2704 if (!MONO_HANDLE_IS_NULL (ref_nesting_type)) {
2705 if (!reflection_setup_internal_class (MONO_HANDLE_CAST (MonoReflectionTypeBuilder, ref_nesting_type), error))
2706 goto leave;
2708 MonoType *nesting_type = mono_reflection_type_handle_mono_type (ref_nesting_type, error);
2709 goto_if_nok (error, leave);
2710 klass->nested_in = mono_class_from_mono_type_internal (nesting_type);
2713 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
2715 MONO_PROFILER_RAISE (class_loaded, (klass));
2717 leave:
2718 mono_loader_unlock ();
2719 HANDLE_FUNCTION_RETURN_VAL (is_ok (error));
2723 * reflection_init_generic_class:
2724 * @tb: a TypeBuilder object
2725 * @error: set on error
2727 * Creates the generic class after all generic parameters have been added.
2728 * On success returns TRUE, on failure returns FALSE and sets @error.
2730 * This assumes that reflection_setup_internal_class has already set up
2731 * ref_tb
2733 static gboolean
2734 reflection_init_generic_class (MonoReflectionTypeBuilderHandle ref_tb, MonoError *error)
2736 HANDLE_FUNCTION_ENTER ();
2738 error_init (error);
2740 MonoTypeBuilderState ref_state = (MonoTypeBuilderState)MONO_HANDLE_GETVAL (ref_tb, state);
2741 g_assert (ref_state == MonoTypeBuilderFinished);
2743 MonoType *type = MONO_HANDLE_GETVAL (MONO_HANDLE_CAST (MonoReflectionType, ref_tb), type);
2744 MonoClass *klass = mono_class_from_mono_type_internal (type);
2746 MonoArrayHandle generic_params = MONO_HANDLE_NEW_GET (MonoArray, ref_tb, generic_params);
2747 int count = MONO_HANDLE_IS_NULL (generic_params) ? 0 : mono_array_handle_length (generic_params);
2749 if (count == 0)
2750 goto leave;
2752 if (mono_class_try_get_generic_container (klass) != NULL)
2753 goto leave; /* already setup */
2755 MonoGenericContainer *generic_container;
2756 generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
2758 generic_container->owner.klass = klass;
2759 generic_container->type_argc = count;
2760 generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
2762 klass->class_kind = MONO_CLASS_GTD;
2763 mono_class_set_generic_container (klass, generic_container);
2766 MonoReflectionGenericParamHandle ref_gparam;
2767 ref_gparam = MONO_HANDLE_NEW (MonoReflectionGenericParam, NULL);
2768 for (int i = 0; i < count; i++) {
2769 MONO_HANDLE_ARRAY_GETREF (ref_gparam, generic_params, i);
2770 MonoType *param_type = mono_reflection_type_handle_mono_type (MONO_HANDLE_CAST (MonoReflectionType, ref_gparam), error);
2771 goto_if_nok (error, leave);
2772 MonoGenericParamFull *param = (MonoGenericParamFull *) param_type->data.generic_param;
2773 generic_container->type_params [i] = *param;
2774 /*Make sure we are a diferent type instance */
2775 generic_container->type_params [i].owner = generic_container;
2776 generic_container->type_params [i].info.pklass = NULL;
2777 generic_container->type_params [i].info.flags = MONO_HANDLE_GETVAL (ref_gparam, attrs);
2779 g_assert (generic_container->type_params [i].owner);
2782 generic_container->context.class_inst = mono_get_shared_generic_inst (generic_container);
2783 MonoGenericContext* context;
2784 context = &generic_container->context;
2785 MonoType *canonical_inst;
2786 canonical_inst = &((MonoClassGtd*)klass)->canonical_inst;
2787 canonical_inst->type = MONO_TYPE_GENERICINST;
2788 canonical_inst->data.generic_class = mono_metadata_lookup_generic_class (klass, context->class_inst, FALSE);
2790 leave:
2791 HANDLE_FUNCTION_RETURN_VAL (is_ok (error));
2794 static MonoMarshalSpec*
2795 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
2796 MonoReflectionMarshal *minfo, MonoError *error)
2798 MonoMarshalSpec *res;
2800 error_init (error);
2802 res = image_g_new0 (image, MonoMarshalSpec, 1);
2803 res->native = (MonoMarshalNative)minfo->type;
2805 switch (minfo->type) {
2806 case MONO_NATIVE_LPARRAY:
2807 res->data.array_data.elem_type = (MonoMarshalNative)minfo->eltype;
2808 if (minfo->has_size) {
2809 res->data.array_data.param_num = minfo->param_num;
2810 res->data.array_data.num_elem = minfo->count;
2811 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
2813 else {
2814 res->data.array_data.param_num = -1;
2815 res->data.array_data.num_elem = -1;
2816 res->data.array_data.elem_mult = -1;
2818 break;
2820 case MONO_NATIVE_BYVALTSTR:
2821 case MONO_NATIVE_BYVALARRAY:
2822 res->data.array_data.num_elem = minfo->count;
2823 break;
2825 case MONO_NATIVE_CUSTOM:
2826 if (minfo->marshaltyperef) {
2827 MonoType *marshaltyperef = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, error);
2828 if (!is_ok (error)) {
2829 image_g_free (image, res);
2830 return NULL;
2832 res->data.custom_data.custom_name =
2833 type_get_fully_qualified_name (marshaltyperef);
2835 if (minfo->mcookie) {
2836 res->data.custom_data.cookie = mono_string_to_utf8_checked_internal (minfo->mcookie, error);
2837 if (!is_ok (error)) {
2838 image_g_free (image, res);
2839 return NULL;
2842 break;
2844 default:
2845 break;
2848 return res;
2850 #endif /* !DISABLE_REFLECTION_EMIT */
2852 MonoReflectionMarshalAsAttributeHandle
2853 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
2854 MonoMarshalSpec *spec, MonoError *error)
2856 error_init (error);
2858 MonoReflectionMarshalAsAttributeHandle minfo = MONO_HANDLE_CAST (MonoReflectionMarshalAsAttribute, mono_object_new_handle (domain, mono_class_get_marshal_as_attribute_class (), error));
2859 goto_if_nok (error, fail);
2860 guint32 utype;
2861 utype = spec->native;
2862 MONO_HANDLE_SETVAL (minfo, utype, guint32, utype);
2864 switch (utype) {
2865 case MONO_NATIVE_LPARRAY:
2866 MONO_HANDLE_SETVAL (minfo, array_subtype, guint32, spec->data.array_data.elem_type);
2867 MONO_HANDLE_SETVAL (minfo, size_const, gint32, spec->data.array_data.num_elem);
2868 if (spec->data.array_data.param_num != -1)
2869 MONO_HANDLE_SETVAL (minfo, size_param_index, gint16, spec->data.array_data.param_num);
2870 break;
2872 case MONO_NATIVE_BYVALTSTR:
2873 case MONO_NATIVE_BYVALARRAY:
2874 MONO_HANDLE_SETVAL (minfo, size_const, gint32, spec->data.array_data.num_elem);
2875 break;
2877 case MONO_NATIVE_CUSTOM:
2878 if (spec->data.custom_data.custom_name) {
2879 MonoType *mtype = mono_reflection_type_from_name_checked (spec->data.custom_data.custom_name, klass->image, error);
2880 goto_if_nok (error, fail);
2882 if (mtype) {
2883 MonoReflectionTypeHandle rt = mono_type_get_object_handle (domain, mtype, error);
2884 goto_if_nok (error, fail);
2886 MONO_HANDLE_SET (minfo, marshal_type_ref, rt);
2889 MonoStringHandle custom_name = mono_string_new_handle (domain, spec->data.custom_data.custom_name, error);
2890 goto_if_nok (error, fail);
2891 MONO_HANDLE_SET (minfo, marshal_type, custom_name);
2893 if (spec->data.custom_data.cookie) {
2894 MonoStringHandle cookie = mono_string_new_handle (domain, spec->data.custom_data.cookie, error);
2895 goto_if_nok (error, fail);
2896 MONO_HANDLE_SET (minfo, marshal_cookie, cookie);
2898 break;
2900 default:
2901 break;
2904 return minfo;
2905 fail:
2906 return MONO_HANDLE_NEW (MonoReflectionMarshalAsAttribute, NULL);
2909 #ifndef DISABLE_REFLECTION_EMIT
2910 static MonoMethod*
2911 reflection_methodbuilder_to_mono_method (MonoClass *klass,
2912 ReflectionMethodBuilder *rmb,
2913 MonoMethodSignature *sig,
2914 MonoError *error)
2916 MonoMethod *m;
2917 MonoMethodWrapper *wrapperm;
2918 MonoMarshalSpec **specs = NULL;
2919 MonoReflectionMethodAux *method_aux;
2920 MonoImage *image;
2921 gboolean dynamic;
2922 int i;
2924 error_init (error);
2926 * Methods created using a MethodBuilder should have their memory allocated
2927 * inside the image mempool, while dynamic methods should have their memory
2928 * malloc'd.
2930 dynamic = rmb->refs != NULL;
2931 image = dynamic ? NULL : klass->image;
2933 if (!dynamic)
2934 g_assert (!mono_class_is_ginst (klass));
2936 mono_loader_lock ();
2938 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
2939 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
2940 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
2941 else
2942 m = (MonoMethod *)image_g_new0 (image, MonoDynamicMethod, 1);
2944 wrapperm = (MonoMethodWrapper*)m;
2946 m->dynamic = dynamic;
2947 m->slot = -1;
2948 m->flags = rmb->attrs;
2949 m->iflags = rmb->iattrs;
2950 m->name = string_to_utf8_image_raw (image, rmb->name, error);
2951 goto_if_nok (error, fail);
2952 m->klass = klass;
2953 m->signature = sig;
2954 m->sre_method = TRUE;
2955 m->skip_visibility = rmb->skip_visibility;
2956 if (rmb->table_idx)
2957 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
2959 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
2960 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
2961 m->string_ctor = 1;
2963 m->signature->pinvoke = 1;
2964 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
2965 m->signature->pinvoke = 1;
2967 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
2969 method_aux->dllentry = rmb->dllentry ? string_to_utf8_image_raw (image, rmb->dllentry, error) : image_strdup (image, m->name);
2970 mono_error_assert_ok (error);
2971 method_aux->dll = string_to_utf8_image_raw (image, rmb->dll, error);
2972 mono_error_assert_ok (error);
2974 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
2976 if (image_is_dynamic (klass->image))
2977 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
2979 goto leave;
2981 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
2982 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
2983 MonoMethodHeader *header;
2984 guint32 code_size;
2985 gint32 max_stack, i;
2986 gint32 num_locals = 0;
2987 gint32 num_clauses = 0;
2988 guint8 *code;
2990 if (rmb->ilgen) {
2991 code = mono_array_addr_internal (rmb->ilgen->code, guint8, 0);
2992 code_size = rmb->ilgen->code_len;
2993 max_stack = rmb->ilgen->max_stack;
2994 num_locals = rmb->ilgen->locals ? mono_array_length_internal (rmb->ilgen->locals) : 0;
2995 if (rmb->ilgen->ex_handlers)
2996 num_clauses = mono_reflection_method_count_clauses (rmb->ilgen);
2997 } else {
2998 if (rmb->code) {
2999 code = mono_array_addr_internal (rmb->code, guint8, 0);
3000 code_size = mono_array_length_internal (rmb->code);
3001 /* we probably need to run a verifier on the code... */
3002 max_stack = 8;
3004 else {
3005 code = NULL;
3006 code_size = 0;
3007 max_stack = 8;
3011 header = (MonoMethodHeader *)mono_image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
3012 header->code_size = code_size;
3013 header->code = (const unsigned char *)image_g_malloc (image, code_size);
3014 memcpy ((char*)header->code, code, code_size);
3015 header->max_stack = max_stack;
3016 header->init_locals = rmb->init_locals;
3017 header->num_locals = num_locals;
3019 for (i = 0; i < num_locals; ++i) {
3020 MonoReflectionLocalBuilder *lb =
3021 mono_array_get_internal (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
3023 header->locals [i] = image_g_new0 (image, MonoType, 1);
3024 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)lb->type, error);
3025 mono_error_assert_ok (error);
3026 memcpy (header->locals [i], type, mono_sizeof_type (type));
3029 header->num_clauses = num_clauses;
3030 if (num_clauses) {
3031 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
3032 rmb->ilgen, num_clauses, error);
3033 mono_error_assert_ok (error);
3036 wrapperm->header = header;
3037 MonoDynamicMethod *dm = (MonoDynamicMethod*)wrapperm;
3038 dm->assembly = klass->image->assembly;
3041 if (rmb->generic_params) {
3042 int count = mono_array_length_internal (rmb->generic_params);
3043 MonoGenericContainer *container;
3045 container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
3046 container->is_method = TRUE;
3047 container->is_anonymous = FALSE;
3048 container->type_argc = count;
3049 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
3050 container->owner.method = m;
3052 m->is_generic = TRUE;
3053 mono_method_set_generic_container (m, container);
3055 for (i = 0; i < count; i++) {
3056 MonoReflectionGenericParam *gp =
3057 mono_array_get_internal (rmb->generic_params, MonoReflectionGenericParam*, i);
3058 MonoType *gp_type = mono_reflection_type_get_handle ((MonoReflectionType*)gp, error);
3059 mono_error_assert_ok (error);
3060 MonoGenericParamFull *param = (MonoGenericParamFull *) gp_type->data.generic_param;
3061 container->type_params [i] = *param;
3062 container->type_params [i].owner = container;
3064 gp->type.type->data.generic_param = (MonoGenericParam*)&container->type_params [i];
3066 MonoClass *gklass = mono_class_from_mono_type_internal (gp_type);
3067 gklass->wastypebuilder = TRUE;
3071 * The method signature might have pointers to generic parameters that belong to other methods.
3072 * This is a valid SRE case, but the resulting method signature must be encoded using the proper
3073 * generic parameters.
3075 for (i = 0; i < m->signature->param_count; ++i) {
3076 MonoType *t = m->signature->params [i];
3077 if (t->type == MONO_TYPE_MVAR) {
3078 MonoGenericParam *gparam = t->data.generic_param;
3079 if (gparam->num < count) {
3080 m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
3081 m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
3087 if (mono_class_is_gtd (klass)) {
3088 container->parent = mono_class_get_generic_container (klass);
3089 container->context.class_inst = mono_class_get_generic_container (klass)->context.class_inst;
3091 container->context.method_inst = mono_get_shared_generic_inst (container);
3094 if (rmb->refs) {
3095 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
3096 int i;
3097 void **data;
3099 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
3101 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
3102 data [0] = GUINT_TO_POINTER (rmb->nrefs);
3103 for (i = 0; i < rmb->nrefs; ++i)
3104 data [i + 1] = rmb->refs [i];
3107 method_aux = NULL;
3109 /* Parameter info */
3110 if (rmb->pinfo) {
3111 if (!method_aux)
3112 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
3113 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature_internal (m)->param_count + 1);
3114 for (i = 0; i <= m->signature->param_count; ++i) {
3115 MonoReflectionParamBuilder *pb;
3116 if ((pb = mono_array_get_internal (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
3117 if ((i > 0) && (pb->attrs)) {
3118 /* Make a copy since it might point to a shared type structure */
3119 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
3120 m->signature->params [i - 1]->attrs = pb->attrs;
3123 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
3124 MonoDynamicImage *assembly;
3125 guint32 idx, len;
3126 MonoTypeEnum def_type;
3127 char *p;
3128 const char *p2;
3130 if (!method_aux->param_defaults) {
3131 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
3132 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
3134 assembly = (MonoDynamicImage*)klass->image;
3135 idx = mono_dynimage_encode_constant (assembly, pb->def_value, &def_type);
3136 /* Copy the data from the blob since it might get realloc-ed */
3137 p = assembly->blob.data + idx;
3138 len = mono_metadata_decode_blob_size (p, &p2);
3139 len += p2 - p;
3140 method_aux->param_defaults [i] = (uint8_t *)image_g_malloc (image, len);
3141 method_aux->param_default_types [i] = def_type;
3142 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
3145 if (pb->name) {
3146 method_aux->param_names [i] = string_to_utf8_image_raw (image, pb->name, error);
3147 mono_error_assert_ok (error);
3149 if (pb->cattrs) {
3150 if (!method_aux->param_cattr)
3151 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
3152 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
3158 /* Parameter marshalling */
3159 if (rmb->pinfo)
3160 for (i = 0; i < mono_array_length_internal (rmb->pinfo); ++i) {
3161 MonoReflectionParamBuilder *pb;
3162 if ((pb = mono_array_get_internal (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
3163 if (pb->marshal_info) {
3164 if (specs == NULL)
3165 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
3166 specs [pb->position] =
3167 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info, error);
3168 goto_if_nok (error, fail);
3172 if (specs != NULL) {
3173 if (!method_aux)
3174 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
3175 method_aux->param_marshall = specs;
3178 if (image_is_dynamic (klass->image) && method_aux)
3179 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
3181 leave:
3182 mono_loader_unlock ();
3183 if (!m) // FIXME: This leaks if image is not NULL.
3184 image_g_free (image, specs);
3185 return m;
3187 fail:
3188 m = NULL;
3189 goto leave;
3192 static MonoMethod*
3193 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb, MonoError *error)
3195 ReflectionMethodBuilder rmb;
3196 MonoMethodSignature *sig;
3198 mono_loader_lock ();
3200 if (!mono_reflection_methodbuilder_from_ctor_builder (&rmb, mb, error)) {
3201 mono_loader_unlock ();
3202 return NULL;
3205 g_assert (klass->image != NULL);
3206 sig = ctor_builder_to_signature_raw (klass->image, mb, error); /* FIXME use handles */
3207 mono_loader_unlock ();
3208 return_val_if_nok (error, NULL);
3210 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
3211 return_val_if_nok (error, NULL);
3212 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
3214 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
3215 /* ilgen is no longer needed */
3216 mb->ilgen = NULL;
3219 return mb->mhandle;
3222 static MonoMethod*
3223 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilderHandle ref_mb, MonoError *error)
3225 ReflectionMethodBuilder rmb;
3226 MonoMethodSignature *sig;
3228 error_init (error);
3230 mono_loader_lock ();
3232 MonoReflectionMethodBuilder *mb = MONO_HANDLE_RAW (ref_mb); /* FIXME use handles */
3233 if (!mono_reflection_methodbuilder_from_method_builder (&rmb, mb, error)) {
3234 mono_loader_unlock ();
3235 return NULL;
3238 g_assert (klass->image != NULL);
3239 sig = method_builder_to_signature (klass->image, ref_mb, error);
3240 mono_loader_unlock ();
3241 return_val_if_nok (error, NULL);
3243 MonoMethod *method = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
3244 return_val_if_nok (error, NULL);
3245 MONO_HANDLE_SETVAL (ref_mb, mhandle, MonoMethod*, method);
3246 mono_save_custom_attrs (klass->image, method, mb->cattrs);
3248 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save)
3249 /* ilgen is no longer needed */
3250 mb->ilgen = NULL;
3251 return method;
3254 static MonoMethod*
3255 methodbuilder_to_mono_method_raw (MonoClass *klass, MonoReflectionMethodBuilder* mb_raw, MonoError *error)
3257 HANDLE_FUNCTION_ENTER (); /* FIXME change callers of methodbuilder_to_mono_method_raw to use handles */
3258 error_init (error);
3259 MONO_HANDLE_DCL (MonoReflectionMethodBuilder, mb);
3260 MonoMethod *result = methodbuilder_to_mono_method (klass, mb, error);
3261 HANDLE_FUNCTION_RETURN_VAL (result);
3264 #endif
3266 #ifndef DISABLE_REFLECTION_EMIT
3269 * fix_partial_generic_class:
3270 * @klass: a generic instantiation MonoClass
3271 * @error: set on error
3273 * Assumes that the generic container of @klass has its vtable
3274 * initialized, and updates the parent class, interfaces, methods and
3275 * fields of @klass by inflating the types using the generic context.
3277 * On success returns TRUE, on failure returns FALSE and sets @error.
3280 static gboolean
3281 fix_partial_generic_class (MonoClass *klass, MonoError *error)
3283 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
3284 int i;
3286 error_init (error);
3288 if (klass->wastypebuilder)
3289 return TRUE;
3291 if (klass->parent != gklass->parent) {
3292 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);
3293 if (mono_error_ok (error)) {
3294 MonoClass *parent = mono_class_from_mono_type_internal (parent_type);
3295 mono_metadata_free_type (parent_type);
3296 if (parent != klass->parent) {
3297 /*fool mono_class_setup_parent*/
3298 klass->supertypes = NULL;
3299 mono_class_setup_parent (klass, parent);
3301 } else {
3302 if (gklass->wastypebuilder)
3303 klass->wastypebuilder = TRUE;
3304 return FALSE;
3308 if (!mono_class_get_generic_class (klass)->need_sync)
3309 return TRUE;
3311 int mcount = mono_class_get_method_count (klass);
3312 int gmcount = mono_class_get_method_count (gklass);
3313 if (mcount != gmcount) {
3314 mono_class_set_method_count (klass, gmcount);
3315 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (gmcount + 1));
3317 for (i = 0; i < gmcount; i++) {
3318 klass->methods [i] = mono_class_inflate_generic_method_full_checked (
3319 gklass->methods [i], klass, mono_class_get_context (klass), error);
3320 mono_error_assert_ok (error);
3324 if (klass->interface_count && klass->interface_count != gklass->interface_count) {
3325 klass->interface_count = gklass->interface_count;
3326 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
3327 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
3329 MonoClass **gklass_interfaces = m_class_get_interfaces (gklass);
3330 for (i = 0; i < gklass->interface_count; ++i) {
3331 MonoType *iface_type = mono_class_inflate_generic_type_checked (m_class_get_byval_arg (gklass_interfaces [i]), mono_class_get_context (klass), error);
3332 return_val_if_nok (error, FALSE);
3334 klass->interfaces [i] = mono_class_from_mono_type_internal (iface_type);
3335 mono_metadata_free_type (iface_type);
3337 if (!ensure_runtime_vtable (klass->interfaces [i], error))
3338 return FALSE;
3340 klass->interfaces_inited = 1;
3343 int fcount = mono_class_get_field_count (klass);
3344 int gfcount = mono_class_get_field_count (gklass);
3345 if (fcount != gfcount) {
3346 mono_class_set_field_count (klass, gfcount);
3347 klass->fields = image_g_new0 (klass->image, MonoClassField, gfcount);
3349 for (i = 0; i < gfcount; i++) {
3350 klass->fields [i] = gklass->fields [i];
3351 klass->fields [i].parent = klass;
3352 klass->fields [i].type = mono_class_inflate_generic_type_checked (gklass->fields [i].type, mono_class_get_context (klass), error);
3353 return_val_if_nok (error, FALSE);
3357 /*We can only finish with this klass once it's parent has as well*/
3358 if (gklass->wastypebuilder)
3359 klass->wastypebuilder = TRUE;
3360 return TRUE;
3364 * ensure_generic_class_runtime_vtable:
3365 * @klass a generic class
3366 * @error set on error
3368 * Ensures that the generic container of @klass has a vtable and
3369 * returns TRUE on success. On error returns FALSE and sets @error.
3371 static gboolean
3372 ensure_generic_class_runtime_vtable (MonoClass *klass, MonoError *error)
3374 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
3376 error_init (error);
3378 if (!ensure_runtime_vtable (gklass, error))
3379 return FALSE;
3381 return fix_partial_generic_class (klass, error);
3385 * ensure_runtime_vtable:
3386 * @klass the class
3387 * @error set on error
3389 * Ensures that @klass has a vtable and returns TRUE on success. On
3390 * error returns FALSE and sets @error.
3392 static gboolean
3393 ensure_runtime_vtable (MonoClass *klass, MonoError *error)
3395 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info_raw (klass); /* FIXME use handles */
3396 int i, num, j;
3398 error_init (error);
3400 if (!image_is_dynamic (klass->image) || (!tb && !mono_class_is_ginst (klass)) || klass->wastypebuilder)
3401 return TRUE;
3402 if (klass->parent)
3403 if (!ensure_runtime_vtable (klass->parent, error))
3404 return FALSE;
3406 if (tb) {
3407 num = tb->ctors? mono_array_length_internal (tb->ctors): 0;
3408 num += tb->num_methods;
3409 mono_class_set_method_count (klass, num);
3410 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
3411 num = tb->ctors? mono_array_length_internal (tb->ctors): 0;
3412 for (i = 0; i < num; ++i) {
3413 MonoMethod *ctor = ctorbuilder_to_mono_method (klass, mono_array_get_internal (tb->ctors, MonoReflectionCtorBuilder*, i), error);
3414 if (!ctor)
3415 return FALSE;
3416 klass->methods [i] = ctor;
3418 num = tb->num_methods;
3419 j = i;
3420 for (i = 0; i < num; ++i) {
3421 MonoMethod *meth = methodbuilder_to_mono_method_raw (klass, mono_array_get_internal (tb->methods, MonoReflectionMethodBuilder*, i), error); /* FIXME use handles */
3422 if (!meth)
3423 return FALSE;
3424 klass->methods [j++] = meth;
3427 if (tb->interfaces) {
3428 klass->interface_count = mono_array_length_internal (tb->interfaces);
3429 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
3430 for (i = 0; i < klass->interface_count; ++i) {
3431 MonoType *iface = mono_type_array_get_and_resolve_raw (tb->interfaces, i, error); /* FIXME use handles */
3432 return_val_if_nok (error, FALSE);
3433 klass->interfaces [i] = mono_class_from_mono_type_internal (iface);
3434 if (!ensure_runtime_vtable (klass->interfaces [i], error))
3435 return FALSE;
3437 klass->interfaces_inited = 1;
3439 } else if (mono_class_is_ginst (klass)){
3440 if (!ensure_generic_class_runtime_vtable (klass, error)) {
3441 mono_class_set_type_load_failure (klass, "Could not initialize vtable for generic class due to: %s", mono_error_get_message (error));
3442 return FALSE;
3446 if (mono_class_is_interface (klass) && !mono_class_is_ginst (klass)) {
3447 int slot_num = 0;
3448 int mcount = mono_class_get_method_count (klass);
3449 for (i = 0; i < mcount; ++i) {
3450 MonoMethod *im = klass->methods [i];
3451 if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
3452 im->slot = slot_num++;
3455 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
3456 mono_class_setup_interface_offsets (klass);
3457 mono_class_setup_interface_id (klass);
3461 * The generic vtable is needed even if image->run is not set since some
3462 * runtime code like ves_icall_Type_GetMethodsByName depends on
3463 * method->slot being defined.
3467 * tb->methods could not be freed since it is used for determining
3468 * overrides during dynamic vtable construction.
3471 return TRUE;
3474 static MonoMethod*
3475 mono_reflection_method_get_handle (MonoObject *method, MonoError *error)
3477 error_init (error);
3478 MonoClass *klass = mono_object_class (method);
3479 if (is_sr_mono_method (klass)) {
3480 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
3481 return sr_method->method;
3483 if (is_sre_method_builder (klass)) {
3484 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
3485 return mb->mhandle;
3487 if (mono_is_sre_method_on_tb_inst (klass)) {
3488 MonoClass *handle_class;
3490 MonoMethod *result = (MonoMethod*)mono_reflection_resolve_object (NULL, method, &handle_class, NULL, error);
3491 return_val_if_nok (error, NULL);
3493 return result;
3496 g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
3497 return NULL;
3500 void
3501 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides, MonoError *error)
3503 MonoReflectionTypeBuilder *tb;
3504 int i, j, onum;
3505 MonoReflectionMethod *m;
3507 error_init (error);
3508 *overrides = NULL;
3509 *num_overrides = 0;
3511 g_assert (image_is_dynamic (klass->image));
3513 if (!mono_class_has_ref_info (klass))
3514 return;
3516 tb = mono_class_get_ref_info_raw (klass); /* FIXME use handles */
3517 g_assert (strcmp (mono_object_class (tb)->name, "TypeBuilder") == 0);
3519 onum = 0;
3520 if (tb->methods) {
3521 for (i = 0; i < tb->num_methods; ++i) {
3522 MonoReflectionMethodBuilder *mb =
3523 mono_array_get_internal (tb->methods, MonoReflectionMethodBuilder*, i);
3524 if (mb->override_methods)
3525 onum += mono_array_length_internal (mb->override_methods);
3529 if (onum) {
3530 *overrides = g_new0 (MonoMethod*, onum * 2);
3532 onum = 0;
3533 for (i = 0; i < tb->num_methods; ++i) {
3534 MonoReflectionMethodBuilder *mb =
3535 mono_array_get_internal (tb->methods, MonoReflectionMethodBuilder*, i);
3536 if (mb->override_methods) {
3537 for (j = 0; j < mono_array_length_internal (mb->override_methods); ++j) {
3538 m = mono_array_get_internal (mb->override_methods, MonoReflectionMethod*, j);
3540 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m, error);
3541 return_if_nok (error);
3542 (*overrides) [onum * 2 + 1] = mb->mhandle;
3544 g_assert (mb->mhandle);
3546 onum ++;
3552 *num_overrides = onum;
3555 static gint32
3556 modulebuilder_get_next_table_index (MonoReflectionModuleBuilder *mb, gint32 table, gint32 num_fields, MonoError *error)
3558 error_init (error);
3560 if (mb->table_indexes == NULL) {
3561 MonoArray *arr = mono_array_new_checked (mono_object_domain (&mb->module.obj), mono_defaults.int_class, 64, error);
3562 return_val_if_nok (error, 0);
3563 for (int i = 0; i < 64; i++) {
3564 mono_array_set_internal (arr, int, i, 1);
3566 MONO_OBJECT_SETREF_INTERNAL (mb, table_indexes, arr);
3568 gint32 index = mono_array_get_internal (mb->table_indexes, gint32, table);
3569 gint32 next_index = index + num_fields;
3570 mono_array_set_internal (mb->table_indexes, gint32, table, next_index);
3571 return index;
3574 /* This initializes the same data as mono_class_setup_fields () */
3575 static void
3576 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
3578 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info_raw (klass); /* FIXME use handles */
3579 MonoReflectionFieldBuilder *fb;
3580 MonoClassField *field;
3581 MonoFieldDefaultValue *def_values;
3582 MonoImage *image = klass->image;
3583 const char *p, *p2;
3584 int i, instance_size, packing_size = 0;
3585 guint32 len, idx;
3587 error_init (error);
3589 if (klass->parent) {
3590 if (!klass->parent->size_inited)
3591 mono_class_init (klass->parent);
3592 instance_size = klass->parent->instance_size;
3593 } else {
3594 instance_size = MONO_ABI_SIZEOF (MonoObject);
3597 int fcount = tb->num_fields;
3598 mono_class_set_field_count (klass, fcount);
3600 gint32 first_idx = 0;
3601 if (tb->num_fields > 0) {
3602 first_idx = modulebuilder_get_next_table_index (tb->module, MONO_TABLE_FIELD, (gint32)tb->num_fields, error);
3603 return_if_nok (error);
3605 mono_class_set_first_field_idx (klass, first_idx - 1); /* Why do we subtract 1? because mono_class_create_from_typedef does it, too. */
3607 if (tb->class_size) {
3608 packing_size = tb->packing_size;
3609 instance_size += tb->class_size;
3612 klass->fields = image_g_new0 (image, MonoClassField, fcount);
3613 def_values = image_g_new0 (image, MonoFieldDefaultValue, fcount);
3614 mono_class_set_field_def_values (klass, def_values);
3616 This is, guess what, a hack.
3617 The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
3618 On the static path no field class is resolved, only types are built. This is the right thing to do
3619 but we suck.
3620 Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
3622 klass->size_inited = 1;
3624 for (i = 0; i < fcount; ++i) {
3625 MonoArray *rva_data;
3626 fb = (MonoReflectionFieldBuilder *)mono_array_get_internal (tb->fields, gpointer, i);
3627 field = &klass->fields [i];
3628 field->parent = klass;
3629 field->name = string_to_utf8_image_raw (image, fb->name, error); /* FIXME use handles */
3630 if (!mono_error_ok (error))
3631 return;
3632 if (fb->attrs) {
3633 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
3634 return_if_nok (error);
3635 field->type = mono_metadata_type_dup (klass->image, type);
3636 field->type->attrs = fb->attrs;
3637 } else {
3638 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
3639 return_if_nok (error);
3642 if (!klass->enumtype && !mono_type_get_underlying_type (field->type)) {
3643 mono_class_set_type_load_failure (klass, "Field '%s' is an enum type with a bad underlying type", field->name);
3644 continue;
3647 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
3648 char *base = mono_array_addr_internal (rva_data, char, 0);
3649 size_t size = mono_array_length_internal (rva_data);
3650 char *data = (char *)mono_image_alloc (klass->image, size);
3651 memcpy (data, base, size);
3652 def_values [i].data = data;
3654 if (fb->offset != -1)
3655 field->offset = fb->offset;
3656 fb->handle = field;
3657 mono_save_custom_attrs (klass->image, field, fb->cattrs);
3659 if (fb->def_value) {
3660 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
3661 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
3662 idx = mono_dynimage_encode_constant (assembly, fb->def_value, &def_values [i].def_type);
3663 /* Copy the data from the blob since it might get realloc-ed */
3664 p = assembly->blob.data + idx;
3665 len = mono_metadata_decode_blob_size (p, &p2);
3666 len += p2 - p;
3667 def_values [i].data = (const char *)mono_image_alloc (image, len);
3668 memcpy ((gpointer)def_values [i].data, p, len);
3671 MonoObjectHandle field_builder_handle = MONO_HANDLE_CAST (MonoObject, MONO_HANDLE_NEW (MonoReflectionFieldBuilder, fb));
3672 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);
3675 if (!mono_class_has_failure (klass))
3676 mono_class_layout_fields (klass, instance_size, packing_size, tb->class_size, TRUE);
3679 static void
3680 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
3682 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info_raw (klass); /* FIXME use handles */
3683 MonoReflectionPropertyBuilder *pb;
3684 MonoImage *image = klass->image;
3685 MonoProperty *properties;
3686 MonoClassPropertyInfo *info;
3687 int i;
3689 error_init (error);
3691 info = (MonoClassPropertyInfo*)mono_class_get_property_info (klass);
3692 if (!info) {
3693 info = mono_class_alloc0 (klass, sizeof (MonoClassPropertyInfo));
3694 mono_class_set_property_info (klass, info);
3697 info->count = tb->properties ? mono_array_length_internal (tb->properties) : 0;
3698 info->first = 0;
3700 properties = image_g_new0 (image, MonoProperty, info->count);
3701 info->properties = properties;
3702 for (i = 0; i < info->count; ++i) {
3703 pb = mono_array_get_internal (tb->properties, MonoReflectionPropertyBuilder*, i);
3704 properties [i].parent = klass;
3705 properties [i].attrs = pb->attrs;
3706 properties [i].name = string_to_utf8_image_raw (image, pb->name, error); /* FIXME use handles */
3707 if (!mono_error_ok (error))
3708 return;
3709 if (pb->get_method)
3710 properties [i].get = pb->get_method->mhandle;
3711 if (pb->set_method)
3712 properties [i].set = pb->set_method->mhandle;
3714 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
3715 if (pb->def_value) {
3716 guint32 len, idx;
3717 const char *p, *p2;
3718 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
3719 if (!info->def_values)
3720 info->def_values = image_g_new0 (image, MonoFieldDefaultValue, info->count);
3721 properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
3722 idx = mono_dynimage_encode_constant (assembly, pb->def_value, &info->def_values [i].def_type);
3723 /* Copy the data from the blob since it might get realloc-ed */
3724 p = assembly->blob.data + idx;
3725 len = mono_metadata_decode_blob_size (p, &p2);
3726 len += p2 - p;
3727 info->def_values [i].data = (const char *)mono_image_alloc (image, len);
3728 memcpy ((gpointer)info->def_values [i].data, p, len);
3733 static void
3734 typebuilder_setup_events (MonoClass *klass, MonoError *error)
3736 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info_raw (klass); /* FIXME use handles */
3737 MonoReflectionEventBuilder *eb;
3738 MonoImage *image = klass->image;
3739 MonoEvent *events;
3740 MonoClassEventInfo *info;
3741 int i;
3743 error_init (error);
3745 info = mono_class_alloc0 (klass, sizeof (MonoClassEventInfo));
3746 mono_class_set_event_info (klass, info);
3748 info->count = tb->events ? mono_array_length_internal (tb->events) : 0;
3749 info->first = 0;
3751 events = image_g_new0 (image, MonoEvent, info->count);
3752 info->events = events;
3753 for (i = 0; i < info->count; ++i) {
3754 eb = mono_array_get_internal (tb->events, MonoReflectionEventBuilder*, i);
3755 events [i].parent = klass;
3756 events [i].attrs = eb->attrs;
3757 events [i].name = string_to_utf8_image_raw (image, eb->name, error); /* FIXME use handles */
3758 if (!mono_error_ok (error))
3759 return;
3760 if (eb->add_method)
3761 events [i].add = eb->add_method->mhandle;
3762 if (eb->remove_method)
3763 events [i].remove = eb->remove_method->mhandle;
3764 if (eb->raise_method)
3765 events [i].raise = eb->raise_method->mhandle;
3767 #ifndef MONO_SMALL_CONFIG
3768 if (eb->other_methods) {
3769 int j;
3770 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length_internal (eb->other_methods) + 1);
3771 for (j = 0; j < mono_array_length_internal (eb->other_methods); ++j) {
3772 MonoReflectionMethodBuilder *mb =
3773 mono_array_get_internal (eb->other_methods,
3774 MonoReflectionMethodBuilder*, j);
3775 events [i].other [j] = mb->mhandle;
3778 #endif
3779 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
3783 struct remove_instantiations_user_data
3785 MonoClass *klass;
3786 MonoError *error;
3789 static gboolean
3790 remove_instantiations_of_and_ensure_contents (gpointer key,
3791 gpointer value,
3792 gpointer user_data)
3794 struct remove_instantiations_user_data *data = (struct remove_instantiations_user_data*)user_data;
3795 MonoType *type = (MonoType*)key;
3796 MonoClass *klass = data->klass;
3797 gboolean already_failed = !is_ok (data->error);
3798 ERROR_DECL_VALUE (lerror);
3799 MonoError *error = already_failed ? &lerror : data->error;
3801 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
3802 MonoClass *inst_klass = mono_class_from_mono_type_internal (type);
3803 //Ensure it's safe to use it.
3804 if (!fix_partial_generic_class (inst_klass, error)) {
3805 mono_class_set_type_load_failure (inst_klass, "Could not initialized generic type instance due to: %s", mono_error_get_message (error));
3806 // Marked the class with failure, but since some other instantiation already failed,
3807 // just report that one, and swallow the error from this one.
3808 if (already_failed)
3809 mono_error_cleanup (error);
3811 return TRUE;
3812 } else
3813 return FALSE;
3817 * reflection_setup_internal_class:
3818 * @tb: a TypeBuilder object
3819 * @error: set on error
3821 * Creates a MonoClass that represents the TypeBuilder.
3822 * This is a trick that lets us simplify a lot of reflection code
3823 * (and will allow us to support Build and Run assemblies easier).
3825 * Returns TRUE on success. On failure, returns FALSE and sets @error.
3827 static gboolean
3828 reflection_setup_internal_class (MonoReflectionTypeBuilderHandle ref_tb, MonoError *error)
3830 MonoReflectionModuleBuilderHandle module_ref = MONO_HANDLE_NEW_GET (MonoReflectionModuleBuilder, ref_tb, module);
3831 GHashTable *unparented_classes = MONO_HANDLE_GETVAL(module_ref, unparented_classes);
3833 if (unparented_classes) {
3834 return reflection_setup_internal_class_internal (ref_tb, error);
3835 } else {
3836 // If we're not being called recursively
3837 unparented_classes = g_hash_table_new (NULL, NULL);
3838 MONO_HANDLE_SETVAL (module_ref, unparented_classes, GHashTable *, unparented_classes);
3840 gboolean ret_val = reflection_setup_internal_class_internal (ref_tb, error);
3841 mono_error_assert_ok (error);
3843 // Fix the relationship between the created classes and their parents
3844 reflection_setup_class_hierarchy (unparented_classes, error);
3845 mono_error_assert_ok (error);
3847 g_hash_table_destroy (unparented_classes);
3848 MONO_HANDLE_SETVAL (module_ref, unparented_classes, GHashTable *, NULL);
3850 return ret_val;
3854 MonoReflectionTypeHandle
3855 ves_icall_TypeBuilder_create_runtime_class (MonoReflectionTypeBuilderHandle ref_tb, MonoError *error)
3857 error_init (error);
3859 reflection_setup_internal_class (ref_tb, error);
3860 mono_error_assert_ok (error);
3862 MonoDomain *domain = MONO_HANDLE_DOMAIN (ref_tb);
3863 MonoType *type = MONO_HANDLE_GETVAL (MONO_HANDLE_CAST (MonoReflectionType, ref_tb), type);
3864 MonoClass *klass = mono_class_from_mono_type_internal (type);
3866 MonoArrayHandle cattrs = MONO_HANDLE_NEW_GET (MonoArray, ref_tb, cattrs);
3867 mono_save_custom_attrs (klass->image, klass, MONO_HANDLE_RAW (cattrs)); /* FIXME use handles */
3870 * we need to lock the domain because the lock will be taken inside
3871 * So, we need to keep the locking order correct.
3873 mono_loader_lock ();
3874 mono_domain_lock (domain);
3875 if (klass->wastypebuilder) {
3876 mono_domain_unlock (domain);
3877 mono_loader_unlock ();
3879 return mono_type_get_object_handle (domain, m_class_get_byval_arg (klass), error);
3882 * Fields to set in klass:
3883 * the various flags: delegate/unicode/contextbound etc.
3885 mono_class_set_flags (klass, MONO_HANDLE_GETVAL (ref_tb, attrs));
3886 klass->has_cctor = 1;
3888 mono_class_setup_parent (klass, klass->parent);
3889 /* fool mono_class_setup_supertypes */
3890 klass->supertypes = NULL;
3891 mono_class_setup_supertypes (klass);
3892 mono_class_setup_mono_type (klass);
3894 /* enums are done right away */
3895 if (!klass->enumtype)
3896 if (!ensure_runtime_vtable (klass, error))
3897 goto failure;
3899 MonoArrayHandle nested_types;
3900 nested_types = MONO_HANDLE_NEW_GET (MonoArray, ref_tb, subtypes);
3901 if (!MONO_HANDLE_IS_NULL (nested_types)) {
3902 GList *nested = NULL;
3903 int num_nested = mono_array_handle_length (nested_types);
3904 MonoReflectionTypeHandle nested_tb = MONO_HANDLE_NEW (MonoReflectionType, NULL);
3905 for (int i = 0; i < num_nested; ++i) {
3906 MONO_HANDLE_ARRAY_GETREF (nested_tb, nested_types, i);
3908 if (MONO_HANDLE_GETVAL (nested_tb, type) == NULL) {
3909 reflection_setup_internal_class (MONO_HANDLE_CAST (MonoReflectionTypeBuilder, nested_tb), error);
3910 mono_error_assert_ok (error);
3913 MonoType *subtype = mono_reflection_type_handle_mono_type (nested_tb, error);
3914 goto_if_nok (error, failure);
3915 nested = mono_g_list_prepend_image (klass->image, nested, mono_class_from_mono_type_internal (subtype));
3917 mono_class_set_nested_classes_property (klass, nested);
3920 klass->nested_classes_inited = TRUE;
3922 typebuilder_setup_fields (klass, error);
3923 goto_if_nok (error, failure);
3924 typebuilder_setup_properties (klass, error);
3925 goto_if_nok (error, failure);
3927 typebuilder_setup_events (klass, error);
3928 goto_if_nok (error, failure);
3930 klass->wastypebuilder = TRUE;
3932 MonoArrayHandle generic_params;
3933 generic_params = MONO_HANDLE_NEW_GET (MonoArray, ref_tb, generic_params);
3934 if (!MONO_HANDLE_IS_NULL (generic_params)) {
3935 int num_params = mono_array_handle_length (generic_params);
3936 MonoReflectionTypeHandle ref_gparam = MONO_HANDLE_NEW (MonoReflectionType, NULL);
3937 for (int i = 0; i < num_params; i++) {
3938 MONO_HANDLE_ARRAY_GETREF (ref_gparam, generic_params, i);
3939 MonoType *param_type = mono_reflection_type_handle_mono_type (ref_gparam, error);
3940 goto_if_nok (error, failure);
3941 MonoClass *gklass = mono_class_from_mono_type_internal (param_type);
3943 gklass->wastypebuilder = TRUE;
3948 * If we are a generic TypeBuilder, there might be instantiations in the type cache
3949 * which have type System.Reflection.MonoGenericClass, but after the type is created,
3950 * we want to return normal System.MonoType objects, so clear these out from the cache.
3952 * Together with this we must ensure the contents of all instances to match the created type.
3954 if (domain->type_hash && mono_class_is_gtd (klass)) {
3955 struct remove_instantiations_user_data data;
3956 data.klass = klass;
3957 data.error = error;
3958 mono_error_assert_ok (error);
3959 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, &data);
3960 goto_if_nok (error, failure);
3963 mono_domain_unlock (domain);
3964 mono_loader_unlock ();
3966 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
3967 mono_class_set_type_load_failure (klass, "Not a valid enumeration");
3968 mono_error_set_type_load_class (error, klass, "Not a valid enumeration");
3969 goto failure_unlocked;
3972 MonoReflectionTypeHandle res;
3973 res = mono_type_get_object_handle (domain, m_class_get_byval_arg (klass), error);
3974 goto_if_nok (error, failure_unlocked);
3976 return res;
3978 failure:
3979 mono_class_set_type_load_failure (klass, "TypeBuilder could not create runtime class due to: %s", mono_error_get_message (error));
3980 klass->wastypebuilder = TRUE;
3981 mono_domain_unlock (domain);
3982 mono_loader_unlock ();
3983 failure_unlocked:
3984 return MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE);
3987 typedef struct {
3988 MonoMethod *handle;
3989 MonoDomain *domain;
3990 } DynamicMethodReleaseData;
3993 * The runtime automatically clean up those after finalization.
3995 static MonoReferenceQueue *dynamic_method_queue;
3997 static void
3998 free_dynamic_method (void *dynamic_method)
4000 DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
4001 MonoDomain *domain = data->domain;
4002 MonoMethod *method = data->handle;
4003 guint32 dis_link;
4005 mono_domain_lock (domain);
4006 dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
4007 g_hash_table_remove (domain->method_to_dyn_method, method);
4008 mono_domain_unlock (domain);
4009 g_assert (dis_link);
4010 mono_gchandle_free_internal (dis_link);
4012 mono_runtime_free_method (domain, method);
4013 g_free (data);
4016 static gboolean
4017 reflection_create_dynamic_method (MonoReflectionDynamicMethodHandle ref_mb, MonoError *error)
4019 MonoReferenceQueue *queue;
4020 MonoMethod *handle;
4021 DynamicMethodReleaseData *release_data;
4022 ReflectionMethodBuilder rmb;
4023 MonoMethodSignature *sig;
4024 MonoClass *klass;
4025 MonoDomain *domain;
4026 GSList *l;
4027 int i;
4029 error_init (error);
4031 if (mono_runtime_is_shutting_down ()) {
4032 mono_error_set_generic_error (error, "System", "InvalidOperationException", "");
4033 return FALSE;
4036 if (!(queue = dynamic_method_queue)) {
4037 mono_loader_lock ();
4038 if (!(queue = dynamic_method_queue))
4039 queue = dynamic_method_queue = mono_gc_reference_queue_new_internal (free_dynamic_method);
4040 mono_loader_unlock ();
4043 sig = dynamic_method_to_signature (ref_mb, error);
4044 return_val_if_nok (error, FALSE);
4046 MonoReflectionDynamicMethod *mb = MONO_HANDLE_RAW (ref_mb); /* FIXME convert reflection_create_dynamic_method to use handles */
4047 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
4050 * Resolve references.
4053 * Every second entry in the refs array is reserved for storing handle_class,
4054 * which is needed by the ldtoken implementation in the JIT.
4056 rmb.nrefs = mb->nrefs;
4057 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
4058 for (i = 0; i < mb->nrefs; i += 2) {
4059 MonoClass *handle_class;
4060 gpointer ref;
4061 MonoObject *obj = mono_array_get_internal (mb->refs, MonoObject*, i);
4063 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
4064 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
4066 * The referenced DynamicMethod should already be created by the managed
4067 * code, except in the case of circular references. In that case, we store
4068 * method in the refs array, and fix it up later when the referenced
4069 * DynamicMethod is created.
4071 if (method->mhandle) {
4072 ref = method->mhandle;
4073 } else {
4074 /* FIXME: GC object stored in unmanaged memory */
4075 ref = method;
4077 /* FIXME: GC object stored in unmanaged memory */
4078 method->referenced_by = g_slist_append (method->referenced_by, mb);
4080 handle_class = mono_defaults.methodhandle_class;
4081 } else {
4082 MonoException *ex = NULL;
4083 ref = mono_reflection_resolve_object (mb->module->image, obj, &handle_class, NULL, error);
4084 if (!is_ok (error)) {
4085 g_free (rmb.refs);
4086 return FALSE;
4088 if (!ref)
4089 ex = mono_get_exception_type_load (NULL, NULL);
4090 else if (mono_security_core_clr_enabled ())
4091 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
4093 if (ex) {
4094 g_free (rmb.refs);
4095 mono_error_set_exception_instance (error, ex);
4096 return FALSE;
4100 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
4101 rmb.refs [i + 1] = handle_class;
4104 MonoAssembly *ass = NULL;
4105 if (mb->owner) {
4106 MonoType *owner_type = mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner, error);
4107 if (!is_ok (error)) {
4108 g_free (rmb.refs);
4109 return FALSE;
4111 klass = mono_class_from_mono_type_internal (owner_type);
4112 ass = klass->image->assembly;
4113 } else {
4114 klass = mono_defaults.object_class;
4115 ass = (mb->module && mb->module->image) ? mb->module->image->assembly : NULL;
4118 mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
4119 ((MonoDynamicMethod*)handle)->assembly = ass;
4120 g_free (rmb.refs);
4121 return_val_if_nok (error, FALSE);
4123 release_data = g_new (DynamicMethodReleaseData, 1);
4124 release_data->handle = handle;
4125 release_data->domain = mono_object_get_domain_internal ((MonoObject*)mb);
4126 if (!mono_gc_reference_queue_add_internal (queue, (MonoObject*)mb, release_data))
4127 g_free (release_data);
4129 /* Fix up refs entries pointing at us */
4130 for (l = mb->referenced_by; l; l = l->next) {
4131 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
4132 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
4133 gpointer *data;
4135 g_assert (method->mhandle);
4137 data = (gpointer*)wrapper->method_data;
4138 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
4139 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
4140 data [i + 1] = mb->mhandle;
4143 g_slist_free (mb->referenced_by);
4145 /* ilgen is no longer needed */
4146 mb->ilgen = NULL;
4148 domain = mono_domain_get ();
4149 mono_domain_lock (domain);
4150 if (!domain->method_to_dyn_method)
4151 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
4152 g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref_internal ((MonoObject *)mb, TRUE));
4153 mono_domain_unlock (domain);
4155 return TRUE;
4158 void
4159 ves_icall_DynamicMethod_create_dynamic_method (MonoReflectionDynamicMethodHandle mb, MonoError *error)
4161 (void) reflection_create_dynamic_method (mb, error);
4164 #endif /* DISABLE_REFLECTION_EMIT */
4166 MonoMethodSignature *
4167 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
4169 MonoMethodSignature *sig;
4170 g_assert (image_is_dynamic (image));
4172 error_init (error);
4174 sig = (MonoMethodSignature *)g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
4175 if (sig)
4176 return sig;
4178 return mono_method_signature_checked (method, error);
4181 #ifndef DISABLE_REFLECTION_EMIT
4184 * ensure_complete_type:
4186 * Ensure that KLASS is completed if it is a dynamic type, or references
4187 * dynamic types.
4189 static void
4190 ensure_complete_type (MonoClass *klass, MonoError *error)
4192 HANDLE_FUNCTION_ENTER ();
4194 error_init (error);
4196 if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_has_ref_info (klass)) {
4197 MonoReflectionTypeBuilderHandle tb = mono_class_get_ref_info (klass);
4199 mono_domain_try_type_resolve_typebuilder (mono_domain_get (), tb, error);
4200 goto_if_nok (error, exit);
4202 // Asserting here could break a lot of code
4203 //g_assert (klass->wastypebuilder);
4206 if (mono_class_is_ginst (klass)) {
4207 MonoGenericInst *inst = mono_class_get_generic_class (klass)->context.class_inst;
4208 int i;
4210 for (i = 0; i < inst->type_argc; ++i) {
4211 ensure_complete_type (mono_class_from_mono_type_internal (inst->type_argv [i]), error);
4212 goto_if_nok (error, exit);
4216 exit:
4217 HANDLE_FUNCTION_RETURN ();
4220 gpointer
4221 mono_reflection_resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
4223 HANDLE_FUNCTION_ENTER ();
4225 MonoClass *oklass = obj->vtable->klass;
4226 gpointer result = NULL;
4228 error_init (error);
4230 if (strcmp (oklass->name, "String") == 0) {
4231 result = mono_string_intern_checked ((MonoString*)obj, error);
4232 goto_if_nok (error, return_null);
4233 *handle_class = mono_defaults.string_class;
4234 g_assert (result);
4235 } else if (strcmp (oklass->name, "RuntimeType") == 0) {
4236 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
4237 goto_if_nok (error, return_null);
4238 MonoClass *mc = mono_class_from_mono_type_internal (type);
4239 if (!mono_class_init (mc)) {
4240 mono_error_set_for_class_failure (error, mc);
4241 goto return_null;
4244 if (context) {
4245 MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, error);
4246 goto_if_nok (error, return_null);
4248 result = mono_class_from_mono_type_internal (inflated);
4249 mono_metadata_free_type (inflated);
4250 } else {
4251 result = mono_class_from_mono_type_internal (type);
4253 *handle_class = mono_defaults.typehandle_class;
4254 g_assert (result);
4255 } else if (strcmp (oklass->name, "MonoMethod") == 0 ||
4256 strcmp (oklass->name, "MonoCMethod") == 0) {
4257 result = ((MonoReflectionMethod*)obj)->method;
4258 if (context) {
4259 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
4260 mono_error_assert_ok (error);
4262 *handle_class = mono_defaults.methodhandle_class;
4263 g_assert (result);
4264 } else if (strcmp (oklass->name, "MonoField") == 0) {
4265 MonoClassField *field = ((MonoReflectionField*)obj)->field;
4267 ensure_complete_type (field->parent, error);
4268 goto_if_nok (error, return_null);
4270 if (context) {
4271 MonoType *inflated = mono_class_inflate_generic_type_checked (m_class_get_byval_arg (field->parent), context, error);
4272 goto_if_nok (error, return_null);
4274 MonoClass *klass;
4275 klass = mono_class_from_mono_type_internal (inflated);
4276 MonoClassField *inflated_field;
4277 gpointer iter = NULL;
4278 mono_metadata_free_type (inflated);
4279 while ((inflated_field = mono_class_get_fields_internal (klass, &iter))) {
4280 if (!strcmp (field->name, inflated_field->name))
4281 break;
4283 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
4284 result = inflated_field;
4285 } else {
4286 result = field;
4288 *handle_class = mono_defaults.fieldhandle_class;
4289 g_assert (result);
4290 } else if (strcmp (oklass->name, "TypeBuilder") == 0) {
4291 MonoReflectionTypeBuilderHandle tb = MONO_HANDLE_NEW (MonoReflectionTypeBuilder, (MonoReflectionTypeBuilder*)obj);
4292 MonoType *type = mono_reflection_type_get_handle (&MONO_HANDLE_RAW (tb)->type, error);
4293 goto_if_nok (error, return_null);
4294 MonoClass *klass;
4296 klass = type->data.klass;
4297 if (klass->wastypebuilder) {
4298 /* Already created */
4299 result = klass;
4301 else {
4302 mono_domain_try_type_resolve_typebuilder (mono_domain_get (), tb, error);
4303 goto_if_nok (error, return_null);
4304 result = type->data.klass;
4305 g_assert (result);
4307 *handle_class = mono_defaults.typehandle_class;
4308 } else if (strcmp (oklass->name, "SignatureHelper") == 0) {
4309 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
4310 MonoMethodSignature *sig;
4311 int nargs, i;
4313 if (helper->arguments)
4314 nargs = mono_array_length_internal (helper->arguments);
4315 else
4316 nargs = 0;
4318 sig = mono_metadata_signature_alloc (image, nargs);
4319 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
4320 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
4322 if (helper->unmanaged_call_conv) { /* unmanaged */
4323 sig->call_convention = helper->unmanaged_call_conv - 1;
4324 sig->pinvoke = TRUE;
4325 } else if (helper->call_conv & 0x02) {
4326 sig->call_convention = MONO_CALL_VARARG;
4327 } else {
4328 sig->call_convention = MONO_CALL_DEFAULT;
4331 sig->param_count = nargs;
4332 /* TODO: Copy type ? */
4333 sig->ret = helper->return_type->type;
4334 for (i = 0; i < nargs; ++i) {
4335 sig->params [i] = mono_type_array_get_and_resolve_raw (helper->arguments, i, error); /* FIXME use handles */
4336 if (!is_ok (error)) {
4337 image_g_free (image, sig);
4338 goto return_null;
4342 result = sig;
4343 *handle_class = NULL;
4344 } else if (strcmp (oklass->name, "DynamicMethod") == 0) {
4345 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
4346 /* Already created by the managed code */
4347 g_assert (method->mhandle);
4348 result = method->mhandle;
4349 *handle_class = mono_defaults.methodhandle_class;
4350 } else if (strcmp (oklass->name, "MonoArrayMethod") == 0) {
4351 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
4352 MonoType *mtype;
4353 MonoClass *klass;
4354 MonoMethod *method;
4355 gpointer iter;
4356 char *name;
4358 mtype = mono_reflection_type_get_handle (m->parent, error);
4359 goto_if_nok (error, return_null);
4360 klass = mono_class_from_mono_type_internal (mtype);
4362 /* Find the method */
4364 name = mono_string_to_utf8_checked_internal (m->name, error);
4365 goto_if_nok (error, return_null);
4366 iter = NULL;
4367 while ((method = mono_class_get_methods (klass, &iter))) {
4368 if (!strcmp (method->name, name))
4369 break;
4371 g_free (name);
4373 // FIXME:
4374 g_assert (method);
4375 // FIXME: Check parameters/return value etc. match
4377 result = method;
4378 *handle_class = mono_defaults.methodhandle_class;
4379 } else if (is_sre_method_builder (oklass) ||
4380 mono_is_sre_ctor_builder (oklass) ||
4381 is_sre_field_builder (oklass) ||
4382 is_sre_gparam_builder (oklass) ||
4383 is_sre_generic_instance (oklass) ||
4384 is_sre_array (oklass) ||
4385 is_sre_byref (oklass) ||
4386 is_sre_pointer (oklass) ||
4387 !strcmp (oklass->name, "FieldOnTypeBuilderInst") ||
4388 !strcmp (oklass->name, "MethodOnTypeBuilderInst") ||
4389 !strcmp (oklass->name, "ConstructorOnTypeBuilderInst")) {
4390 static MonoMethod *resolve_method;
4391 if (!resolve_method) {
4392 MonoMethod *m = mono_class_get_method_from_name_checked (mono_class_get_module_builder_class (), "RuntimeResolve", 1, 0, error);
4393 mono_error_assert_ok (error);
4394 g_assert (m);
4395 mono_memory_barrier ();
4396 resolve_method = m;
4398 void *args [16];
4399 args [0] = obj;
4400 obj = mono_runtime_invoke_checked (resolve_method, NULL, args, error);
4401 mono_error_assert_ok (error);
4402 g_assert (obj);
4403 result = mono_reflection_resolve_object (image, obj, handle_class, context, error);
4404 goto exit;
4405 } else {
4406 g_print ("%s\n", obj->vtable->klass->name);
4407 g_assert_not_reached ();
4410 goto exit;
4411 return_null:
4412 result = NULL;
4413 goto exit;
4414 exit:
4415 HANDLE_FUNCTION_RETURN_VAL (result);
4418 gpointer
4419 mono_reflection_resolve_object_handle (MonoImage *image, MonoObjectHandle obj, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
4421 return mono_reflection_resolve_object (image, MONO_HANDLE_RAW (obj), handle_class, context, error);
4424 #else /* DISABLE_REFLECTION_EMIT */
4426 MonoArray*
4427 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
4429 g_assert_not_reached ();
4430 return NULL;
4433 void
4434 mono_reflection_dynimage_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4436 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
4439 static gboolean
4440 mono_image_module_basic_init (MonoReflectionModuleBuilderHandle moduleb, MonoError *error)
4442 g_assert_not_reached ();
4443 return FALSE;
4446 guint32
4447 mono_image_insert_string (MonoReflectionModuleBuilderHandle module, MonoStringHandle str, MonoError *error)
4449 g_assert_not_reached ();
4450 return 0;
4453 guint32
4454 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObjectHandle obj, MonoArrayHandle opt_param_types, MonoError *error)
4456 g_assert_not_reached ();
4457 return 0;
4460 guint32
4461 mono_image_create_token (MonoDynamicImage *assembly, MonoObjectHandle obj,
4462 gboolean create_open_instance, gboolean register_token, MonoError *error)
4464 g_assert_not_reached ();
4465 return 0;
4468 void
4469 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides, MonoError *error)
4471 error_init (error);
4472 *overrides = NULL;
4473 *num_overrides = 0;
4476 MonoReflectionTypeHandle
4477 ves_icall_TypeBuilder_create_runtime_class (MonoReflectionTypeBuilderHandle tb, MonoError *error)
4479 g_assert_not_reached ();
4480 return MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE);
4483 void
4484 ves_icall_DynamicMethod_create_dynamic_method (MonoReflectionDynamicMethodHandle mb, MonoError *error)
4486 error_init (error);
4489 MonoType*
4490 mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
4492 error_init (error);
4493 if (!ref)
4494 return NULL;
4495 return ref->type;
4498 MonoType*
4499 mono_reflection_type_handle_mono_type (MonoReflectionTypeHandle ref, MonoError *error)
4501 error_init (error);
4502 if (MONO_HANDLE_IS_NULL (ref))
4503 return NULL;
4504 return MONO_HANDLE_GETVAL (ref, type);
4508 #endif /* DISABLE_REFLECTION_EMIT */
4510 void
4511 mono_sre_generic_param_table_entry_free (GenericParamTableEntry *entry)
4513 MONO_GC_UNREGISTER_ROOT_IF_MOVING (entry->gparam);
4514 g_free (entry);
4517 gint32
4518 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilderHandle mb, MonoObjectHandle obj, MonoBoolean create_open_instance, MonoError *error)
4520 error_init (error);
4521 if (MONO_HANDLE_IS_NULL (obj)) {
4522 mono_error_set_argument_null (error, "obj", "");
4523 return 0;
4525 return mono_image_create_token (MONO_HANDLE_GETVAL (mb, dynamic_image), obj, create_open_instance, TRUE, error);
4528 gint32
4529 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilderHandle mb,
4530 MonoReflectionMethodHandle method,
4531 MonoArrayHandle opt_param_types,
4532 MonoError *error)
4534 error_init (error);
4535 if (MONO_HANDLE_IS_NULL (method)) {
4536 mono_error_set_argument_null (error, "method", "");
4537 return 0;
4540 return mono_image_create_method_token (MONO_HANDLE_GETVAL (mb, dynamic_image), MONO_HANDLE_CAST (MonoObject, method), opt_param_types, error);
4543 void
4544 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
4546 ERROR_DECL (error);
4547 mono_image_create_pefile (mb, file, error);
4548 mono_error_set_pending_exception (error);
4551 void
4552 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
4554 ERROR_DECL (error);
4555 mono_image_build_metadata (mb, error);
4556 mono_error_set_pending_exception (error);
4559 void
4560 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilderHandle mb, MonoObjectHandle obj, guint32 token, MonoError *error)
4562 error_init (error);
4563 /* This function may be called by ModuleBuilder.FixupTokens to update
4564 * an existing token, so replace is okay here. */
4565 mono_dynamic_image_register_token (MONO_HANDLE_GETVAL (mb, dynamic_image), token, obj, MONO_DYN_IMAGE_TOK_REPLACE);
4568 MonoObjectHandle
4569 ves_icall_ModuleBuilder_GetRegisteredToken (MonoReflectionModuleBuilderHandle mb, guint32 token, MonoError *error)
4571 MonoDynamicImage *dynamic_image = MONO_HANDLE_GETVAL (mb, dynamic_image);
4572 return mono_dynamic_image_get_registered_token (dynamic_image, token, error);
4575 #ifndef DISABLE_REFLECTION_EMIT
4576 MonoArray*
4577 ves_icall_CustomAttributeBuilder_GetBlob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
4579 ERROR_DECL (error);
4580 MonoArray *result = mono_reflection_get_custom_attrs_blob_checked (assembly, ctor, ctorArgs, properties, propValues, fields, fieldValues, error);
4581 mono_error_set_pending_exception (error);
4582 return result;
4584 #endif
4586 void
4587 ves_icall_AssemblyBuilder_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4589 mono_reflection_dynimage_basic_init (assemblyb);
4592 void
4593 ves_icall_AssemblyBuilder_UpdateNativeCustomAttributes (MonoReflectionAssemblyBuilderHandle assemblyb, MonoError *error)
4595 MonoArrayHandle cattrs = MONO_HANDLE_NEW_GET (MonoArray, assemblyb, cattrs);
4597 MonoReflectionAssemblyHandle assembly_handle = MONO_HANDLE_CAST (MonoReflectionAssembly, assemblyb);
4598 MonoAssembly *assembly = MONO_HANDLE_GETVAL (assembly_handle, assembly);
4599 g_assert (assembly);
4601 mono_save_custom_attrs (assembly->image, assembly, MONO_HANDLE_RAW (cattrs));
4604 void
4605 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionTypeHandle enumtype,
4606 MonoReflectionTypeHandle t,
4607 MonoError *error)
4609 error_init (error);
4610 MONO_HANDLE_SETVAL (enumtype, type, MonoType*, MONO_HANDLE_GETVAL (t, type));
4613 void
4614 ves_icall_ModuleBuilder_basic_init (MonoReflectionModuleBuilderHandle moduleb, MonoError *error)
4616 error_init (error);
4617 mono_image_module_basic_init (moduleb, error);
4620 guint32
4621 ves_icall_ModuleBuilder_getUSIndex (MonoReflectionModuleBuilderHandle module, MonoStringHandle str, MonoError *error)
4623 return mono_image_insert_string (module, str, error);
4626 void
4627 ves_icall_ModuleBuilder_set_wrappers_type (MonoReflectionModuleBuilderHandle moduleb, MonoReflectionTypeHandle ref_type, MonoError *error)
4629 error_init (error);
4630 MonoDynamicImage *image = MONO_HANDLE_GETVAL (moduleb, dynamic_image);
4631 MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
4633 g_assert (type);
4634 image->wrappers_type = mono_class_from_mono_type_internal (type);