Merge pull request #3936 from kumpera/monoclass_reorg2
[mono-project.git] / mono / metadata / sre.c
blob3d73c7561332b5efbf78b0ed01f3c6b7f1240560
1 /*
2 * sre.c: Routines for creating an image at runtime
3 * and related System.Reflection.Emit icalls
4 *
5 *
6 * Author:
7 * Paolo Molaro (lupus@ximian.com)
9 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
10 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
11 * Copyright 2011 Rodrigo Kumpera
12 * Copyright 2016 Microsoft
14 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
16 #include <config.h>
17 #include <glib.h>
18 #include "mono/metadata/assembly.h"
19 #include "mono/metadata/debug-helpers.h"
20 #include "mono/metadata/dynamic-image-internals.h"
21 #include "mono/metadata/dynamic-stream-internals.h"
22 #include "mono/metadata/exception.h"
23 #include "mono/metadata/gc-internals.h"
24 #include "mono/metadata/mono-ptr-array.h"
25 #include "mono/metadata/object-internals.h"
26 #include "mono/metadata/profiler-private.h"
27 #include "mono/metadata/reflection-internals.h"
28 #include "mono/metadata/reflection-cache.h"
29 #include "mono/metadata/sre-internals.h"
30 #include "mono/metadata/custom-attrs-internals.h"
31 #include "mono/metadata/security-manager.h"
32 #include "mono/metadata/security-core-clr.h"
33 #include "mono/metadata/tabledefs.h"
34 #include "mono/metadata/tokentype.h"
35 #include "mono/utils/checked-build.h"
36 #include "mono/utils/mono-digest.h"
38 static GENERATE_GET_CLASS_WITH_CACHE (marshal_as_attribute, System.Runtime.InteropServices, MarshalAsAttribute);
39 static GENERATE_GET_CLASS_WITH_CACHE (module_builder, System.Reflection.Emit, ModuleBuilder);
41 #ifndef DISABLE_REFLECTION_EMIT
42 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
43 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error);
44 static gboolean ensure_runtime_vtable (MonoClass *klass, MonoError *error);
45 static void reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb);
46 static gboolean reflection_setup_internal_class (MonoReflectionTypeBuilder *tb, MonoError *error);
48 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
49 #endif
51 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
52 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error);
53 static gboolean is_sre_array (MonoClass *klass);
54 static gboolean is_sre_byref (MonoClass *klass);
55 static gboolean is_sre_pointer (MonoClass *klass);
56 static gboolean is_sre_generic_instance (MonoClass *klass);
57 static gboolean is_sre_type_builder (MonoClass *klass);
58 static gboolean is_sre_method_builder (MonoClass *klass);
59 static gboolean is_sre_field_builder (MonoClass *klass);
60 static gboolean is_sre_gparam_builder (MonoClass *klass);
61 static gboolean is_sre_enum_builder (MonoClass *klass);
62 static gboolean is_sr_mono_method (MonoClass *klass);
63 static gboolean is_sr_mono_field (MonoClass *klass);
65 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
66 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
68 #define mono_type_array_get_and_resolve(array, index, error) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index), error)
70 static void mono_image_module_basic_init (MonoReflectionModuleBuilder *module);
72 void
73 mono_reflection_emit_init (void)
75 mono_dynamic_images_init ();
78 static char*
79 type_get_fully_qualified_name (MonoType *type)
81 MONO_REQ_GC_NEUTRAL_MODE;
83 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
86 static char*
87 type_get_qualified_name (MonoType *type, MonoAssembly *ass)
89 MONO_REQ_GC_UNSAFE_MODE;
91 MonoClass *klass;
92 MonoAssembly *ta;
94 klass = mono_class_from_mono_type (type);
95 if (!klass)
96 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
97 ta = klass->image->assembly;
98 if (assembly_is_dynamic (ta) || (ta == ass)) {
99 if (mono_class_is_ginst (klass) || mono_class_is_gtd (klass))
100 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
101 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
102 else
103 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
106 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
109 #ifndef DISABLE_REFLECTION_EMIT
111 * mp_g_alloc:
113 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
114 * from the C heap.
116 static gpointer
117 image_g_malloc (MonoImage *image, guint size)
119 MONO_REQ_GC_NEUTRAL_MODE;
121 if (image)
122 return mono_image_alloc (image, size);
123 else
124 return g_malloc (size);
126 #endif /* !DISABLE_REFLECTION_EMIT */
129 * image_g_alloc0:
131 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
132 * from the C heap.
134 gpointer
135 mono_image_g_malloc0 (MonoImage *image, guint size)
137 MONO_REQ_GC_NEUTRAL_MODE;
139 if (image)
140 return mono_image_alloc0 (image, size);
141 else
142 return g_malloc0 (size);
146 * image_g_free:
147 * @image: a MonoImage
148 * @ptr: pointer
150 * If @image is NULL, free @ptr, otherwise do nothing.
152 static void
153 image_g_free (MonoImage *image, gpointer ptr)
155 if (image == NULL)
156 g_free (ptr);
159 #ifndef DISABLE_REFLECTION_EMIT
160 static char*
161 image_strdup (MonoImage *image, const char *s)
163 MONO_REQ_GC_NEUTRAL_MODE;
165 if (image)
166 return mono_image_strdup (image, s);
167 else
168 return g_strdup (s);
170 #endif
172 #define image_g_new(image,struct_type, n_structs) \
173 ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
175 #define image_g_new0(image,struct_type, n_structs) \
176 ((struct_type *) mono_image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
179 static void
180 alloc_table (MonoDynamicTable *table, guint nrows)
182 mono_dynimage_alloc_table (table, nrows);
185 static guint32
186 string_heap_insert (MonoDynamicStream *sh, const char *str)
188 return mono_dynstream_insert_string (sh, str);
191 static guint32
192 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
194 return mono_dynstream_add_data (stream, data, len);
198 * Despite the name, we handle also TypeSpec (with the above helper).
200 static guint32
201 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
203 return mono_dynimage_encode_typedef_or_ref_full (assembly, type, TRUE);
207 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
208 * dest may be misaligned.
210 static void
211 swap_with_size (char *dest, const char* val, int len, int nelem) {
212 MONO_REQ_GC_NEUTRAL_MODE;
213 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
214 int elem;
216 for (elem = 0; elem < nelem; ++elem) {
217 switch (len) {
218 case 1:
219 *dest = *val;
220 break;
221 case 2:
222 dest [0] = val [1];
223 dest [1] = val [0];
224 break;
225 case 4:
226 dest [0] = val [3];
227 dest [1] = val [2];
228 dest [2] = val [1];
229 dest [3] = val [0];
230 break;
231 case 8:
232 dest [0] = val [7];
233 dest [1] = val [6];
234 dest [2] = val [5];
235 dest [3] = val [4];
236 dest [4] = val [3];
237 dest [5] = val [2];
238 dest [6] = val [1];
239 dest [7] = val [0];
240 break;
241 default:
242 g_assert_not_reached ();
244 dest += len;
245 val += len;
247 #else
248 memcpy (dest, val, len * nelem);
249 #endif
252 guint32
253 mono_reflection_method_count_clauses (MonoReflectionILGen *ilgen)
255 MONO_REQ_GC_UNSAFE_MODE;
257 guint32 num_clauses = 0;
258 int i;
260 MonoILExceptionInfo *ex_info;
261 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
262 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
263 if (ex_info->handlers)
264 num_clauses += mono_array_length (ex_info->handlers);
265 else
266 num_clauses++;
269 return num_clauses;
272 #ifndef DISABLE_REFLECTION_EMIT
273 static MonoExceptionClause*
274 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses, MonoError *error)
276 MONO_REQ_GC_UNSAFE_MODE;
278 mono_error_init (error);
280 MonoExceptionClause *clauses;
281 MonoExceptionClause *clause;
282 MonoILExceptionInfo *ex_info;
283 MonoILExceptionBlock *ex_block;
284 guint32 finally_start;
285 int i, j, clause_index;;
287 clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
289 clause_index = 0;
290 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
291 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
292 finally_start = ex_info->start + ex_info->len;
293 if (!ex_info->handlers)
294 continue;
295 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
296 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
297 clause = &(clauses [clause_index]);
299 clause->flags = ex_block->type;
300 clause->try_offset = ex_info->start;
302 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
303 clause->try_len = finally_start - ex_info->start;
304 else
305 clause->try_len = ex_info->len;
306 clause->handler_offset = ex_block->start;
307 clause->handler_len = ex_block->len;
308 if (ex_block->extype) {
309 MonoType *extype = mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype, error);
311 if (!is_ok (error)) {
312 image_g_free (image, clauses);
313 return NULL;
315 clause->data.catch_class = mono_class_from_mono_type (extype);
316 } else {
317 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
318 clause->data.filter_offset = ex_block->filter_offset;
319 else
320 clause->data.filter_offset = 0;
322 finally_start = ex_block->start + ex_block->len;
324 clause_index ++;
328 return clauses;
330 #endif /* !DISABLE_REFLECTION_EMIT */
332 #ifndef DISABLE_REFLECTION_EMIT
334 * LOCKING: Acquires the loader lock.
336 static void
337 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
339 MONO_REQ_GC_UNSAFE_MODE;
341 MonoCustomAttrInfo *ainfo, *tmp;
343 if (!cattrs || !mono_array_length (cattrs))
344 return;
346 ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
348 mono_loader_lock ();
349 tmp = (MonoCustomAttrInfo *)mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
350 if (tmp)
351 mono_custom_attrs_free (tmp);
352 mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
353 mono_loader_unlock ();
356 #endif
358 guint32
359 mono_reflection_resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
361 MONO_REQ_GC_UNSAFE_MODE;
363 MonoDynamicTable *table;
364 guint32 token;
365 guint32 *values;
366 guint32 cols [MONO_ASSEMBLY_SIZE];
367 const char *pubkey;
368 guint32 publen;
370 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
371 return token;
373 if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
374 table = &assembly->tables [MONO_TABLE_MODULEREF];
375 token = table->next_idx ++;
376 table->rows ++;
377 alloc_table (table, table->rows);
378 values = table->values + token * MONO_MODULEREF_SIZE;
379 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
381 token <<= MONO_RESOLUTION_SCOPE_BITS;
382 token |= MONO_RESOLUTION_SCOPE_MODULEREF;
383 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
385 return token;
388 if (assembly_is_dynamic (image->assembly))
389 /* FIXME: */
390 memset (cols, 0, sizeof (cols));
391 else {
392 /* image->assembly->image is the manifest module */
393 image = image->assembly->image;
394 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
397 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
398 token = table->next_idx ++;
399 table->rows ++;
400 alloc_table (table, table->rows);
401 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
402 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
403 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
404 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
405 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
406 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
407 values [MONO_ASSEMBLYREF_FLAGS] = 0;
408 values [MONO_ASSEMBLYREF_CULTURE] = 0;
409 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
411 if (strcmp ("", image->assembly->aname.culture)) {
412 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
413 image->assembly->aname.culture);
416 if ((pubkey = mono_image_get_public_key (image, &publen))) {
417 guchar pubtoken [9];
418 pubtoken [0] = 8;
419 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
420 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
421 } else {
422 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
424 token <<= MONO_RESOLUTION_SCOPE_BITS;
425 token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
426 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
427 return token;
430 #ifndef DISABLE_REFLECTION_EMIT
431 gboolean
432 mono_reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error)
434 MONO_REQ_GC_UNSAFE_MODE;
436 mono_error_init (error);
437 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
439 rmb->ilgen = mb->ilgen;
440 rmb->rtype = (MonoReflectionType*)mb->rtype;
441 return_val_if_nok (error, FALSE);
442 rmb->parameters = mb->parameters;
443 rmb->generic_params = mb->generic_params;
444 rmb->generic_container = mb->generic_container;
445 rmb->opt_types = NULL;
446 rmb->pinfo = mb->pinfo;
447 rmb->attrs = mb->attrs;
448 rmb->iattrs = mb->iattrs;
449 rmb->call_conv = mb->call_conv;
450 rmb->code = mb->code;
451 rmb->type = mb->type;
452 rmb->name = mb->name;
453 rmb->table_idx = &mb->table_idx;
454 rmb->init_locals = mb->init_locals;
455 rmb->skip_visibility = FALSE;
456 rmb->return_modreq = mb->return_modreq;
457 rmb->return_modopt = mb->return_modopt;
458 rmb->param_modreq = mb->param_modreq;
459 rmb->param_modopt = mb->param_modopt;
460 rmb->permissions = mb->permissions;
461 rmb->mhandle = mb->mhandle;
462 rmb->nrefs = 0;
463 rmb->refs = NULL;
465 if (mb->dll) {
466 rmb->charset = mb->charset;
467 rmb->extra_flags = mb->extra_flags;
468 rmb->native_cc = mb->native_cc;
469 rmb->dllentry = mb->dllentry;
470 rmb->dll = mb->dll;
473 return TRUE;
476 gboolean
477 mono_reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error)
479 MONO_REQ_GC_UNSAFE_MODE;
481 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
483 mono_error_init (error);
485 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
487 rmb->ilgen = mb->ilgen;
488 rmb->rtype = mono_type_get_object_checked (mono_domain_get (), &mono_defaults.void_class->byval_arg, error);
489 return_val_if_nok (error, FALSE);
490 rmb->parameters = mb->parameters;
491 rmb->generic_params = NULL;
492 rmb->generic_container = NULL;
493 rmb->opt_types = NULL;
494 rmb->pinfo = mb->pinfo;
495 rmb->attrs = mb->attrs;
496 rmb->iattrs = mb->iattrs;
497 rmb->call_conv = mb->call_conv;
498 rmb->code = NULL;
499 rmb->type = mb->type;
500 rmb->name = mono_string_new (mono_domain_get (), name);
501 rmb->table_idx = &mb->table_idx;
502 rmb->init_locals = mb->init_locals;
503 rmb->skip_visibility = FALSE;
504 rmb->return_modreq = NULL;
505 rmb->return_modopt = NULL;
506 rmb->param_modreq = mb->param_modreq;
507 rmb->param_modopt = mb->param_modopt;
508 rmb->permissions = mb->permissions;
509 rmb->mhandle = mb->mhandle;
510 rmb->nrefs = 0;
511 rmb->refs = NULL;
513 return TRUE;
516 static void
517 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
519 MONO_REQ_GC_UNSAFE_MODE;
521 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
523 rmb->ilgen = mb->ilgen;
524 rmb->rtype = mb->rtype;
525 rmb->parameters = mb->parameters;
526 rmb->generic_params = NULL;
527 rmb->generic_container = NULL;
528 rmb->opt_types = NULL;
529 rmb->pinfo = NULL;
530 rmb->attrs = mb->attrs;
531 rmb->iattrs = 0;
532 rmb->call_conv = mb->call_conv;
533 rmb->code = NULL;
534 rmb->type = (MonoObject *) mb->owner;
535 rmb->name = mb->name;
536 rmb->table_idx = NULL;
537 rmb->init_locals = mb->init_locals;
538 rmb->skip_visibility = mb->skip_visibility;
539 rmb->return_modreq = NULL;
540 rmb->return_modopt = NULL;
541 rmb->param_modreq = NULL;
542 rmb->param_modopt = NULL;
543 rmb->permissions = NULL;
544 rmb->mhandle = mb->mhandle;
545 rmb->nrefs = 0;
546 rmb->refs = NULL;
548 #else /* DISABLE_REFLECTION_EMIT */
549 gboolean
550 mono_reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error) {
551 g_assert_not_reached ();
552 return FALSE;
554 gboolean
555 mono_reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error)
557 g_assert_not_reached ();
558 return FALSE;
560 #endif /* DISABLE_REFLECTION_EMIT */
562 #ifndef DISABLE_REFLECTION_EMIT
563 static guint32
564 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
566 MONO_REQ_GC_NEUTRAL_MODE;
568 MonoDynamicTable *table;
569 guint32 *values;
570 guint32 token, pclass;
572 switch (parent & MONO_TYPEDEFORREF_MASK) {
573 case MONO_TYPEDEFORREF_TYPEREF:
574 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
575 break;
576 case MONO_TYPEDEFORREF_TYPESPEC:
577 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
578 break;
579 case MONO_TYPEDEFORREF_TYPEDEF:
580 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
581 break;
582 default:
583 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
584 return 0;
586 /* extract the index */
587 parent >>= MONO_TYPEDEFORREF_BITS;
589 table = &assembly->tables [MONO_TABLE_MEMBERREF];
591 if (assembly->save) {
592 alloc_table (table, table->rows + 1);
593 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
594 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
595 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
596 values [MONO_MEMBERREF_SIGNATURE] = sig;
599 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
600 table->next_idx ++;
602 return token;
606 * Insert a memberef row into the metadata: the token that point to the memberref
607 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
608 * mono_image_get_fieldref_token()).
609 * The sig param is an index to an already built signature.
611 static guint32
612 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
614 MONO_REQ_GC_NEUTRAL_MODE;
616 guint32 parent = mono_image_typedef_or_ref (assembly, type);
617 return mono_image_add_memberef_row (assembly, parent, name, sig);
621 static guint32
622 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
624 MONO_REQ_GC_NEUTRAL_MODE;
626 guint32 token;
627 MonoMethodSignature *sig;
629 create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
631 if (create_typespec) {
632 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
633 if (token)
634 return token;
637 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
638 if (token && !create_typespec)
639 return token;
641 g_assert (!method->is_inflated);
642 if (!token) {
644 * A methodref signature can't contain an unmanaged calling convention.
646 sig = mono_metadata_signature_dup (mono_method_signature (method));
647 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
648 sig->call_convention = MONO_CALL_DEFAULT;
649 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
650 method->name, mono_dynimage_encode_method_signature (assembly, sig));
651 g_free (sig);
652 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
655 if (create_typespec) {
656 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
657 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
658 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
660 if (assembly->save) {
661 guint32 *values;
663 alloc_table (table, table->rows + 1);
664 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
665 values [MONO_METHODSPEC_METHOD] = token;
666 values [MONO_METHODSPEC_SIGNATURE] = mono_dynimage_encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
669 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
670 table->next_idx ++;
671 /*methodspec and memberef tokens are diferent, */
672 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
673 return token;
675 return token;
678 static guint32
679 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
680 const gchar *name, guint32 sig)
682 MonoDynamicTable *table;
683 guint32 token;
684 guint32 *values;
686 table = &assembly->tables [MONO_TABLE_MEMBERREF];
688 if (assembly->save) {
689 alloc_table (table, table->rows + 1);
690 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
691 values [MONO_MEMBERREF_CLASS] = original;
692 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
693 values [MONO_MEMBERREF_SIGNATURE] = sig;
696 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
697 table->next_idx ++;
699 return token;
702 #endif
704 static gboolean
705 is_field_on_inst (MonoClassField *field)
707 return mono_class_is_ginst (field->parent) && mono_class_get_generic_class (field->parent)->is_dynamic;
710 #ifndef DISABLE_REFLECTION_EMIT
711 static guint32
712 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
714 MonoType *type;
715 guint32 token;
717 g_assert (field);
718 g_assert (field->parent);
720 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
721 if (token)
722 return token;
724 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) {
725 int index = field - field->parent->fields;
726 type = mono_field_get_type (&mono_class_get_generic_class (field->parent)->container_class->fields [index]);
727 } else {
728 type = mono_field_get_type (field);
730 token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
731 mono_field_get_name (field),
732 mono_dynimage_encode_fieldref_signature (assembly, field->parent->image, type));
733 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
734 return token;
737 static guint32
738 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
740 MonoDynamicTable *table;
741 guint32 *values;
742 guint32 token, mtoken = 0, sig;
743 MonoMethodInflated *imethod;
744 MonoMethod *declaring;
746 table = &assembly->tables [MONO_TABLE_METHODSPEC];
748 g_assert (method->is_inflated);
749 imethod = (MonoMethodInflated *) method;
750 declaring = imethod->declaring;
752 sig = mono_dynimage_encode_method_signature (assembly, mono_method_signature (declaring));
753 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
755 if (!mono_method_signature (declaring)->generic_param_count)
756 return mtoken;
758 switch (mono_metadata_token_table (mtoken)) {
759 case MONO_TABLE_MEMBERREF:
760 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
761 break;
762 case MONO_TABLE_METHOD:
763 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
764 break;
765 default:
766 g_assert_not_reached ();
769 sig = mono_dynimage_encode_generic_method_sig (assembly, mono_method_get_context (method));
771 if (assembly->save) {
772 alloc_table (table, table->rows + 1);
773 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
774 values [MONO_METHODSPEC_METHOD] = mtoken;
775 values [MONO_METHODSPEC_SIGNATURE] = sig;
778 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
779 table->next_idx ++;
781 return token;
784 static guint32
785 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
787 MonoMethodInflated *imethod;
788 guint32 token;
790 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
791 if (token)
792 return token;
794 g_assert (method->is_inflated);
795 imethod = (MonoMethodInflated *) method;
797 if (mono_method_signature (imethod->declaring)->generic_param_count) {
798 token = method_encode_methodspec (assembly, method);
799 } else {
800 guint32 sig = mono_dynimage_encode_method_signature (
801 assembly, mono_method_signature (imethod->declaring));
802 token = mono_image_get_memberref_token (
803 assembly, &method->klass->byval_arg, method->name, sig);
806 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
807 return token;
810 static guint32
811 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
813 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
814 guint32 sig, token;
816 sig = mono_dynimage_encode_method_signature (assembly, mono_method_signature (imethod->declaring));
817 token = mono_image_get_memberref_token (
818 assembly, &m->klass->byval_arg, m->name, sig);
820 return token;
823 static guint32
824 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error)
826 guint32 idx;
827 MonoDynamicTable *table;
828 guint32 *values;
830 mono_error_init (error);
832 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
833 idx = table->next_idx ++;
834 table->rows ++;
835 alloc_table (table, table->rows);
836 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
838 values [MONO_STAND_ALONE_SIGNATURE] =
839 mono_dynimage_encode_reflection_sighelper (assembly, helper, error);
840 return_val_if_nok (error, 0);
842 return idx;
845 static int
846 reflection_cc_to_file (int call_conv) {
847 switch (call_conv & 0x3) {
848 case 0:
849 case 1: return MONO_CALL_DEFAULT;
850 case 2: return MONO_CALL_VARARG;
851 default:
852 g_assert_not_reached ();
854 return 0;
856 #endif /* !DISABLE_REFLECTION_EMIT */
858 struct _ArrayMethod {
859 MonoType *parent;
860 MonoMethodSignature *sig;
861 char *name;
862 guint32 token;
865 void
866 mono_sre_array_method_free (ArrayMethod *am)
868 g_free (am->sig);
869 g_free (am->name);
870 g_free (am);
873 #ifndef DISABLE_REFLECTION_EMIT
874 static guint32
875 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m, MonoError *error)
877 guint32 nparams, i;
878 GList *tmp;
879 char *name = NULL;
880 MonoMethodSignature *sig;
881 ArrayMethod *am = NULL;
882 MonoType *mtype;
884 mono_error_init (error);
886 nparams = mono_array_length (m->parameters);
887 sig = (MonoMethodSignature *)g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
888 sig->hasthis = 1;
889 sig->sentinelpos = -1;
890 sig->call_convention = reflection_cc_to_file (m->call_conv);
891 sig->param_count = nparams;
892 if (m->ret) {
893 sig->ret = mono_reflection_type_get_handle (m->ret, error);
894 if (!is_ok (error))
895 goto fail;
896 } else
897 sig->ret = &mono_defaults.void_class->byval_arg;
899 mtype = mono_reflection_type_get_handle (m->parent, error);
900 if (!is_ok (error))
901 goto fail;
903 for (i = 0; i < nparams; ++i) {
904 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i, error);
905 if (!is_ok (error))
906 goto fail;
909 name = mono_string_to_utf8_checked (m->name, error);
910 if (!is_ok (error))
911 goto fail;
912 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
913 am = (ArrayMethod *)tmp->data;
914 if (strcmp (name, am->name) == 0 &&
915 mono_metadata_type_equal (am->parent, mtype) &&
916 mono_metadata_signature_equal (am->sig, sig)) {
917 g_free (name);
918 g_free (sig);
919 m->table_idx = am->token & 0xffffff;
920 return am->token;
923 am = g_new0 (ArrayMethod, 1);
924 am->name = name;
925 am->sig = sig;
926 am->parent = mtype;
927 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
928 mono_dynimage_encode_method_signature (assembly, sig));
929 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
930 m->table_idx = am->token & 0xffffff;
931 return am->token;
932 fail:
933 g_free (am);
934 g_free (name);
935 g_free (sig);
936 return 0;
939 #endif
941 #ifndef DISABLE_REFLECTION_EMIT
944 * mono_image_insert_string:
945 * @module: module builder object
946 * @str: a string
948 * Insert @str into the user string stream of @module.
950 guint32
951 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
953 MonoDynamicImage *assembly;
954 guint32 idx;
955 char buf [16];
956 char *b = buf;
958 if (!module->dynamic_image)
959 mono_image_module_basic_init (module);
961 assembly = module->dynamic_image;
963 if (assembly->save) {
964 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
965 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
966 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
968 char *swapped = g_malloc (2 * mono_string_length (str));
969 const char *p = (const char*)mono_string_chars (str);
971 swap_with_size (swapped, p, 2, mono_string_length (str));
972 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
973 g_free (swapped);
975 #else
976 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
977 #endif
978 mono_image_add_stream_data (&assembly->us, "", 1);
979 } else {
980 idx = assembly->us.index ++;
983 mono_dynamic_image_register_token (assembly, MONO_TOKEN_STRING | idx, (MonoObject*)str);
985 return MONO_TOKEN_STRING | idx;
988 guint32
989 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
991 MonoClass *klass;
992 guint32 token = 0;
993 MonoMethodSignature *sig;
995 mono_error_init (error);
997 klass = obj->vtable->klass;
998 if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
999 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
1000 MonoMethodSignature *old;
1001 guint32 sig_token, parent;
1002 int nargs, i;
1004 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
1006 nargs = mono_array_length (opt_param_types);
1007 old = mono_method_signature (method);
1008 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
1010 sig->hasthis = old->hasthis;
1011 sig->explicit_this = old->explicit_this;
1012 sig->call_convention = old->call_convention;
1013 sig->generic_param_count = old->generic_param_count;
1014 sig->param_count = old->param_count + nargs;
1015 sig->sentinelpos = old->param_count;
1016 sig->ret = old->ret;
1018 for (i = 0; i < old->param_count; i++)
1019 sig->params [i] = old->params [i];
1021 for (i = 0; i < nargs; i++) {
1022 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
1023 sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt, error);
1024 if (!is_ok (error)) goto fail;
1027 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
1028 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
1029 parent >>= MONO_TYPEDEFORREF_BITS;
1031 parent <<= MONO_MEMBERREF_PARENT_BITS;
1032 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
1034 sig_token = mono_dynimage_encode_method_signature (assembly, sig);
1035 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
1036 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
1037 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
1038 ReflectionMethodBuilder rmb;
1039 guint32 parent, sig_token;
1040 int nopt_args, nparams, ngparams, i;
1042 if (!mono_reflection_methodbuilder_from_method_builder (&rmb, mb, error))
1043 goto fail;
1045 rmb.opt_types = opt_param_types;
1046 nopt_args = mono_array_length (opt_param_types);
1048 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
1049 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
1050 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
1052 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
1053 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
1054 sig->call_convention = rmb.call_conv;
1055 sig->generic_param_count = ngparams;
1056 sig->param_count = nparams + nopt_args;
1057 sig->sentinelpos = nparams;
1058 sig->ret = mono_reflection_type_get_handle (rmb.rtype, error);
1059 if (!is_ok (error)) goto fail;
1061 for (i = 0; i < nparams; i++) {
1062 MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
1063 sig->params [i] = mono_reflection_type_get_handle (rt, error);
1064 if (!is_ok (error)) goto fail;
1067 for (i = 0; i < nopt_args; i++) {
1068 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
1069 sig->params [nparams + i] = mono_reflection_type_get_handle (rt, error);
1070 if (!is_ok (error)) goto fail;
1073 // FIXME: This doesn't work, we don't use 'sig' for anything
1074 // The token fixup doesn't work either
1075 g_assert_not_reached ();
1077 sig_token = mono_dynimage_encode_method_builder_signature (assembly, &rmb, error);
1078 if (!is_ok (error))
1079 goto fail;
1081 parent = mono_image_create_token (assembly, obj, TRUE, TRUE, error);
1082 if (!mono_error_ok (error))
1083 goto fail;
1084 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
1086 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
1087 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
1089 char *name = mono_string_to_utf8_checked (rmb.name, error);
1090 if (!is_ok (error)) goto fail;
1091 token = mono_image_get_varargs_method_token (
1092 assembly, parent, name, sig_token);
1093 g_free (name);
1094 } else {
1095 g_error ("requested method token for %s\n", klass->name);
1098 g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
1099 mono_dynamic_image_register_token (assembly, token, obj);
1100 return token;
1101 fail:
1102 g_assert (!mono_error_ok (error));
1103 return 0;
1107 * mono_image_create_token:
1108 * @assembly: a dynamic assembly
1109 * @obj:
1110 * @register_token: Whenever to register the token in the assembly->tokens hash.
1112 * Get a token to insert in the IL code stream for the given MemberInfo.
1113 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
1114 * the table_idx-es were recomputed, so registering the token would overwrite an existing
1115 * entry.
1117 guint32
1118 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
1119 gboolean create_open_instance, gboolean register_token,
1120 MonoError *error)
1122 MonoClass *klass;
1123 guint32 token = 0;
1125 mono_error_init (error);
1127 klass = obj->vtable->klass;
1129 /* Check for user defined reflection objects */
1130 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
1131 if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0)) {
1132 mono_error_set_not_supported (error, "User defined subclasses of System.Type are not yet supported");
1133 return 0;
1136 if (strcmp (klass->name, "RuntimeType") == 0) {
1137 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
1138 return_val_if_nok (error, 0);
1139 MonoClass *mc = mono_class_from_mono_type (type);
1140 token = mono_metadata_token_from_dor (
1141 mono_dynimage_encode_typedef_or_ref_full (assembly, type, !mono_class_is_gtd (mc) || create_open_instance));
1142 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
1143 strcmp (klass->name, "MonoMethod") == 0) {
1144 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
1145 if (m->method->is_inflated) {
1146 if (create_open_instance)
1147 token = mono_image_get_methodspec_token (assembly, m->method);
1148 else
1149 token = mono_image_get_inflated_method_token (assembly, m->method);
1150 } else if ((m->method->klass->image == &assembly->image) &&
1151 !mono_class_is_ginst (m->method->klass)) {
1152 static guint32 method_table_idx = 0xffffff;
1153 if (m->method->klass->wastypebuilder) {
1154 /* we use the same token as the one that was assigned
1155 * to the Methodbuilder.
1156 * FIXME: do the equivalent for Fields.
1158 token = m->method->token;
1159 } else {
1161 * Each token should have a unique index, but the indexes are
1162 * assigned by managed code, so we don't know about them. An
1163 * easy solution is to count backwards...
1165 method_table_idx --;
1166 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
1168 } else {
1169 token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
1171 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
1172 } else if (strcmp (klass->name, "MonoField") == 0) {
1173 MonoReflectionField *f = (MonoReflectionField *)obj;
1174 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
1175 static guint32 field_table_idx = 0xffffff;
1176 field_table_idx --;
1177 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
1178 } else {
1179 token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
1181 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
1182 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
1183 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
1184 token = mono_image_get_array_token (assembly, m, error);
1185 return_val_if_nok (error, 0);
1186 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
1187 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
1188 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s, error);
1189 return_val_if_nok (error, 0);
1190 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
1191 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
1192 return_val_if_nok (error, 0);
1193 token = mono_metadata_token_from_dor (
1194 mono_image_typedef_or_ref (assembly, type));
1195 } else {
1196 g_error ("requested token for %s\n", klass->name);
1199 if (register_token)
1200 mono_image_register_token (assembly, token, obj);
1202 return token;
1206 #endif
1208 #ifndef DISABLE_REFLECTION_EMIT
1211 * mono_reflection_dynimage_basic_init:
1212 * @assembly: an assembly builder object
1214 * Create the MonoImage that represents the assembly builder and setup some
1215 * of the helper hash table and the basic metadata streams.
1217 void
1218 mono_reflection_dynimage_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
1220 MonoError error;
1221 MonoDynamicAssembly *assembly;
1222 MonoDynamicImage *image;
1223 MonoDomain *domain = mono_object_domain (assemblyb);
1225 if (assemblyb->dynamic_assembly)
1226 return;
1228 #if HAVE_BOEHM_GC
1229 /* assembly->assembly.image might be GC allocated */
1230 assembly = assemblyb->dynamic_assembly = (MonoDynamicAssembly *)GC_MALLOC (sizeof (MonoDynamicAssembly));
1231 #else
1232 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
1233 #endif
1235 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
1237 assembly->assembly.ref_count = 1;
1238 assembly->assembly.dynamic = TRUE;
1239 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
1240 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
1241 assembly->assembly.basedir = mono_string_to_utf8_checked (assemblyb->dir, &error);
1242 if (mono_error_set_pending_exception (&error))
1243 return;
1244 if (assemblyb->culture) {
1245 assembly->assembly.aname.culture = mono_string_to_utf8_checked (assemblyb->culture, &error);
1246 if (mono_error_set_pending_exception (&error))
1247 return;
1248 } else
1249 assembly->assembly.aname.culture = g_strdup ("");
1251 if (assemblyb->version) {
1252 char *vstr = mono_string_to_utf8_checked (assemblyb->version, &error);
1253 if (mono_error_set_pending_exception (&error))
1254 return;
1255 char **version = g_strsplit (vstr, ".", 4);
1256 char **parts = version;
1257 assembly->assembly.aname.major = atoi (*parts++);
1258 assembly->assembly.aname.minor = atoi (*parts++);
1259 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
1260 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
1262 g_strfreev (version);
1263 g_free (vstr);
1264 } else {
1265 assembly->assembly.aname.major = 0;
1266 assembly->assembly.aname.minor = 0;
1267 assembly->assembly.aname.build = 0;
1268 assembly->assembly.aname.revision = 0;
1271 assembly->run = assemblyb->access != 2;
1272 assembly->save = assemblyb->access != 1;
1273 assembly->domain = domain;
1275 char *assembly_name = mono_string_to_utf8_checked (assemblyb->name, &error);
1276 if (mono_error_set_pending_exception (&error))
1277 return;
1278 image = mono_dynamic_image_create (assembly, assembly_name, g_strdup ("RefEmit_YouForgotToDefineAModule"));
1279 image->initial_image = TRUE;
1280 assembly->assembly.aname.name = image->image.name;
1281 assembly->assembly.image = &image->image;
1282 if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
1283 /* -1 to correct for the trailing NULL byte */
1284 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
1285 g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
1287 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);
1290 mono_domain_assemblies_lock (domain);
1291 domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
1292 mono_domain_assemblies_unlock (domain);
1294 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
1296 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
1298 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
1301 #endif /* !DISABLE_REFLECTION_EMIT */
1303 #ifndef DISABLE_REFLECTION_EMIT
1304 static gpointer
1305 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
1307 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
1310 static gpointer
1311 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
1313 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
1316 static gboolean
1317 image_module_basic_init (MonoReflectionModuleBuilder *moduleb, MonoError *error)
1319 MonoDynamicImage *image = moduleb->dynamic_image;
1320 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
1321 mono_error_init (error);
1322 if (!image) {
1323 int module_count;
1324 MonoImage **new_modules;
1325 MonoImage *ass;
1326 char *name, *fqname;
1328 * FIXME: we already created an image in mono_reflection_dynimage_basic_init (), but
1329 * we don't know which module it belongs to, since that is only
1330 * determined at assembly save time.
1332 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
1333 name = mono_string_to_utf8_checked (ab->name, error);
1334 return_val_if_nok (error, FALSE);
1335 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, error);
1336 if (!is_ok (error)) {
1337 g_free (name);
1338 return FALSE;
1340 image = mono_dynamic_image_create (ab->dynamic_assembly, name, fqname);
1342 moduleb->module.image = &image->image;
1343 moduleb->dynamic_image = image;
1344 register_module (mono_object_domain (moduleb), moduleb, image);
1346 /* register the module with the assembly */
1347 ass = ab->dynamic_assembly->assembly.image;
1348 module_count = ass->module_count;
1349 new_modules = g_new0 (MonoImage *, module_count + 1);
1351 if (ass->modules)
1352 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
1353 new_modules [module_count] = &image->image;
1354 mono_image_addref (&image->image);
1356 g_free (ass->modules);
1357 ass->modules = new_modules;
1358 ass->module_count ++;
1360 return TRUE;
1363 static void
1364 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
1366 MonoError error;
1367 (void) image_module_basic_init (moduleb, &error);
1368 mono_error_set_pending_exception (&error);
1371 #endif
1373 static gboolean
1374 is_corlib_type (MonoClass *klass)
1376 return klass->image == mono_defaults.corlib;
1379 #define check_corlib_type_cached(_class, _namespace, _name) do { \
1380 static MonoClass *cached_class; \
1381 if (cached_class) \
1382 return cached_class == _class; \
1383 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
1384 cached_class = _class; \
1385 return TRUE; \
1387 return FALSE; \
1388 } while (0) \
1392 #ifndef DISABLE_REFLECTION_EMIT
1393 static gboolean
1394 is_sre_array (MonoClass *klass)
1396 check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
1399 static gboolean
1400 is_sre_byref (MonoClass *klass)
1402 check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
1405 static gboolean
1406 is_sre_pointer (MonoClass *klass)
1408 check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
1411 static gboolean
1412 is_sre_generic_instance (MonoClass *klass)
1414 check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilderInstantiation");
1417 static gboolean
1418 is_sre_type_builder (MonoClass *klass)
1420 check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
1423 static gboolean
1424 is_sre_method_builder (MonoClass *klass)
1426 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
1429 gboolean
1430 mono_is_sre_ctor_builder (MonoClass *klass)
1432 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
1435 static gboolean
1436 is_sre_field_builder (MonoClass *klass)
1438 check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
1441 static gboolean
1442 is_sre_gparam_builder (MonoClass *klass)
1444 check_corlib_type_cached (klass, "System.Reflection.Emit", "GenericTypeParameterBuilder");
1447 static gboolean
1448 is_sre_enum_builder (MonoClass *klass)
1450 check_corlib_type_cached (klass, "System.Reflection.Emit", "EnumBuilder");
1453 gboolean
1454 mono_is_sre_method_on_tb_inst (MonoClass *klass)
1456 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
1459 gboolean
1460 mono_is_sre_ctor_on_tb_inst (MonoClass *klass)
1462 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
1465 static MonoReflectionType*
1466 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error)
1468 static MonoMethod *method_get_underlying_system_type = NULL;
1469 MonoReflectionType *rt;
1470 MonoMethod *usertype_method;
1472 mono_error_init (error);
1474 if (!method_get_underlying_system_type)
1475 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
1477 usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
1479 rt = (MonoReflectionType *) mono_runtime_invoke_checked (usertype_method, t, NULL, error);
1481 return rt;
1484 MonoType*
1485 mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
1487 MonoClass *klass;
1488 mono_error_init (error);
1490 if (!ref)
1491 return NULL;
1492 if (ref->type)
1493 return ref->type;
1495 if (mono_reflection_is_usertype (ref)) {
1496 ref = mono_reflection_type_get_underlying_system_type (ref, error);
1497 if (ref == NULL || mono_reflection_is_usertype (ref) || !is_ok (error))
1498 return NULL;
1499 if (ref->type)
1500 return ref->type;
1503 klass = mono_object_class (ref);
1505 if (is_sre_array (klass)) {
1506 MonoType *res;
1507 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
1508 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type, error);
1509 return_val_if_nok (error, NULL);
1510 g_assert (base);
1511 if (sre_array->rank == 0) //single dimentional array
1512 res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
1513 else
1514 res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
1515 sre_array->type.type = res;
1516 return res;
1517 } else if (is_sre_byref (klass)) {
1518 MonoType *res;
1519 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
1520 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type, error);
1521 return_val_if_nok (error, NULL);
1522 g_assert (base);
1523 res = &mono_class_from_mono_type (base)->this_arg;
1524 sre_byref->type.type = res;
1525 return res;
1526 } else if (is_sre_pointer (klass)) {
1527 MonoType *res;
1528 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
1529 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type, error);
1530 return_val_if_nok (error, NULL);
1531 g_assert (base);
1532 res = &mono_ptr_class_get (base)->byval_arg;
1533 sre_pointer->type.type = res;
1534 return res;
1535 } else if (is_sre_generic_instance (klass)) {
1536 MonoType *res, **types;
1537 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
1538 int i, count;
1540 count = mono_array_length (gclass->type_arguments);
1541 types = g_new0 (MonoType*, count);
1542 for (i = 0; i < count; ++i) {
1543 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (gclass->type_arguments, gpointer, i);
1544 types [i] = mono_reflection_type_get_handle (t, error);
1545 if (!types[i] || !is_ok (error)) {
1546 g_free (types);
1547 return NULL;
1551 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types, error);
1552 g_free (types);
1553 g_assert (res);
1554 gclass->type.type = res;
1555 return res;
1556 } else if (is_sre_gparam_builder (klass)) {
1557 MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)ref;
1558 MonoGenericParamFull *param;
1559 MonoImage *image;
1560 MonoClass *pklass;
1562 image = &gparam->tbuilder->module->dynamic_image->image;
1564 param = mono_image_new0 (image, MonoGenericParamFull, 1);
1566 param->info.name = mono_string_to_utf8_image (image, gparam->name, error);
1567 mono_error_assert_ok (error);
1568 param->param.num = gparam->index;
1570 if (gparam->mbuilder) {
1571 if (!gparam->mbuilder->generic_container) {
1572 gparam->mbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (image, sizeof (MonoGenericContainer));
1573 gparam->mbuilder->generic_container->is_method = TRUE;
1575 * Cannot set owner.method, since the MonoMethod is not created yet.
1576 * Set the image field instead, so type_in_image () works.
1578 gparam->mbuilder->generic_container->is_anonymous = TRUE;
1579 gparam->mbuilder->generic_container->owner.image = image;
1581 param->param.owner = gparam->mbuilder->generic_container;
1582 } else if (gparam->tbuilder) {
1583 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)(gparam->tbuilder), error);
1584 mono_error_assert_ok (error);
1585 MonoClass *owner = mono_class_from_mono_type (type);
1586 g_assert (mono_class_is_gtd (owner));
1587 param->param.owner = mono_class_get_generic_container (owner);
1590 pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
1592 gparam->type.type = &pklass->byval_arg;
1594 mono_class_set_ref_info (pklass, gparam);
1595 mono_image_append_class_to_reflection_info_set (pklass);
1597 return &pklass->byval_arg;
1598 } else if (is_sre_enum_builder (klass)) {
1599 MonoReflectionEnumBuilder *ebuilder = (MonoReflectionEnumBuilder *)ref;
1601 return mono_reflection_type_get_handle ((MonoReflectionType*)ebuilder->tb, error);
1602 } else if (is_sre_type_builder (klass)) {
1603 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)ref;
1605 /* This happens when a finished type references an unfinished one. Have to create the minimal type */
1606 reflection_setup_internal_class (tb, error);
1607 mono_error_assert_ok (error);
1608 g_assert (ref->type);
1609 return ref->type;
1612 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
1613 return NULL;
1617 * LOCKING: Assumes the loader lock is held.
1619 static MonoMethodSignature*
1620 parameters_to_signature (MonoImage *image, MonoArray *parameters, MonoError *error) {
1621 MonoMethodSignature *sig;
1622 int count, i;
1624 mono_error_init (error);
1626 count = parameters? mono_array_length (parameters): 0;
1628 sig = (MonoMethodSignature *)mono_image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
1629 sig->param_count = count;
1630 sig->sentinelpos = -1; /* FIXME */
1631 for (i = 0; i < count; ++i) {
1632 sig->params [i] = mono_type_array_get_and_resolve (parameters, i, error);
1633 if (!is_ok (error)) {
1634 image_g_free (image, sig);
1635 return NULL;
1638 return sig;
1642 * LOCKING: Assumes the loader lock is held.
1644 static MonoMethodSignature*
1645 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor, MonoError *error) {
1646 MonoMethodSignature *sig;
1648 mono_error_init (error);
1650 sig = parameters_to_signature (image, ctor->parameters, error);
1651 return_val_if_nok (error, NULL);
1652 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
1653 sig->ret = &mono_defaults.void_class->byval_arg;
1654 return sig;
1658 * LOCKING: Assumes the loader lock is held.
1660 static MonoMethodSignature*
1661 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method, MonoError *error) {
1662 MonoMethodSignature *sig;
1664 mono_error_init (error);
1666 sig = parameters_to_signature (image, method->parameters, error);
1667 return_val_if_nok (error, NULL);
1668 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
1669 if (method->rtype) {
1670 sig->ret = mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype, error);
1671 if (!is_ok (error)) {
1672 image_g_free (image, sig);
1673 return NULL;
1675 } else {
1676 sig->ret = &mono_defaults.void_class->byval_arg;
1678 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
1679 return sig;
1682 static MonoMethodSignature*
1683 dynamic_method_to_signature (MonoReflectionDynamicMethod *method, MonoError *error) {
1684 MonoMethodSignature *sig;
1686 mono_error_init (error);
1688 sig = parameters_to_signature (NULL, method->parameters, error);
1689 return_val_if_nok (error, NULL);
1690 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
1691 if (method->rtype) {
1692 sig->ret = mono_reflection_type_get_handle (method->rtype, error);
1693 if (!is_ok (error)) {
1694 g_free (sig);
1695 return NULL;
1697 } else {
1698 sig->ret = &mono_defaults.void_class->byval_arg;
1700 sig->generic_param_count = 0;
1701 return sig;
1704 static void
1705 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type, MonoError *error)
1707 mono_error_init (error);
1708 MonoClass *klass = mono_object_class (prop);
1709 if (strcmp (klass->name, "PropertyBuilder") == 0) {
1710 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
1711 *name = mono_string_to_utf8_checked (pb->name, error);
1712 return_if_nok (error);
1713 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type, error);
1714 } else {
1715 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
1716 *name = g_strdup (p->property->name);
1717 if (p->property->get)
1718 *type = mono_method_signature (p->property->get)->ret;
1719 else
1720 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
1724 static void
1725 get_field_name_and_type (MonoObject *field, char **name, MonoType **type, MonoError *error)
1727 mono_error_init (error);
1728 MonoClass *klass = mono_object_class (field);
1729 if (strcmp (klass->name, "FieldBuilder") == 0) {
1730 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
1731 *name = mono_string_to_utf8_checked (fb->name, error);
1732 return_if_nok (error);
1733 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
1734 } else {
1735 MonoReflectionField *f = (MonoReflectionField *)field;
1736 *name = g_strdup (mono_field_get_name (f->field));
1737 *type = f->field->type;
1741 #else /* DISABLE_REFLECTION_EMIT */
1743 static gboolean
1744 is_sre_type_builder (MonoClass *klass)
1746 return FALSE;
1749 static gboolean
1750 is_sre_generic_instance (MonoClass *klass)
1752 return FALSE;
1755 gboolean
1756 mono_is_sre_ctor_builder (MonoClass *klass)
1758 return FALSE;
1761 gboolean
1762 mono_is_sre_method_on_tb_inst (MonoClass *klass)
1764 return FALSE;
1767 gboolean
1768 mono_is_sre_ctor_on_tb_inst (MonoClass *klass)
1770 return FALSE;
1773 #endif /* !DISABLE_REFLECTION_EMIT */
1776 static gboolean
1777 is_sr_mono_field (MonoClass *klass)
1779 check_corlib_type_cached (klass, "System.Reflection", "MonoField");
1782 gboolean
1783 mono_is_sr_mono_property (MonoClass *klass)
1785 check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
1788 static gboolean
1789 is_sr_mono_method (MonoClass *klass)
1791 check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
1794 gboolean
1795 mono_is_sr_mono_cmethod (MonoClass *klass)
1797 check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
1800 gboolean
1801 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
1803 return is_sr_mono_method (klass) || mono_is_sr_mono_cmethod (klass);
1806 gboolean
1807 mono_is_sre_type_builder (MonoClass *klass)
1809 return is_sre_type_builder (klass);
1812 gboolean
1813 mono_is_sre_generic_instance (MonoClass *klass)
1815 return is_sre_generic_instance (klass);
1821 * encode_cattr_value:
1822 * Encode a value in a custom attribute stream of bytes.
1823 * The value to encode is either supplied as an object in argument val
1824 * (valuetypes are boxed), or as a pointer to the data in the
1825 * argument argval.
1826 * @type represents the type of the value
1827 * @buffer is the start of the buffer
1828 * @p the current position in the buffer
1829 * @buflen contains the size of the buffer and is used to return the new buffer size
1830 * if this needs to be realloced.
1831 * @retbuffer and @retp return the start and the position of the buffer
1832 * @error set on error.
1834 static void
1835 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval, MonoError *error)
1837 MonoTypeEnum simple_type;
1839 mono_error_init (error);
1840 if ((p-buffer) + 10 >= *buflen) {
1841 char *newbuf;
1842 *buflen *= 2;
1843 newbuf = (char *)g_realloc (buffer, *buflen);
1844 p = newbuf + (p-buffer);
1845 buffer = newbuf;
1847 if (!argval)
1848 argval = ((char*)arg + sizeof (MonoObject));
1849 simple_type = type->type;
1850 handle_enum:
1851 switch (simple_type) {
1852 case MONO_TYPE_BOOLEAN:
1853 case MONO_TYPE_U1:
1854 case MONO_TYPE_I1:
1855 *p++ = *argval;
1856 break;
1857 case MONO_TYPE_CHAR:
1858 case MONO_TYPE_U2:
1859 case MONO_TYPE_I2:
1860 swap_with_size (p, argval, 2, 1);
1861 p += 2;
1862 break;
1863 case MONO_TYPE_U4:
1864 case MONO_TYPE_I4:
1865 case MONO_TYPE_R4:
1866 swap_with_size (p, argval, 4, 1);
1867 p += 4;
1868 break;
1869 case MONO_TYPE_R8:
1870 swap_with_size (p, argval, 8, 1);
1871 p += 8;
1872 break;
1873 case MONO_TYPE_U8:
1874 case MONO_TYPE_I8:
1875 swap_with_size (p, argval, 8, 1);
1876 p += 8;
1877 break;
1878 case MONO_TYPE_VALUETYPE:
1879 if (type->data.klass->enumtype) {
1880 simple_type = mono_class_enum_basetype (type->data.klass)->type;
1881 goto handle_enum;
1882 } else {
1883 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
1885 break;
1886 case MONO_TYPE_STRING: {
1887 char *str;
1888 guint32 slen;
1889 if (!arg) {
1890 *p++ = 0xFF;
1891 break;
1893 str = mono_string_to_utf8_checked ((MonoString*)arg, error);
1894 return_if_nok (error);
1895 slen = strlen (str);
1896 if ((p-buffer) + 10 + slen >= *buflen) {
1897 char *newbuf;
1898 *buflen *= 2;
1899 *buflen += slen;
1900 newbuf = (char *)g_realloc (buffer, *buflen);
1901 p = newbuf + (p-buffer);
1902 buffer = newbuf;
1904 mono_metadata_encode_value (slen, p, &p);
1905 memcpy (p, str, slen);
1906 p += slen;
1907 g_free (str);
1908 break;
1910 case MONO_TYPE_CLASS: {
1911 char *str;
1912 guint32 slen;
1913 MonoType *arg_type;
1914 if (!arg) {
1915 *p++ = 0xFF;
1916 break;
1918 handle_type:
1919 arg_type = mono_reflection_type_get_handle ((MonoReflectionType*)arg, error);
1920 return_if_nok (error);
1922 str = type_get_qualified_name (arg_type, NULL);
1923 slen = strlen (str);
1924 if ((p-buffer) + 10 + slen >= *buflen) {
1925 char *newbuf;
1926 *buflen *= 2;
1927 *buflen += slen;
1928 newbuf = (char *)g_realloc (buffer, *buflen);
1929 p = newbuf + (p-buffer);
1930 buffer = newbuf;
1932 mono_metadata_encode_value (slen, p, &p);
1933 memcpy (p, str, slen);
1934 p += slen;
1935 g_free (str);
1936 break;
1938 case MONO_TYPE_SZARRAY: {
1939 int len, i;
1940 MonoClass *eclass, *arg_eclass;
1942 if (!arg) {
1943 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
1944 break;
1946 len = mono_array_length ((MonoArray*)arg);
1947 *p++ = len & 0xff;
1948 *p++ = (len >> 8) & 0xff;
1949 *p++ = (len >> 16) & 0xff;
1950 *p++ = (len >> 24) & 0xff;
1951 *retp = p;
1952 *retbuffer = buffer;
1953 eclass = type->data.klass;
1954 arg_eclass = mono_object_class (arg)->element_class;
1956 if (!eclass) {
1957 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
1958 eclass = mono_defaults.object_class;
1960 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
1961 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
1962 int elsize = mono_class_array_element_size (arg_eclass);
1963 for (i = 0; i < len; ++i) {
1964 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr, error);
1965 return_if_nok (error);
1966 elptr += elsize;
1968 } else if (eclass->valuetype && arg_eclass->valuetype) {
1969 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
1970 int elsize = mono_class_array_element_size (eclass);
1971 for (i = 0; i < len; ++i) {
1972 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr, error);
1973 return_if_nok (error);
1974 elptr += elsize;
1976 } else {
1977 for (i = 0; i < len; ++i) {
1978 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL, error);
1979 return_if_nok (error);
1982 break;
1984 case MONO_TYPE_OBJECT: {
1985 MonoClass *klass;
1986 char *str;
1987 guint32 slen;
1990 * The parameter type is 'object' but the type of the actual
1991 * argument is not. So we have to add type information to the blob
1992 * too. This is completely undocumented in the spec.
1995 if (arg == NULL) {
1996 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
1997 *p++ = 0xFF;
1998 break;
2001 klass = mono_object_class (arg);
2003 if (mono_object_isinst_checked (arg, mono_defaults.systemtype_class, error)) {
2004 *p++ = 0x50;
2005 goto handle_type;
2006 } else {
2007 return_if_nok (error);
2010 if (klass->enumtype) {
2011 *p++ = 0x55;
2012 } else if (klass == mono_defaults.string_class) {
2013 simple_type = MONO_TYPE_STRING;
2014 *p++ = 0x0E;
2015 goto handle_enum;
2016 } else if (klass->rank == 1) {
2017 *p++ = 0x1D;
2018 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
2019 /* See Partition II, Appendix B3 */
2020 *p++ = 0x51;
2021 else
2022 *p++ = klass->element_class->byval_arg.type;
2023 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL, error);
2024 return_if_nok (error);
2025 break;
2026 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
2027 *p++ = simple_type = klass->byval_arg.type;
2028 goto handle_enum;
2029 } else {
2030 g_error ("unhandled type in custom attr");
2032 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
2033 slen = strlen (str);
2034 if ((p-buffer) + 10 + slen >= *buflen) {
2035 char *newbuf;
2036 *buflen *= 2;
2037 *buflen += slen;
2038 newbuf = (char *)g_realloc (buffer, *buflen);
2039 p = newbuf + (p-buffer);
2040 buffer = newbuf;
2042 mono_metadata_encode_value (slen, p, &p);
2043 memcpy (p, str, slen);
2044 p += slen;
2045 g_free (str);
2046 simple_type = mono_class_enum_basetype (klass)->type;
2047 goto handle_enum;
2049 default:
2050 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
2052 *retp = p;
2053 *retbuffer = buffer;
2056 static void
2057 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
2059 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
2060 char *str = type_get_qualified_name (type, NULL);
2061 int slen = strlen (str);
2063 *p++ = 0x55;
2065 * This seems to be optional...
2066 * *p++ = 0x80;
2068 mono_metadata_encode_value (slen, p, &p);
2069 memcpy (p, str, slen);
2070 p += slen;
2071 g_free (str);
2072 } else if (type->type == MONO_TYPE_OBJECT) {
2073 *p++ = 0x51;
2074 } else if (type->type == MONO_TYPE_CLASS) {
2075 /* it should be a type: encode_cattr_value () has the check */
2076 *p++ = 0x50;
2077 } else {
2078 mono_metadata_encode_value (type->type, p, &p);
2079 if (type->type == MONO_TYPE_SZARRAY)
2080 /* See the examples in Partition VI, Annex B */
2081 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
2084 *retp = p;
2087 #ifndef DISABLE_REFLECTION_EMIT
2088 static void
2089 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value, MonoError *error)
2091 int len;
2093 mono_error_init (error);
2095 /* Preallocate a large enough buffer */
2096 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
2097 char *str = type_get_qualified_name (type, NULL);
2098 len = strlen (str);
2099 g_free (str);
2100 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
2101 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
2102 len = strlen (str);
2103 g_free (str);
2104 } else {
2105 len = 0;
2107 len += strlen (name);
2109 if ((p-buffer) + 20 + len >= *buflen) {
2110 char *newbuf;
2111 *buflen *= 2;
2112 *buflen += len;
2113 newbuf = (char *)g_realloc (buffer, *buflen);
2114 p = newbuf + (p-buffer);
2115 buffer = newbuf;
2118 encode_field_or_prop_type (type, p, &p);
2120 len = strlen (name);
2121 mono_metadata_encode_value (len, p, &p);
2122 memcpy (p, name, len);
2123 p += len;
2124 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL, error);
2125 return_if_nok (error);
2126 *retp = p;
2127 *retbuffer = buffer;
2131 * mono_reflection_get_custom_attrs_blob:
2132 * @ctor: custom attribute constructor
2133 * @ctorArgs: arguments o the constructor
2134 * @properties:
2135 * @propValues:
2136 * @fields:
2137 * @fieldValues:
2139 * Creates the blob of data that needs to be saved in the metadata and that represents
2140 * the custom attributed described by @ctor, @ctorArgs etc.
2141 * Returns: a Byte array representing the blob of data.
2143 MonoArray*
2144 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
2146 MonoError error;
2147 MonoArray *result = mono_reflection_get_custom_attrs_blob_checked (assembly, ctor, ctorArgs, properties, propValues, fields, fieldValues, &error);
2148 mono_error_cleanup (&error);
2149 return result;
2153 * mono_reflection_get_custom_attrs_blob_checked:
2154 * @ctor: custom attribute constructor
2155 * @ctorArgs: arguments o the constructor
2156 * @properties:
2157 * @propValues:
2158 * @fields:
2159 * @fieldValues:
2160 * @error: set on error
2162 * Creates the blob of data that needs to be saved in the metadata and that represents
2163 * the custom attributed described by @ctor, @ctorArgs etc.
2164 * Returns: a Byte array representing the blob of data. On failure returns NULL and sets @error.
2166 MonoArray*
2167 mono_reflection_get_custom_attrs_blob_checked (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues, MonoError *error)
2169 MonoArray *result = NULL;
2170 MonoMethodSignature *sig;
2171 MonoObject *arg;
2172 char *buffer, *p;
2173 guint32 buflen, i;
2175 mono_error_init (error);
2177 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
2178 /* sig is freed later so allocate it in the heap */
2179 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor, error);
2180 if (!is_ok (error)) {
2181 g_free (sig);
2182 return NULL;
2184 } else {
2185 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
2188 g_assert (mono_array_length (ctorArgs) == sig->param_count);
2189 buflen = 256;
2190 p = buffer = (char *)g_malloc (buflen);
2191 /* write the prolog */
2192 *p++ = 1;
2193 *p++ = 0;
2194 for (i = 0; i < sig->param_count; ++i) {
2195 arg = mono_array_get (ctorArgs, MonoObject*, i);
2196 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL, error);
2197 if (!is_ok (error)) goto leave;
2199 i = 0;
2200 if (properties)
2201 i += mono_array_length (properties);
2202 if (fields)
2203 i += mono_array_length (fields);
2204 *p++ = i & 0xff;
2205 *p++ = (i >> 8) & 0xff;
2206 if (properties) {
2207 MonoObject *prop;
2208 for (i = 0; i < mono_array_length (properties); ++i) {
2209 MonoType *ptype;
2210 char *pname;
2212 prop = (MonoObject *)mono_array_get (properties, gpointer, i);
2213 get_prop_name_and_type (prop, &pname, &ptype, error);
2214 if (!is_ok (error)) goto leave;
2215 *p++ = 0x54; /* PROPERTY signature */
2216 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i), error);
2217 g_free (pname);
2218 if (!is_ok (error)) goto leave;
2222 if (fields) {
2223 MonoObject *field;
2224 for (i = 0; i < mono_array_length (fields); ++i) {
2225 MonoType *ftype;
2226 char *fname;
2228 field = (MonoObject *)mono_array_get (fields, gpointer, i);
2229 get_field_name_and_type (field, &fname, &ftype, error);
2230 if (!is_ok (error)) goto leave;
2231 *p++ = 0x53; /* FIELD signature */
2232 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i), error);
2233 g_free (fname);
2234 if (!is_ok (error)) goto leave;
2238 g_assert (p - buffer <= buflen);
2239 buflen = p - buffer;
2240 result = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, buflen, error);
2241 if (!is_ok (error))
2242 goto leave;
2243 p = mono_array_addr (result, char, 0);
2244 memcpy (p, buffer, buflen);
2245 leave:
2246 g_free (buffer);
2247 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
2248 g_free (sig);
2249 return result;
2253 * reflection_setup_internal_class:
2254 * @tb: a TypeBuilder object
2255 * @error: set on error
2257 * Creates a MonoClass that represents the TypeBuilder.
2258 * This is a trick that lets us simplify a lot of reflection code
2259 * (and will allow us to support Build and Run assemblies easier).
2261 * Returns TRUE on success. On failure, returns FALSE and sets @error.
2263 static gboolean
2264 reflection_setup_internal_class (MonoReflectionTypeBuilder *tb, MonoError *error)
2266 MonoClass *klass, *parent;
2268 mono_error_init (error);
2270 mono_loader_lock ();
2272 if (tb->parent) {
2273 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
2274 if (!is_ok (error)) {
2275 mono_loader_unlock ();
2276 return FALSE;
2278 /* check so we can compile corlib correctly */
2279 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
2280 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
2281 parent = parent_type->data.klass;
2282 } else {
2283 parent = mono_class_from_mono_type (parent_type);
2285 } else {
2286 parent = NULL;
2289 /* the type has already being created: it means we just have to change the parent */
2290 if (tb->type.type) {
2291 klass = mono_class_from_mono_type (tb->type.type);
2292 klass->parent = NULL;
2293 /* fool mono_class_setup_parent */
2294 klass->supertypes = NULL;
2295 mono_class_setup_parent (klass, parent);
2296 mono_class_setup_mono_type (klass);
2297 mono_loader_unlock ();
2298 return TRUE;
2302 * The size calculation here warrants some explaining.
2303 * reflection_setup_internal_class is called too early, well before we know whether the type will be a GTD or DEF,
2304 * meaning we need to alloc enough space to morth a def into a gtd.
2306 klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, MAX (sizeof (MonoClassDef), sizeof (MonoClassGtd)));
2307 klass->class_kind = MONO_CLASS_DEF;
2309 klass->image = &tb->module->dynamic_image->image;
2311 klass->inited = 1; /* we lie to the runtime */
2312 klass->name = mono_string_to_utf8_image (klass->image, tb->name, error);
2313 if (!is_ok (error))
2314 goto failure;
2315 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, error);
2316 if (!is_ok (error))
2317 goto failure;
2318 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
2319 mono_class_set_flags (klass, tb->attrs);
2321 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
2323 klass->element_class = klass;
2325 if (mono_class_get_ref_info (klass) == NULL) {
2326 mono_class_set_ref_info (klass, tb);
2328 /* Put into cache so mono_class_get_checked () will find it.
2329 Skip nested types as those should not be available on the global scope. */
2330 if (!tb->nesting_type)
2331 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
2334 We must register all types as we cannot rely on the name_cache hashtable since we find the class
2335 by performing a mono_class_get which does the full resolution.
2337 Working around this semantics would require us to write a lot of code for no clear advantage.
2339 mono_image_append_class_to_reflection_info_set (klass);
2340 } else {
2341 g_assert (mono_class_get_ref_info (klass) == tb);
2344 mono_dynamic_image_register_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
2346 if (parent != NULL) {
2347 mono_class_setup_parent (klass, parent);
2348 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
2349 const char *old_n = klass->name;
2350 /* trick to get relative numbering right when compiling corlib */
2351 klass->name = "BuildingObject";
2352 mono_class_setup_parent (klass, mono_defaults.object_class);
2353 klass->name = old_n;
2356 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
2357 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
2358 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
2359 klass->instance_size = sizeof (MonoObject);
2360 klass->size_inited = 1;
2361 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
2364 mono_class_setup_mono_type (klass);
2366 mono_class_setup_supertypes (klass);
2369 * FIXME: handle interfaces.
2372 tb->type.type = &klass->byval_arg;
2374 if (tb->nesting_type) {
2375 reflection_setup_internal_class ((MonoReflectionTypeBuilder*)tb->nesting_type, error);
2376 g_assert (tb->nesting_type->type);
2377 MonoType *nesting_type = mono_reflection_type_get_handle (tb->nesting_type, error);
2378 if (!is_ok (error)) goto failure;
2379 klass->nested_in = mono_class_from_mono_type (nesting_type);
2382 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
2384 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
2386 mono_loader_unlock ();
2387 return TRUE;
2389 failure:
2390 mono_loader_unlock ();
2391 return FALSE;
2395 * reflection_create_generic_class:
2396 * @tb: a TypeBuilder object
2397 * @error: set on error
2399 * Creates the generic class after all generic parameters have been added.
2400 * On success returns TRUE, on failure returns FALSE and sets @error.
2402 static gboolean
2403 reflection_create_generic_class (MonoReflectionTypeBuilder *tb, MonoError *error)
2405 MonoClass *klass;
2406 int count, i;
2408 mono_error_init (error);
2410 reflection_setup_internal_class (tb, error);
2412 klass = mono_class_from_mono_type (tb->type.type);
2414 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
2416 if (count == 0)
2417 return TRUE;
2419 MonoGenericContainer *generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
2421 generic_container->owner.klass = klass;
2422 generic_container->type_argc = count;
2423 generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
2425 klass->class_kind = MONO_CLASS_GTD;
2426 mono_class_set_generic_container (klass, generic_container);
2429 for (i = 0; i < count; i++) {
2430 MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)mono_array_get (tb->generic_params, gpointer, i);
2431 MonoType *param_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, error);
2432 return_val_if_nok (error, FALSE);
2433 MonoGenericParamFull *param = (MonoGenericParamFull *) param_type->data.generic_param;
2434 generic_container->type_params [i] = *param;
2435 /*Make sure we are a diferent type instance */
2436 generic_container->type_params [i].param.owner = generic_container;
2437 generic_container->type_params [i].info.pklass = NULL;
2438 generic_container->type_params [i].info.flags = gparam->attrs;
2440 g_assert (generic_container->type_params [i].param.owner);
2443 generic_container->context.class_inst = mono_get_shared_generic_inst (generic_container);
2444 return TRUE;
2447 static MonoMarshalSpec*
2448 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
2449 MonoReflectionMarshal *minfo, MonoError *error)
2451 MonoMarshalSpec *res;
2453 mono_error_init (error);
2455 res = image_g_new0 (image, MonoMarshalSpec, 1);
2456 res->native = (MonoMarshalNative)minfo->type;
2458 switch (minfo->type) {
2459 case MONO_NATIVE_LPARRAY:
2460 res->data.array_data.elem_type = (MonoMarshalNative)minfo->eltype;
2461 if (minfo->has_size) {
2462 res->data.array_data.param_num = minfo->param_num;
2463 res->data.array_data.num_elem = minfo->count;
2464 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
2466 else {
2467 res->data.array_data.param_num = -1;
2468 res->data.array_data.num_elem = -1;
2469 res->data.array_data.elem_mult = -1;
2471 break;
2473 case MONO_NATIVE_BYVALTSTR:
2474 case MONO_NATIVE_BYVALARRAY:
2475 res->data.array_data.num_elem = minfo->count;
2476 break;
2478 case MONO_NATIVE_CUSTOM:
2479 if (minfo->marshaltyperef) {
2480 MonoType *marshaltyperef = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, error);
2481 if (!is_ok (error)) {
2482 image_g_free (image, res);
2483 return NULL;
2485 res->data.custom_data.custom_name =
2486 type_get_fully_qualified_name (marshaltyperef);
2488 if (minfo->mcookie) {
2489 res->data.custom_data.cookie = mono_string_to_utf8_checked (minfo->mcookie, error);
2490 if (!is_ok (error)) {
2491 image_g_free (image, res);
2492 return NULL;
2495 break;
2497 default:
2498 break;
2501 return res;
2503 #endif /* !DISABLE_REFLECTION_EMIT */
2505 MonoReflectionMarshalAsAttribute*
2506 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
2507 MonoMarshalSpec *spec, MonoError *error)
2509 MonoReflectionType *rt;
2510 MonoReflectionMarshalAsAttribute *minfo;
2511 MonoType *mtype;
2513 mono_error_init (error);
2515 minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new_checked (domain, mono_class_get_marshal_as_attribute_class (), error);
2516 if (!minfo)
2517 return NULL;
2518 minfo->utype = spec->native;
2520 switch (minfo->utype) {
2521 case MONO_NATIVE_LPARRAY:
2522 minfo->array_subtype = spec->data.array_data.elem_type;
2523 minfo->size_const = spec->data.array_data.num_elem;
2524 if (spec->data.array_data.param_num != -1)
2525 minfo->size_param_index = spec->data.array_data.param_num;
2526 break;
2528 case MONO_NATIVE_BYVALTSTR:
2529 case MONO_NATIVE_BYVALARRAY:
2530 minfo->size_const = spec->data.array_data.num_elem;
2531 break;
2533 case MONO_NATIVE_CUSTOM:
2534 if (spec->data.custom_data.custom_name) {
2535 mtype = mono_reflection_type_from_name_checked (spec->data.custom_data.custom_name, klass->image, error);
2536 return_val_if_nok (error, NULL);
2538 if (mtype) {
2539 rt = mono_type_get_object_checked (domain, mtype, error);
2540 if (!rt)
2541 return NULL;
2543 MONO_OBJECT_SETREF (minfo, marshal_type_ref, rt);
2546 MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
2548 if (spec->data.custom_data.cookie)
2549 MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
2550 break;
2552 default:
2553 break;
2556 return minfo;
2559 #ifndef DISABLE_REFLECTION_EMIT
2560 static MonoMethod*
2561 reflection_methodbuilder_to_mono_method (MonoClass *klass,
2562 ReflectionMethodBuilder *rmb,
2563 MonoMethodSignature *sig,
2564 MonoError *error)
2566 MonoMethod *m;
2567 MonoMethodWrapper *wrapperm;
2568 MonoMarshalSpec **specs;
2569 MonoReflectionMethodAux *method_aux;
2570 MonoImage *image;
2571 gboolean dynamic;
2572 int i;
2574 mono_error_init (error);
2576 * Methods created using a MethodBuilder should have their memory allocated
2577 * inside the image mempool, while dynamic methods should have their memory
2578 * malloc'd.
2580 dynamic = rmb->refs != NULL;
2581 image = dynamic ? NULL : klass->image;
2583 if (!dynamic)
2584 g_assert (!mono_class_is_ginst (klass));
2586 mono_loader_lock ();
2588 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
2589 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
2590 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
2591 else
2592 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
2594 wrapperm = (MonoMethodWrapper*)m;
2596 m->dynamic = dynamic;
2597 m->slot = -1;
2598 m->flags = rmb->attrs;
2599 m->iflags = rmb->iattrs;
2600 m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
2601 m->klass = klass;
2602 m->signature = sig;
2603 m->sre_method = TRUE;
2604 m->skip_visibility = rmb->skip_visibility;
2605 if (rmb->table_idx)
2606 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
2608 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
2609 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
2610 m->string_ctor = 1;
2612 m->signature->pinvoke = 1;
2613 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
2614 m->signature->pinvoke = 1;
2616 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
2618 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, error) : image_strdup (image, m->name);
2619 mono_error_assert_ok (error);
2620 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, error);
2621 mono_error_assert_ok (error);
2623 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
2625 if (image_is_dynamic (klass->image))
2626 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
2628 mono_loader_unlock ();
2630 return m;
2631 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
2632 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
2633 MonoMethodHeader *header;
2634 guint32 code_size;
2635 gint32 max_stack, i;
2636 gint32 num_locals = 0;
2637 gint32 num_clauses = 0;
2638 guint8 *code;
2640 if (rmb->ilgen) {
2641 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
2642 code_size = rmb->ilgen->code_len;
2643 max_stack = rmb->ilgen->max_stack;
2644 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
2645 if (rmb->ilgen->ex_handlers)
2646 num_clauses = mono_reflection_method_count_clauses (rmb->ilgen);
2647 } else {
2648 if (rmb->code) {
2649 code = mono_array_addr (rmb->code, guint8, 0);
2650 code_size = mono_array_length (rmb->code);
2651 /* we probably need to run a verifier on the code... */
2652 max_stack = 8;
2654 else {
2655 code = NULL;
2656 code_size = 0;
2657 max_stack = 8;
2661 header = (MonoMethodHeader *)mono_image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
2662 header->code_size = code_size;
2663 header->code = (const unsigned char *)image_g_malloc (image, code_size);
2664 memcpy ((char*)header->code, code, code_size);
2665 header->max_stack = max_stack;
2666 header->init_locals = rmb->init_locals;
2667 header->num_locals = num_locals;
2669 for (i = 0; i < num_locals; ++i) {
2670 MonoReflectionLocalBuilder *lb =
2671 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
2673 header->locals [i] = image_g_new0 (image, MonoType, 1);
2674 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)lb->type, error);
2675 mono_error_assert_ok (error);
2676 memcpy (header->locals [i], type, MONO_SIZEOF_TYPE);
2679 header->num_clauses = num_clauses;
2680 if (num_clauses) {
2681 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
2682 rmb->ilgen, num_clauses, error);
2683 mono_error_assert_ok (error);
2686 wrapperm->header = header;
2689 if (rmb->generic_params) {
2690 int count = mono_array_length (rmb->generic_params);
2691 MonoGenericContainer *container;
2693 container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
2694 container->is_method = TRUE;
2695 container->is_anonymous = FALSE;
2696 container->type_argc = count;
2697 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
2698 container->owner.method = m;
2700 m->is_generic = TRUE;
2701 mono_method_set_generic_container (m, container);
2703 for (i = 0; i < count; i++) {
2704 MonoReflectionGenericParam *gp =
2705 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
2706 MonoType *gp_type = mono_reflection_type_get_handle ((MonoReflectionType*)gp, error);
2707 mono_error_assert_ok (error);
2708 MonoGenericParamFull *param = (MonoGenericParamFull *) gp_type->data.generic_param;
2709 container->type_params [i] = *param;
2710 container->type_params [i].param.owner = container;
2712 gp->type.type->data.generic_param = (MonoGenericParam*)&container->type_params [i];
2714 MonoClass *gklass = mono_class_from_mono_type (gp_type);
2715 gklass->wastypebuilder = TRUE;
2719 * The method signature might have pointers to generic parameters that belong to other methods.
2720 * This is a valid SRE case, but the resulting method signature must be encoded using the proper
2721 * generic parameters.
2723 for (i = 0; i < m->signature->param_count; ++i) {
2724 MonoType *t = m->signature->params [i];
2725 if (t->type == MONO_TYPE_MVAR) {
2726 MonoGenericParam *gparam = t->data.generic_param;
2727 if (gparam->num < count) {
2728 m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
2729 m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
2735 if (mono_class_is_gtd (klass)) {
2736 container->parent = mono_class_get_generic_container (klass);
2737 container->context.class_inst = mono_class_get_generic_container (klass)->context.class_inst;
2739 container->context.method_inst = mono_get_shared_generic_inst (container);
2742 if (rmb->refs) {
2743 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
2744 int i;
2745 void **data;
2747 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
2749 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
2750 data [0] = GUINT_TO_POINTER (rmb->nrefs);
2751 for (i = 0; i < rmb->nrefs; ++i)
2752 data [i + 1] = rmb->refs [i];
2755 method_aux = NULL;
2757 /* Parameter info */
2758 if (rmb->pinfo) {
2759 if (!method_aux)
2760 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
2761 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
2762 for (i = 0; i <= m->signature->param_count; ++i) {
2763 MonoReflectionParamBuilder *pb;
2764 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
2765 if ((i > 0) && (pb->attrs)) {
2766 /* Make a copy since it might point to a shared type structure */
2767 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
2768 m->signature->params [i - 1]->attrs = pb->attrs;
2771 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
2772 MonoDynamicImage *assembly;
2773 guint32 idx, len;
2774 MonoTypeEnum def_type;
2775 char *p;
2776 const char *p2;
2778 if (!method_aux->param_defaults) {
2779 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
2780 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
2782 assembly = (MonoDynamicImage*)klass->image;
2783 idx = mono_dynimage_encode_constant (assembly, pb->def_value, &def_type);
2784 /* Copy the data from the blob since it might get realloc-ed */
2785 p = assembly->blob.data + idx;
2786 len = mono_metadata_decode_blob_size (p, &p2);
2787 len += p2 - p;
2788 method_aux->param_defaults [i] = (uint8_t *)image_g_malloc (image, len);
2789 method_aux->param_default_types [i] = def_type;
2790 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
2793 if (pb->name) {
2794 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, error);
2795 mono_error_assert_ok (error);
2797 if (pb->cattrs) {
2798 if (!method_aux->param_cattr)
2799 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
2800 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
2806 /* Parameter marshalling */
2807 specs = NULL;
2808 if (rmb->pinfo)
2809 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
2810 MonoReflectionParamBuilder *pb;
2811 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
2812 if (pb->marshal_info) {
2813 if (specs == NULL)
2814 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
2815 specs [pb->position] =
2816 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info, error);
2817 if (!is_ok (error)) {
2818 mono_loader_unlock ();
2819 image_g_free (image, specs);
2820 /* FIXME: if image is NULL, this leaks all the other stuff we alloc'd in this function */
2821 return NULL;
2826 if (specs != NULL) {
2827 if (!method_aux)
2828 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
2829 method_aux->param_marshall = specs;
2832 if (image_is_dynamic (klass->image) && method_aux)
2833 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
2835 mono_loader_unlock ();
2837 return m;
2840 static MonoMethod*
2841 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb, MonoError *error)
2843 ReflectionMethodBuilder rmb;
2844 MonoMethodSignature *sig;
2846 mono_loader_lock ();
2848 if (!mono_reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
2849 return NULL;
2851 g_assert (klass->image != NULL);
2852 sig = ctor_builder_to_signature (klass->image, mb, error);
2853 mono_loader_unlock ();
2854 return_val_if_nok (error, NULL);
2856 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
2857 return_val_if_nok (error, NULL);
2858 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
2860 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
2861 /* ilgen is no longer needed */
2862 mb->ilgen = NULL;
2865 return mb->mhandle;
2868 static MonoMethod*
2869 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb, MonoError *error)
2871 ReflectionMethodBuilder rmb;
2872 MonoMethodSignature *sig;
2874 mono_error_init (error);
2876 mono_loader_lock ();
2878 if (!mono_reflection_methodbuilder_from_method_builder (&rmb, mb, error))
2879 return NULL;
2881 g_assert (klass->image != NULL);
2882 sig = method_builder_to_signature (klass->image, mb, error);
2883 mono_loader_unlock ();
2884 return_val_if_nok (error, NULL);
2886 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
2887 return_val_if_nok (error, NULL);
2888 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
2890 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save)
2891 /* ilgen is no longer needed */
2892 mb->ilgen = NULL;
2893 return mb->mhandle;
2895 #endif
2897 #ifndef DISABLE_REFLECTION_EMIT
2900 * fix_partial_generic_class:
2901 * @klass: a generic instantiation MonoClass
2902 * @error: set on error
2904 * Assumes that the generic container of @klass has its vtable
2905 * initialized, and updates the parent class, interfaces, methods and
2906 * fields of @klass by inflating the types using the generic context.
2908 * On success returns TRUE, on failure returns FALSE and sets @error.
2911 static gboolean
2912 fix_partial_generic_class (MonoClass *klass, MonoError *error)
2914 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2915 int i;
2917 mono_error_init (error);
2919 if (klass->wastypebuilder)
2920 return TRUE;
2922 if (klass->parent != gklass->parent) {
2923 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &mono_class_get_generic_class (klass)->context, error);
2924 if (mono_error_ok (error)) {
2925 MonoClass *parent = mono_class_from_mono_type (parent_type);
2926 mono_metadata_free_type (parent_type);
2927 if (parent != klass->parent) {
2928 /*fool mono_class_setup_parent*/
2929 klass->supertypes = NULL;
2930 mono_class_setup_parent (klass, parent);
2932 } else {
2933 if (gklass->wastypebuilder)
2934 klass->wastypebuilder = TRUE;
2935 return FALSE;
2939 if (!mono_class_get_generic_class (klass)->need_sync)
2940 return TRUE;
2942 int mcount = mono_class_get_method_count (klass);
2943 int gmcount = mono_class_get_method_count (gklass);
2944 if (mcount != gmcount) {
2945 mono_class_set_method_count (klass, gmcount);
2946 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (gmcount + 1));
2948 for (i = 0; i < gmcount; i++) {
2949 klass->methods [i] = mono_class_inflate_generic_method_full_checked (
2950 gklass->methods [i], klass, mono_class_get_context (klass), error);
2951 mono_error_assert_ok (error);
2955 if (klass->interface_count && klass->interface_count != gklass->interface_count) {
2956 klass->interface_count = gklass->interface_count;
2957 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
2958 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
2960 for (i = 0; i < gklass->interface_count; ++i) {
2961 MonoType *iface_type = mono_class_inflate_generic_type_checked (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass), error);
2962 return_val_if_nok (error, FALSE);
2964 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
2965 mono_metadata_free_type (iface_type);
2967 if (!ensure_runtime_vtable (klass->interfaces [i], error))
2968 return FALSE;
2970 klass->interfaces_inited = 1;
2973 int fcount = mono_class_get_field_count (klass);
2974 int gfcount = mono_class_get_field_count (gklass);
2975 if (fcount != gfcount) {
2976 mono_class_set_field_count (klass, gfcount);
2977 klass->fields = image_g_new0 (klass->image, MonoClassField, gfcount);
2979 for (i = 0; i < gfcount; i++) {
2980 klass->fields [i] = gklass->fields [i];
2981 klass->fields [i].parent = klass;
2982 klass->fields [i].type = mono_class_inflate_generic_type_checked (gklass->fields [i].type, mono_class_get_context (klass), error);
2983 return_val_if_nok (error, FALSE);
2987 /*We can only finish with this klass once it's parent has as well*/
2988 if (gklass->wastypebuilder)
2989 klass->wastypebuilder = TRUE;
2990 return TRUE;
2994 * ensure_generic_class_runtime_vtable:
2995 * @klass a generic class
2996 * @error set on error
2998 * Ensures that the generic container of @klass has a vtable and
2999 * returns TRUE on success. On error returns FALSE and sets @error.
3001 static gboolean
3002 ensure_generic_class_runtime_vtable (MonoClass *klass, MonoError *error)
3004 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
3006 mono_error_init (error);
3008 if (!ensure_runtime_vtable (gklass, error))
3009 return FALSE;
3011 return fix_partial_generic_class (klass, error);
3015 * ensure_runtime_vtable:
3016 * @klass the class
3017 * @error set on error
3019 * Ensures that @klass has a vtable and returns TRUE on success. On
3020 * error returns FALSE and sets @error.
3022 static gboolean
3023 ensure_runtime_vtable (MonoClass *klass, MonoError *error)
3025 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
3026 int i, num, j;
3028 mono_error_init (error);
3030 if (!image_is_dynamic (klass->image) || (!tb && !mono_class_is_ginst (klass)) || klass->wastypebuilder)
3031 return TRUE;
3032 if (klass->parent)
3033 if (!ensure_runtime_vtable (klass->parent, error))
3034 return FALSE;
3036 if (tb) {
3037 num = tb->ctors? mono_array_length (tb->ctors): 0;
3038 num += tb->num_methods;
3039 mono_class_set_method_count (klass, num);
3040 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
3041 num = tb->ctors? mono_array_length (tb->ctors): 0;
3042 for (i = 0; i < num; ++i) {
3043 MonoMethod *ctor = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), error);
3044 if (!ctor)
3045 return FALSE;
3046 klass->methods [i] = ctor;
3048 num = tb->num_methods;
3049 j = i;
3050 for (i = 0; i < num; ++i) {
3051 MonoMethod *meth = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), error);
3052 if (!meth)
3053 return FALSE;
3054 klass->methods [j++] = meth;
3057 if (tb->interfaces) {
3058 klass->interface_count = mono_array_length (tb->interfaces);
3059 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
3060 for (i = 0; i < klass->interface_count; ++i) {
3061 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i, error);
3062 return_val_if_nok (error, FALSE);
3063 klass->interfaces [i] = mono_class_from_mono_type (iface);
3064 if (!ensure_runtime_vtable (klass->interfaces [i], error))
3065 return FALSE;
3067 klass->interfaces_inited = 1;
3069 } else if (mono_class_is_ginst (klass)){
3070 if (!ensure_generic_class_runtime_vtable (klass, error)) {
3071 mono_class_set_type_load_failure (klass, "Could not initialize vtable for generic class due to: %s", mono_error_get_message (error));
3072 return FALSE;
3076 if (mono_class_is_interface (klass) && !mono_class_is_ginst (klass)) {
3077 int slot_num = 0;
3078 int mcount = mono_class_get_method_count (klass);
3079 for (i = 0; i < mcount; ++i) {
3080 MonoMethod *im = klass->methods [i];
3081 if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
3082 im->slot = slot_num++;
3085 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
3086 mono_class_setup_interface_offsets (klass);
3087 mono_class_setup_interface_id (klass);
3091 * The generic vtable is needed even if image->run is not set since some
3092 * runtime code like ves_icall_Type_GetMethodsByName depends on
3093 * method->slot being defined.
3097 * tb->methods could not be freed since it is used for determining
3098 * overrides during dynamic vtable construction.
3101 return TRUE;
3104 static MonoMethod*
3105 mono_reflection_method_get_handle (MonoObject *method, MonoError *error)
3107 mono_error_init (error);
3108 MonoClass *klass = mono_object_class (method);
3109 if (is_sr_mono_method (klass)) {
3110 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
3111 return sr_method->method;
3113 if (is_sre_method_builder (klass)) {
3114 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
3115 return mb->mhandle;
3117 if (mono_is_sre_method_on_tb_inst (klass)) {
3118 MonoClass *handle_class;
3120 MonoMethod *result = mono_reflection_resolve_object (NULL, method, &handle_class, NULL, error);
3121 return_val_if_nok (error, NULL);
3123 return result;
3126 g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
3127 return NULL;
3130 void
3131 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides, MonoError *error)
3133 MonoReflectionTypeBuilder *tb;
3134 int i, j, onum;
3135 MonoReflectionMethod *m;
3137 mono_error_init (error);
3138 *overrides = NULL;
3139 *num_overrides = 0;
3141 g_assert (image_is_dynamic (klass->image));
3143 if (!mono_class_get_ref_info (klass))
3144 return;
3146 g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
3148 tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
3150 onum = 0;
3151 if (tb->methods) {
3152 for (i = 0; i < tb->num_methods; ++i) {
3153 MonoReflectionMethodBuilder *mb =
3154 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3155 if (mb->override_methods)
3156 onum += mono_array_length (mb->override_methods);
3160 if (onum) {
3161 *overrides = g_new0 (MonoMethod*, onum * 2);
3163 onum = 0;
3164 for (i = 0; i < tb->num_methods; ++i) {
3165 MonoReflectionMethodBuilder *mb =
3166 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3167 if (mb->override_methods) {
3168 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
3169 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
3171 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m, error);
3172 return_if_nok (error);
3173 (*overrides) [onum * 2 + 1] = mb->mhandle;
3175 g_assert (mb->mhandle);
3177 onum ++;
3183 *num_overrides = onum;
3186 /* This initializes the same data as mono_class_setup_fields () */
3187 static void
3188 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
3190 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
3191 MonoReflectionFieldBuilder *fb;
3192 MonoClassField *field;
3193 MonoClassExt *ext;
3194 MonoImage *image = klass->image;
3195 const char *p, *p2;
3196 int i, instance_size, packing_size = 0;
3197 guint32 len, idx;
3199 if (klass->parent) {
3200 if (!klass->parent->size_inited)
3201 mono_class_init (klass->parent);
3202 instance_size = klass->parent->instance_size;
3203 } else {
3204 instance_size = sizeof (MonoObject);
3207 int fcount = tb->num_fields;
3208 mono_class_set_field_count (klass, fcount);
3210 mono_error_init (error);
3212 if (tb->class_size) {
3213 packing_size = tb->packing_size;
3214 instance_size += tb->class_size;
3217 klass->fields = image_g_new0 (image, MonoClassField, fcount);
3218 mono_class_alloc_ext (klass);
3219 ext = mono_class_get_ext (klass);
3220 ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, fcount);
3222 This is, guess what, a hack.
3223 The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
3224 On the static path no field class is resolved, only types are built. This is the right thing to do
3225 but we suck.
3226 Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
3228 klass->size_inited = 1;
3230 for (i = 0; i < fcount; ++i) {
3231 MonoArray *rva_data;
3232 fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
3233 field = &klass->fields [i];
3234 field->parent = klass;
3235 field->name = mono_string_to_utf8_image (image, fb->name, error);
3236 if (!mono_error_ok (error))
3237 return;
3238 if (fb->attrs) {
3239 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
3240 return_if_nok (error);
3241 field->type = mono_metadata_type_dup (klass->image, type);
3242 field->type->attrs = fb->attrs;
3243 } else {
3244 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
3245 return_if_nok (error);
3248 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
3249 char *base = mono_array_addr (rva_data, char, 0);
3250 size_t size = mono_array_length (rva_data);
3251 char *data = (char *)mono_image_alloc (klass->image, size);
3252 memcpy (data, base, size);
3253 ext->field_def_values [i].data = data;
3255 if (fb->offset != -1)
3256 field->offset = fb->offset;
3257 fb->handle = field;
3258 mono_save_custom_attrs (klass->image, field, fb->cattrs);
3260 if (fb->def_value) {
3261 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
3262 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
3263 idx = mono_dynimage_encode_constant (assembly, fb->def_value, &ext->field_def_values [i].def_type);
3264 /* Copy the data from the blob since it might get realloc-ed */
3265 p = assembly->blob.data + idx;
3266 len = mono_metadata_decode_blob_size (p, &p2);
3267 len += p2 - p;
3268 ext->field_def_values [i].data = (const char *)mono_image_alloc (image, len);
3269 memcpy ((gpointer)ext->field_def_values [i].data, p, len);
3273 mono_class_layout_fields (klass, instance_size, packing_size, TRUE);
3276 static void
3277 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
3279 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
3280 MonoReflectionPropertyBuilder *pb;
3281 MonoImage *image = klass->image;
3282 MonoProperty *properties;
3283 MonoClassExt *ext;
3284 int i;
3286 mono_error_init (error);
3288 ext = mono_class_get_ext (klass);
3289 if (!ext)
3290 mono_class_set_ext (klass, ext = image_g_new0 (image, MonoClassExt, 1));
3292 ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
3293 ext->property.first = 0;
3295 properties = image_g_new0 (image, MonoProperty, ext->property.count);
3296 ext->properties = properties;
3297 for (i = 0; i < ext->property.count; ++i) {
3298 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3299 properties [i].parent = klass;
3300 properties [i].attrs = pb->attrs;
3301 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
3302 if (!mono_error_ok (error))
3303 return;
3304 if (pb->get_method)
3305 properties [i].get = pb->get_method->mhandle;
3306 if (pb->set_method)
3307 properties [i].set = pb->set_method->mhandle;
3309 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
3310 if (pb->def_value) {
3311 guint32 len, idx;
3312 const char *p, *p2;
3313 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
3314 if (!ext->prop_def_values)
3315 ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, ext->property.count);
3316 properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
3317 idx = mono_dynimage_encode_constant (assembly, pb->def_value, &ext->prop_def_values [i].def_type);
3318 /* Copy the data from the blob since it might get realloc-ed */
3319 p = assembly->blob.data + idx;
3320 len = mono_metadata_decode_blob_size (p, &p2);
3321 len += p2 - p;
3322 ext->prop_def_values [i].data = (const char *)mono_image_alloc (image, len);
3323 memcpy ((gpointer)ext->prop_def_values [i].data, p, len);
3328 static void
3329 typebuilder_setup_events (MonoClass *klass, MonoError *error)
3331 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
3332 MonoReflectionEventBuilder *eb;
3333 MonoImage *image = klass->image;
3334 MonoEvent *events;
3335 MonoClassExt *ext;
3336 int i;
3338 mono_error_init (error);
3340 ext = mono_class_get_ext (klass);
3341 if (!ext)
3342 mono_class_set_ext (klass, ext = image_g_new0 (image, MonoClassExt, 1));
3344 ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
3345 ext->event.first = 0;
3347 events = image_g_new0 (image, MonoEvent, ext->event.count);
3348 ext->events = events;
3349 for (i = 0; i < ext->event.count; ++i) {
3350 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3351 events [i].parent = klass;
3352 events [i].attrs = eb->attrs;
3353 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
3354 if (!mono_error_ok (error))
3355 return;
3356 if (eb->add_method)
3357 events [i].add = eb->add_method->mhandle;
3358 if (eb->remove_method)
3359 events [i].remove = eb->remove_method->mhandle;
3360 if (eb->raise_method)
3361 events [i].raise = eb->raise_method->mhandle;
3363 #ifndef MONO_SMALL_CONFIG
3364 if (eb->other_methods) {
3365 int j;
3366 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
3367 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
3368 MonoReflectionMethodBuilder *mb =
3369 mono_array_get (eb->other_methods,
3370 MonoReflectionMethodBuilder*, j);
3371 events [i].other [j] = mb->mhandle;
3374 #endif
3375 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
3379 struct remove_instantiations_user_data
3381 MonoClass *klass;
3382 MonoError *error;
3385 static gboolean
3386 remove_instantiations_of_and_ensure_contents (gpointer key,
3387 gpointer value,
3388 gpointer user_data)
3390 struct remove_instantiations_user_data *data = (struct remove_instantiations_user_data*)user_data;
3391 MonoType *type = (MonoType*)key;
3392 MonoClass *klass = data->klass;
3393 gboolean already_failed = !is_ok (data->error);
3394 MonoError lerror;
3395 MonoError *error = already_failed ? &lerror : data->error;
3397 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
3398 MonoClass *inst_klass = mono_class_from_mono_type (type);
3399 //Ensure it's safe to use it.
3400 if (!fix_partial_generic_class (inst_klass, error)) {
3401 mono_class_set_type_load_failure (inst_klass, "Could not initialized generic type instance due to: %s", mono_error_get_message (error));
3402 // Marked the class with failure, but since some other instantiation already failed,
3403 // just report that one, and swallow the error from this one.
3404 if (already_failed)
3405 mono_error_cleanup (error);
3407 return TRUE;
3408 } else
3409 return FALSE;
3412 MonoReflectionType*
3413 ves_icall_TypeBuilder_create_runtime_class (MonoReflectionTypeBuilder *tb)
3415 MonoError error;
3416 MonoClass *klass;
3417 MonoDomain* domain;
3418 MonoReflectionType* res;
3419 int i;
3421 mono_error_init (&error);
3423 reflection_create_generic_class (tb, &error);
3424 mono_error_assert_ok (&error);
3426 domain = mono_object_domain (tb);
3427 klass = mono_class_from_mono_type (tb->type.type);
3429 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
3432 * we need to lock the domain because the lock will be taken inside
3433 * So, we need to keep the locking order correct.
3435 mono_loader_lock ();
3436 mono_domain_lock (domain);
3437 if (klass->wastypebuilder) {
3438 mono_domain_unlock (domain);
3439 mono_loader_unlock ();
3441 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
3442 mono_error_set_pending_exception (&error);
3444 return res;
3447 * Fields to set in klass:
3448 * the various flags: delegate/unicode/contextbound etc.
3450 mono_class_set_flags (klass, tb->attrs);
3451 klass->has_cctor = 1;
3453 mono_class_setup_parent (klass, klass->parent);
3454 /* fool mono_class_setup_supertypes */
3455 klass->supertypes = NULL;
3456 mono_class_setup_supertypes (klass);
3457 mono_class_setup_mono_type (klass);
3459 /* enums are done right away */
3460 if (!klass->enumtype)
3461 if (!ensure_runtime_vtable (klass, &error))
3462 goto failure;
3464 if (tb->subtypes) {
3465 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3466 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3467 mono_class_alloc_ext (klass);
3469 if (!subtb->type.type) {
3470 reflection_setup_internal_class (subtb, &error);
3471 mono_error_assert_ok (&error);
3474 MonoType *subtype = mono_reflection_type_get_handle ((MonoReflectionType*)subtb, &error);
3475 if (!is_ok (&error)) goto failure;
3476 mono_class_get_ext (klass)->nested_classes = g_list_prepend_image (klass->image, mono_class_get_ext (klass)->nested_classes, mono_class_from_mono_type (subtype));
3480 klass->nested_classes_inited = TRUE;
3482 typebuilder_setup_fields (klass, &error);
3483 if (!mono_error_ok (&error))
3484 goto failure;
3485 typebuilder_setup_properties (klass, &error);
3486 if (!mono_error_ok (&error))
3487 goto failure;
3489 typebuilder_setup_events (klass, &error);
3490 if (!mono_error_ok (&error))
3491 goto failure;
3493 klass->wastypebuilder = TRUE;
3495 if (tb->generic_params) {
3496 for (i = 0; i < mono_array_length (tb->generic_params); i++) {
3497 MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)mono_array_get (tb->generic_params, gpointer, i);
3498 MonoType *param_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, &error);
3499 MonoClass *gklass = mono_class_from_mono_type (param_type);
3501 gklass->wastypebuilder = TRUE;
3506 * If we are a generic TypeBuilder, there might be instantiations in the type cache
3507 * which have type System.Reflection.MonoGenericClass, but after the type is created,
3508 * we want to return normal System.MonoType objects, so clear these out from the cache.
3510 * Together with this we must ensure the contents of all instances to match the created type.
3512 if (domain->type_hash && mono_class_is_gtd (klass)) {
3513 struct remove_instantiations_user_data data;
3514 data.klass = klass;
3515 data.error = &error;
3516 mono_error_assert_ok (&error);
3517 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, &data);
3518 if (!is_ok (&error))
3519 goto failure;
3522 mono_domain_unlock (domain);
3523 mono_loader_unlock ();
3525 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
3526 mono_class_set_type_load_failure (klass, "Not a valid enumeration");
3527 mono_error_set_type_load_class (&error, klass, "Not a valid enumeration");
3528 goto failure_unlocked;
3531 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
3532 if (!is_ok (&error))
3533 goto failure_unlocked;
3535 g_assert (res != (MonoReflectionType*)tb);
3537 return res;
3539 failure:
3540 mono_class_set_type_load_failure (klass, "TypeBuilder could not create runtime class due to: %s", mono_error_get_message (&error));
3541 klass->wastypebuilder = TRUE;
3542 mono_domain_unlock (domain);
3543 mono_loader_unlock ();
3544 failure_unlocked:
3545 mono_error_set_pending_exception (&error);
3546 return NULL;
3549 typedef struct {
3550 MonoMethod *handle;
3551 MonoDomain *domain;
3552 } DynamicMethodReleaseData;
3555 * The runtime automatically clean up those after finalization.
3557 static MonoReferenceQueue *dynamic_method_queue;
3559 static void
3560 free_dynamic_method (void *dynamic_method)
3562 DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
3563 MonoDomain *domain = data->domain;
3564 MonoMethod *method = data->handle;
3565 guint32 dis_link;
3567 mono_domain_lock (domain);
3568 dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
3569 g_hash_table_remove (domain->method_to_dyn_method, method);
3570 mono_domain_unlock (domain);
3571 g_assert (dis_link);
3572 mono_gchandle_free (dis_link);
3574 mono_runtime_free_method (domain, method);
3575 g_free (data);
3578 static gboolean
3579 reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb, MonoError *error)
3581 MonoReferenceQueue *queue;
3582 MonoMethod *handle;
3583 DynamicMethodReleaseData *release_data;
3584 ReflectionMethodBuilder rmb;
3585 MonoMethodSignature *sig;
3586 MonoClass *klass;
3587 MonoDomain *domain;
3588 GSList *l;
3589 int i;
3591 mono_error_init (error);
3593 if (mono_runtime_is_shutting_down ()) {
3594 mono_error_set_generic_error (error, "System", "InvalidOperationException", "");
3595 return FALSE;
3598 if (!(queue = dynamic_method_queue)) {
3599 mono_loader_lock ();
3600 if (!(queue = dynamic_method_queue))
3601 queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
3602 mono_loader_unlock ();
3605 sig = dynamic_method_to_signature (mb, error);
3606 return_val_if_nok (error, FALSE);
3608 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
3611 * Resolve references.
3614 * Every second entry in the refs array is reserved for storing handle_class,
3615 * which is needed by the ldtoken implementation in the JIT.
3617 rmb.nrefs = mb->nrefs;
3618 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
3619 for (i = 0; i < mb->nrefs; i += 2) {
3620 MonoClass *handle_class;
3621 gpointer ref;
3622 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
3624 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
3625 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
3627 * The referenced DynamicMethod should already be created by the managed
3628 * code, except in the case of circular references. In that case, we store
3629 * method in the refs array, and fix it up later when the referenced
3630 * DynamicMethod is created.
3632 if (method->mhandle) {
3633 ref = method->mhandle;
3634 } else {
3635 /* FIXME: GC object stored in unmanaged memory */
3636 ref = method;
3638 /* FIXME: GC object stored in unmanaged memory */
3639 method->referenced_by = g_slist_append (method->referenced_by, mb);
3641 handle_class = mono_defaults.methodhandle_class;
3642 } else {
3643 MonoException *ex = NULL;
3644 ref = mono_reflection_resolve_object (mb->module->image, obj, &handle_class, NULL, error);
3645 if (!is_ok (error)) {
3646 g_free (rmb.refs);
3647 return FALSE;
3649 if (!ref)
3650 ex = mono_get_exception_type_load (NULL, NULL);
3651 else if (mono_security_core_clr_enabled ())
3652 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
3654 if (ex) {
3655 g_free (rmb.refs);
3656 mono_error_set_exception_instance (error, ex);
3657 return FALSE;
3661 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
3662 rmb.refs [i + 1] = handle_class;
3665 if (mb->owner) {
3666 MonoType *owner_type = mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner, error);
3667 if (!is_ok (error)) {
3668 g_free (rmb.refs);
3669 return FALSE;
3671 klass = mono_class_from_mono_type (owner_type);
3672 } else {
3673 klass = mono_defaults.object_class;
3676 mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
3677 g_free (rmb.refs);
3678 return_val_if_nok (error, FALSE);
3680 release_data = g_new (DynamicMethodReleaseData, 1);
3681 release_data->handle = handle;
3682 release_data->domain = mono_object_get_domain ((MonoObject*)mb);
3683 if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
3684 g_free (release_data);
3686 /* Fix up refs entries pointing at us */
3687 for (l = mb->referenced_by; l; l = l->next) {
3688 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
3689 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
3690 gpointer *data;
3692 g_assert (method->mhandle);
3694 data = (gpointer*)wrapper->method_data;
3695 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
3696 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
3697 data [i + 1] = mb->mhandle;
3700 g_slist_free (mb->referenced_by);
3702 /* ilgen is no longer needed */
3703 mb->ilgen = NULL;
3705 domain = mono_domain_get ();
3706 mono_domain_lock (domain);
3707 if (!domain->method_to_dyn_method)
3708 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
3709 g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
3710 mono_domain_unlock (domain);
3712 return TRUE;
3715 void
3716 ves_icall_DynamicMethod_create_dynamic_method (MonoReflectionDynamicMethod *mb)
3718 MonoError error;
3719 (void) reflection_create_dynamic_method (mb, &error);
3720 mono_error_set_pending_exception (&error);
3723 #endif /* DISABLE_REFLECTION_EMIT */
3725 MonoMethodSignature *
3726 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
3728 MonoMethodSignature *sig;
3729 g_assert (image_is_dynamic (image));
3731 mono_error_init (error);
3733 sig = (MonoMethodSignature *)g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
3734 if (sig)
3735 return sig;
3737 return mono_method_signature_checked (method, error);
3740 #ifndef DISABLE_REFLECTION_EMIT
3743 * ensure_complete_type:
3745 * Ensure that KLASS is completed if it is a dynamic type, or references
3746 * dynamic types.
3748 static void
3749 ensure_complete_type (MonoClass *klass, MonoError *error)
3751 mono_error_init (error);
3753 if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
3754 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
3756 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
3757 return_if_nok (error);
3759 // Asserting here could break a lot of code
3760 //g_assert (klass->wastypebuilder);
3763 if (mono_class_is_ginst (klass)) {
3764 MonoGenericInst *inst = mono_class_get_generic_class (klass)->context.class_inst;
3765 int i;
3767 for (i = 0; i < inst->type_argc; ++i) {
3768 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]), error);
3769 return_if_nok (error);
3774 gpointer
3775 mono_reflection_resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
3777 MonoClass *oklass = obj->vtable->klass;
3778 gpointer result = NULL;
3780 mono_error_init (error);
3782 if (strcmp (oklass->name, "String") == 0) {
3783 result = mono_string_intern_checked ((MonoString*)obj, error);
3784 return_val_if_nok (error, NULL);
3785 *handle_class = mono_defaults.string_class;
3786 g_assert (result);
3787 } else if (strcmp (oklass->name, "RuntimeType") == 0) {
3788 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
3789 return_val_if_nok (error, NULL);
3790 MonoClass *mc = mono_class_from_mono_type (type);
3791 if (!mono_class_init (mc)) {
3792 mono_error_set_for_class_failure (error, mc);
3793 return NULL;
3796 if (context) {
3797 MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, error);
3798 return_val_if_nok (error, NULL);
3800 result = mono_class_from_mono_type (inflated);
3801 mono_metadata_free_type (inflated);
3802 } else {
3803 result = mono_class_from_mono_type (type);
3805 *handle_class = mono_defaults.typehandle_class;
3806 g_assert (result);
3807 } else if (strcmp (oklass->name, "MonoMethod") == 0 ||
3808 strcmp (oklass->name, "MonoCMethod") == 0) {
3809 result = ((MonoReflectionMethod*)obj)->method;
3810 if (context) {
3811 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
3812 mono_error_assert_ok (error);
3814 *handle_class = mono_defaults.methodhandle_class;
3815 g_assert (result);
3816 } else if (strcmp (oklass->name, "MonoField") == 0) {
3817 MonoClassField *field = ((MonoReflectionField*)obj)->field;
3819 ensure_complete_type (field->parent, error);
3820 return_val_if_nok (error, NULL);
3822 if (context) {
3823 MonoType *inflated = mono_class_inflate_generic_type_checked (&field->parent->byval_arg, context, error);
3824 return_val_if_nok (error, NULL);
3826 MonoClass *klass = mono_class_from_mono_type (inflated);
3827 MonoClassField *inflated_field;
3828 gpointer iter = NULL;
3829 mono_metadata_free_type (inflated);
3830 while ((inflated_field = mono_class_get_fields (klass, &iter))) {
3831 if (!strcmp (field->name, inflated_field->name))
3832 break;
3834 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
3835 result = inflated_field;
3836 } else {
3837 result = field;
3839 *handle_class = mono_defaults.fieldhandle_class;
3840 g_assert (result);
3841 } else if (strcmp (oklass->name, "TypeBuilder") == 0) {
3842 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
3843 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
3844 return_val_if_nok (error, NULL);
3845 MonoClass *klass;
3847 klass = type->data.klass;
3848 if (klass->wastypebuilder) {
3849 /* Already created */
3850 result = klass;
3852 else {
3853 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
3854 return_val_if_nok (error, NULL);
3855 result = type->data.klass;
3856 g_assert (result);
3858 *handle_class = mono_defaults.typehandle_class;
3859 } else if (strcmp (oklass->name, "SignatureHelper") == 0) {
3860 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
3861 MonoMethodSignature *sig;
3862 int nargs, i;
3864 if (helper->arguments)
3865 nargs = mono_array_length (helper->arguments);
3866 else
3867 nargs = 0;
3869 sig = mono_metadata_signature_alloc (image, nargs);
3870 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
3871 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
3873 if (helper->unmanaged_call_conv) { /* unmanaged */
3874 sig->call_convention = helper->unmanaged_call_conv - 1;
3875 sig->pinvoke = TRUE;
3876 } else if (helper->call_conv & 0x02) {
3877 sig->call_convention = MONO_CALL_VARARG;
3878 } else {
3879 sig->call_convention = MONO_CALL_DEFAULT;
3882 sig->param_count = nargs;
3883 /* TODO: Copy type ? */
3884 sig->ret = helper->return_type->type;
3885 for (i = 0; i < nargs; ++i) {
3886 sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i, error);
3887 if (!is_ok (error)) {
3888 image_g_free (image, sig);
3889 return NULL;
3893 result = sig;
3894 *handle_class = NULL;
3895 } else if (strcmp (oklass->name, "DynamicMethod") == 0) {
3896 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
3897 /* Already created by the managed code */
3898 g_assert (method->mhandle);
3899 result = method->mhandle;
3900 *handle_class = mono_defaults.methodhandle_class;
3901 } else if (strcmp (oklass->name, "MonoArrayMethod") == 0) {
3902 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
3903 MonoType *mtype;
3904 MonoClass *klass;
3905 MonoMethod *method;
3906 gpointer iter;
3907 char *name;
3909 mtype = mono_reflection_type_get_handle (m->parent, error);
3910 return_val_if_nok (error, NULL);
3911 klass = mono_class_from_mono_type (mtype);
3913 /* Find the method */
3915 name = mono_string_to_utf8_checked (m->name, error);
3916 return_val_if_nok (error, NULL);
3917 iter = NULL;
3918 while ((method = mono_class_get_methods (klass, &iter))) {
3919 if (!strcmp (method->name, name))
3920 break;
3922 g_free (name);
3924 // FIXME:
3925 g_assert (method);
3926 // FIXME: Check parameters/return value etc. match
3928 result = method;
3929 *handle_class = mono_defaults.methodhandle_class;
3930 } else if (is_sre_method_builder (oklass) ||
3931 mono_is_sre_ctor_builder (oklass) ||
3932 is_sre_field_builder (oklass) ||
3933 is_sre_gparam_builder (oklass) ||
3934 is_sre_generic_instance (oklass) ||
3935 is_sre_array (oklass) ||
3936 is_sre_byref (oklass) ||
3937 is_sre_pointer (oklass) ||
3938 !strcmp (oklass->name, "FieldOnTypeBuilderInst") ||
3939 !strcmp (oklass->name, "MethodOnTypeBuilderInst") ||
3940 !strcmp (oklass->name, "ConstructorOnTypeBuilderInst")) {
3941 static MonoMethod *resolve_method;
3942 if (!resolve_method) {
3943 MonoMethod *m = mono_class_get_method_from_name_flags (mono_class_get_module_builder_class (), "RuntimeResolve", 1, 0);
3944 g_assert (m);
3945 mono_memory_barrier ();
3946 resolve_method = m;
3948 void *args [16];
3949 args [0] = obj;
3950 obj = mono_runtime_invoke_checked (resolve_method, NULL, args, error);
3951 mono_error_assert_ok (error);
3952 g_assert (obj);
3953 return mono_reflection_resolve_object (image, obj, handle_class, context, error);
3954 } else {
3955 g_print ("%s\n", obj->vtable->klass->name);
3956 g_assert_not_reached ();
3958 return result;
3961 #else /* DISABLE_REFLECTION_EMIT */
3963 MonoArray*
3964 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
3966 g_assert_not_reached ();
3967 return NULL;
3970 void
3971 mono_reflection_dynimage_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
3973 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
3976 static void
3977 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
3979 g_assert_not_reached ();
3982 guint32
3983 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
3985 g_assert_not_reached ();
3986 return 0;
3989 guint32
3990 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
3992 g_assert_not_reached ();
3993 return 0;
3996 guint32
3997 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
3998 gboolean create_open_instance, gboolean register_token, MonoError *error)
4000 g_assert_not_reached ();
4001 return 0;
4004 void
4005 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides, MonoError *error)
4007 mono_error_init (error);
4008 *overrides = NULL;
4009 *num_overrides = 0;
4012 MonoReflectionType*
4013 ves_icall_TypeBuilder_create_runtime_class (MonoReflectionTypeBuilder *tb)
4015 g_assert_not_reached ();
4016 return NULL;
4019 void
4020 ves_icall_DynamicMethod_create_dynamic_method (MonoReflectionDynamicMethod *mb)
4024 MonoType*
4025 mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
4027 mono_error_init (error);
4028 if (!ref)
4029 return NULL;
4030 return ref->type;
4033 #endif /* DISABLE_REFLECTION_EMIT */
4035 void
4036 mono_sre_generic_param_table_entry_free (GenericParamTableEntry *entry)
4038 mono_gc_deregister_root ((char*) &entry->gparam);
4039 g_free (entry);
4042 gint32
4043 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
4045 MONO_CHECK_ARG_NULL (obj, 0);
4047 MonoError error;
4048 gint32 result = mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE, &error);
4049 mono_error_set_pending_exception (&error);
4050 return result;
4053 gint32
4054 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
4055 MonoReflectionMethod *method,
4056 MonoArray *opt_param_types)
4058 MONO_CHECK_ARG_NULL (method, 0);
4060 MonoError error;
4061 gint32 result = mono_image_create_method_token (
4062 mb->dynamic_image, (MonoObject *) method, opt_param_types, &error);
4063 mono_error_set_pending_exception (&error);
4064 return result;
4067 void
4068 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
4070 MonoError error;
4071 mono_image_create_pefile (mb, file, &error);
4072 mono_error_set_pending_exception (&error);
4075 void
4076 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
4078 MonoError error;
4079 mono_image_build_metadata (mb, &error);
4080 mono_error_set_pending_exception (&error);
4083 void
4084 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
4086 mono_image_register_token (mb->dynamic_image, token, obj);
4089 MonoObject*
4090 ves_icall_ModuleBuilder_GetRegisteredToken (MonoReflectionModuleBuilder *mb, guint32 token)
4092 MonoObject *obj;
4094 mono_loader_lock ();
4095 obj = (MonoObject *)mono_g_hash_table_lookup (mb->dynamic_image->tokens, GUINT_TO_POINTER (token));
4096 mono_loader_unlock ();
4098 return obj;
4101 #ifndef DISABLE_REFLECTION_EMIT
4102 MonoArray*
4103 ves_icall_CustomAttributeBuilder_GetBlob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
4105 MonoError error;
4106 MonoArray *result = mono_reflection_get_custom_attrs_blob_checked (assembly, ctor, ctorArgs, properties, propValues, fields, fieldValues, &error);
4107 mono_error_set_pending_exception (&error);
4108 return result;
4110 #endif
4112 void
4113 ves_icall_AssemblyBuilder_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4115 mono_reflection_dynimage_basic_init (assemblyb);
4118 void
4119 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
4120 MonoReflectionType *t)
4122 enumtype->type = t->type;
4125 void
4126 ves_icall_ModuleBuilder_basic_init (MonoReflectionModuleBuilder *moduleb)
4128 mono_image_module_basic_init (moduleb);
4131 guint32
4132 ves_icall_ModuleBuilder_getUSIndex (MonoReflectionModuleBuilder *module, MonoString *str)
4134 return mono_image_insert_string (module, str);
4137 void
4138 ves_icall_ModuleBuilder_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
4140 MonoDynamicImage *image = moduleb->dynamic_image;
4142 g_assert (type->type);
4143 image->wrappers_type = mono_class_from_mono_type (type->type);