Update test
[mono-project.git] / mono / metadata / reflection.c
blob664d6f90b55ed11c6900823e2ecd97f467f1802c
1 /*
2 * reflection.c: Routines for creating an image at runtime.
3 *
4 * Author:
5 * Paolo Molaro (lupus@ximian.com)
7 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9 * Copyright 2011 Rodrigo Kumpera
12 #include <config.h>
13 #include "mono/utils/mono-digest.h"
14 #include "mono/utils/mono-membar.h"
15 #include "mono/metadata/reflection.h"
16 #include "mono/metadata/tabledefs.h"
17 #include "mono/metadata/metadata-internals.h"
18 #include <mono/metadata/profiler-private.h>
19 #include "mono/metadata/class-internals.h"
20 #include "mono/metadata/gc-internal.h"
21 #include "mono/metadata/tokentype.h"
22 #include "mono/metadata/domain-internals.h"
23 #include "mono/metadata/opcodes.h"
24 #include "mono/metadata/assembly.h"
25 #include "mono/metadata/object-internals.h"
26 #include <mono/metadata/exception.h>
27 #include <mono/metadata/marshal.h>
28 #include <mono/metadata/security-manager.h>
29 #include <stdio.h>
30 #include <glib.h>
31 #include <errno.h>
32 #include <time.h>
33 #include <string.h>
34 #include <ctype.h>
35 #include "image.h"
36 #include "cil-coff.h"
37 #include "mono-endian.h"
38 #include <mono/metadata/gc-internal.h>
39 #include <mono/metadata/mempool-internals.h>
40 #include <mono/metadata/security-core-clr.h>
41 #include <mono/metadata/debug-helpers.h>
42 #include <mono/metadata/verify-internals.h>
43 #include <mono/metadata/mono-ptr-array.h>
44 #include <mono/utils/mono-string.h>
45 #include <mono/utils/mono-error-internals.h>
47 static gboolean is_usertype (MonoReflectionType *ref);
48 static MonoReflectionType *mono_reflection_type_resolve_user_types (MonoReflectionType *type);
50 typedef struct {
51 char *p;
52 char *buf;
53 char *end;
54 } SigBuffer;
56 #define TEXT_OFFSET 512
57 #define CLI_H_SIZE 136
58 #define FILE_ALIGN 512
59 #define VIRT_ALIGN 8192
60 #define START_TEXT_RVA 0x00002000
62 typedef struct {
63 MonoReflectionILGen *ilgen;
64 MonoReflectionType *rtype;
65 MonoArray *parameters;
66 MonoArray *generic_params;
67 MonoGenericContainer *generic_container;
68 MonoArray *pinfo;
69 MonoArray *opt_types;
70 guint32 attrs;
71 guint32 iattrs;
72 guint32 call_conv;
73 guint32 *table_idx; /* note: it's a pointer */
74 MonoArray *code;
75 MonoObject *type;
76 MonoString *name;
77 MonoBoolean init_locals;
78 MonoBoolean skip_visibility;
79 MonoArray *return_modreq;
80 MonoArray *return_modopt;
81 MonoArray *param_modreq;
82 MonoArray *param_modopt;
83 MonoArray *permissions;
84 MonoMethod *mhandle;
85 guint32 nrefs;
86 gpointer *refs;
87 /* for PInvoke */
88 int charset, extra_flags, native_cc;
89 MonoString *dll, *dllentry;
90 } ReflectionMethodBuilder;
92 typedef struct {
93 guint32 owner;
94 MonoReflectionGenericParam *gparam;
95 } GenericParamTableEntry;
97 const unsigned char table_sizes [MONO_TABLE_NUM] = {
98 MONO_MODULE_SIZE,
99 MONO_TYPEREF_SIZE,
100 MONO_TYPEDEF_SIZE,
102 MONO_FIELD_SIZE,
104 MONO_METHOD_SIZE,
106 MONO_PARAM_SIZE,
107 MONO_INTERFACEIMPL_SIZE,
108 MONO_MEMBERREF_SIZE, /* 0x0A */
109 MONO_CONSTANT_SIZE,
110 MONO_CUSTOM_ATTR_SIZE,
111 MONO_FIELD_MARSHAL_SIZE,
112 MONO_DECL_SECURITY_SIZE,
113 MONO_CLASS_LAYOUT_SIZE,
114 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
115 MONO_STAND_ALONE_SIGNATURE_SIZE,
116 MONO_EVENT_MAP_SIZE,
118 MONO_EVENT_SIZE,
119 MONO_PROPERTY_MAP_SIZE,
121 MONO_PROPERTY_SIZE,
122 MONO_METHOD_SEMA_SIZE,
123 MONO_METHODIMPL_SIZE,
124 MONO_MODULEREF_SIZE, /* 0x1A */
125 MONO_TYPESPEC_SIZE,
126 MONO_IMPLMAP_SIZE,
127 MONO_FIELD_RVA_SIZE,
130 MONO_ASSEMBLY_SIZE, /* 0x20 */
131 MONO_ASSEMBLY_PROCESSOR_SIZE,
132 MONO_ASSEMBLYOS_SIZE,
133 MONO_ASSEMBLYREF_SIZE,
134 MONO_ASSEMBLYREFPROC_SIZE,
135 MONO_ASSEMBLYREFOS_SIZE,
136 MONO_FILE_SIZE,
137 MONO_EXP_TYPE_SIZE,
138 MONO_MANIFEST_SIZE,
139 MONO_NESTED_CLASS_SIZE,
141 MONO_GENERICPARAM_SIZE, /* 0x2A */
142 MONO_METHODSPEC_SIZE,
143 MONO_GENPARCONSTRAINT_SIZE
147 #ifndef DISABLE_REFLECTION_EMIT
148 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
149 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_open_instance);
150 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
151 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
152 static void ensure_runtime_vtable (MonoClass *klass);
153 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
154 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method);
155 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
156 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
157 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
158 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
159 static guint32 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb);
160 #endif
162 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
163 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
164 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
165 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
166 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
167 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
168 static void encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
169 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
170 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t);
171 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
172 static MonoReflectionType* mono_reflection_type_resolve_user_types (MonoReflectionType *type);
173 static gboolean is_sre_array (MonoClass *class);
174 static gboolean is_sre_byref (MonoClass *class);
175 static gboolean is_sre_pointer (MonoClass *class);
176 static gboolean is_sre_type_builder (MonoClass *class);
177 static gboolean is_sre_method_builder (MonoClass *class);
178 static gboolean is_sre_ctor_builder (MonoClass *class);
179 static gboolean is_sre_field_builder (MonoClass *class);
180 static gboolean is_sr_mono_method (MonoClass *class);
181 static gboolean is_sr_mono_cmethod (MonoClass *class);
182 static gboolean is_sr_mono_generic_method (MonoClass *class);
183 static gboolean is_sr_mono_generic_cmethod (MonoClass *class);
184 static gboolean is_sr_mono_field (MonoClass *class);
185 static gboolean is_sr_mono_property (MonoClass *class);
186 static gboolean is_sre_method_on_tb_inst (MonoClass *class);
187 static gboolean is_sre_ctor_on_tb_inst (MonoClass *class);
189 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
190 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
191 static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj);
193 static guint32 create_typespec (MonoDynamicImage *assembly, MonoType *type);
194 static void init_type_builder_generics (MonoObject *type);
196 #define RESOLVE_TYPE(type) do { type = (void*)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type); } while (0)
197 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index) do { \
198 MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index); \
199 __type = mono_reflection_type_resolve_user_types (__type); \
200 mono_array_set (arr, MonoReflectionType*, index, __type); \
201 } while (0)
203 #define mono_type_array_get_and_resolve(array, index) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index))
205 void
206 mono_reflection_init (void)
210 static void
211 sigbuffer_init (SigBuffer *buf, int size)
213 buf->buf = g_malloc (size);
214 buf->p = buf->buf;
215 buf->end = buf->buf + size;
218 static void
219 sigbuffer_make_room (SigBuffer *buf, int size)
221 if (buf->end - buf->p < size) {
222 int new_size = buf->end - buf->buf + size + 32;
223 char *p = g_realloc (buf->buf, new_size);
224 size = buf->p - buf->buf;
225 buf->buf = p;
226 buf->p = p + size;
227 buf->end = buf->buf + new_size;
231 static void
232 sigbuffer_add_value (SigBuffer *buf, guint32 val)
234 sigbuffer_make_room (buf, 6);
235 mono_metadata_encode_value (val, buf->p, &buf->p);
238 static void
239 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
241 sigbuffer_make_room (buf, 1);
242 buf->p [0] = val;
243 buf->p++;
246 static void
247 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
249 sigbuffer_make_room (buf, size);
250 memcpy (buf->p, p, size);
251 buf->p += size;
254 static void
255 sigbuffer_free (SigBuffer *buf)
257 g_free (buf->buf);
260 #ifndef DISABLE_REFLECTION_EMIT
262 * mp_g_alloc:
264 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
265 * from the C heap.
267 static gpointer
268 image_g_malloc (MonoImage *image, guint size)
270 if (image)
271 return mono_image_alloc (image, size);
272 else
273 return g_malloc (size);
275 #endif /* !DISABLE_REFLECTION_EMIT */
278 * image_g_alloc0:
280 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
281 * from the C heap.
283 static gpointer
284 image_g_malloc0 (MonoImage *image, guint size)
286 if (image)
287 return mono_image_alloc0 (image, size);
288 else
289 return g_malloc0 (size);
292 #ifndef DISABLE_REFLECTION_EMIT
293 static char*
294 image_strdup (MonoImage *image, const char *s)
296 if (image)
297 return mono_image_strdup (image, s);
298 else
299 return g_strdup (s);
301 #endif
303 #define image_g_new(image,struct_type, n_structs) \
304 ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
306 #define image_g_new0(image,struct_type, n_structs) \
307 ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
310 static void
311 alloc_table (MonoDynamicTable *table, guint nrows)
313 table->rows = nrows;
314 g_assert (table->columns);
315 if (nrows + 1 >= table->alloc_rows) {
316 while (nrows + 1 >= table->alloc_rows) {
317 if (table->alloc_rows == 0)
318 table->alloc_rows = 16;
319 else
320 table->alloc_rows *= 2;
323 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
327 static void
328 make_room_in_stream (MonoDynamicStream *stream, int size)
330 if (size <= stream->alloc_size)
331 return;
333 while (stream->alloc_size <= size) {
334 if (stream->alloc_size < 4096)
335 stream->alloc_size = 4096;
336 else
337 stream->alloc_size *= 2;
340 stream->data = g_realloc (stream->data, stream->alloc_size);
343 static guint32
344 string_heap_insert (MonoDynamicStream *sh, const char *str)
346 guint32 idx;
347 guint32 len;
348 gpointer oldkey, oldval;
350 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
351 return GPOINTER_TO_UINT (oldval);
353 len = strlen (str) + 1;
354 idx = sh->index;
356 make_room_in_stream (sh, idx + len);
359 * We strdup the string even if we already copy them in sh->data
360 * so that the string pointers in the hash remain valid even if
361 * we need to realloc sh->data. We may want to avoid that later.
363 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
364 memcpy (sh->data + idx, str, len);
365 sh->index += len;
366 return idx;
369 static guint32
370 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
372 char *name = mono_string_to_utf8 (str);
373 guint32 idx;
374 idx = string_heap_insert (sh, name);
375 g_free (name);
376 return idx;
379 #ifndef DISABLE_REFLECTION_EMIT
380 static void
381 string_heap_init (MonoDynamicStream *sh)
383 sh->index = 0;
384 sh->alloc_size = 4096;
385 sh->data = g_malloc (4096);
386 sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
387 string_heap_insert (sh, "");
389 #endif
391 static guint32
392 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
394 guint32 idx;
396 make_room_in_stream (stream, stream->index + len);
397 memcpy (stream->data + stream->index, data, len);
398 idx = stream->index;
399 stream->index += len;
401 * align index? Not without adding an additional param that controls it since
402 * we may store a blob value in pieces.
404 return idx;
407 static guint32
408 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
410 guint32 idx;
412 make_room_in_stream (stream, stream->index + len);
413 memset (stream->data + stream->index, 0, len);
414 idx = stream->index;
415 stream->index += len;
416 return idx;
419 static void
420 stream_data_align (MonoDynamicStream *stream)
422 char buf [4] = {0};
423 guint32 count = stream->index % 4;
425 /* we assume the stream data will be aligned */
426 if (count)
427 mono_image_add_stream_data (stream, buf, 4 - count);
430 #ifndef DISABLE_REFLECTION_EMIT
431 static int
432 mono_blob_entry_hash (const char* str)
434 guint len, h;
435 const char *end;
436 len = mono_metadata_decode_blob_size (str, &str);
437 if (len > 0) {
438 end = str + len;
439 h = *str;
440 for (str += 1; str < end; str++)
441 h = (h << 5) - h + *str;
442 return h;
443 } else {
444 return 0;
448 static gboolean
449 mono_blob_entry_equal (const char *str1, const char *str2) {
450 int len, len2;
451 const char *end1;
452 const char *end2;
453 len = mono_metadata_decode_blob_size (str1, &end1);
454 len2 = mono_metadata_decode_blob_size (str2, &end2);
455 if (len != len2)
456 return 0;
457 return memcmp (end1, end2, len) == 0;
459 #endif
460 static guint32
461 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
463 guint32 idx;
464 char *copy;
465 gpointer oldkey, oldval;
467 copy = g_malloc (s1+s2);
468 memcpy (copy, b1, s1);
469 memcpy (copy + s1, b2, s2);
470 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
471 g_free (copy);
472 idx = GPOINTER_TO_UINT (oldval);
473 } else {
474 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
475 mono_image_add_stream_data (&assembly->blob, b2, s2);
476 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
478 return idx;
481 static guint32
482 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
484 char blob_size [8];
485 char *b = blob_size;
486 guint32 size = buf->p - buf->buf;
487 /* store length */
488 g_assert (size <= (buf->end - buf->buf));
489 mono_metadata_encode_value (size, b, &b);
490 return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
494 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
495 * dest may be misaligned.
497 static void
498 swap_with_size (char *dest, const char* val, int len, int nelem) {
499 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
500 int elem;
502 for (elem = 0; elem < nelem; ++elem) {
503 switch (len) {
504 case 1:
505 *dest = *val;
506 break;
507 case 2:
508 dest [0] = val [1];
509 dest [1] = val [0];
510 break;
511 case 4:
512 dest [0] = val [3];
513 dest [1] = val [2];
514 dest [2] = val [1];
515 dest [3] = val [0];
516 break;
517 case 8:
518 dest [0] = val [7];
519 dest [1] = val [6];
520 dest [2] = val [5];
521 dest [3] = val [4];
522 dest [4] = val [3];
523 dest [5] = val [2];
524 dest [6] = val [1];
525 dest [7] = val [0];
526 break;
527 default:
528 g_assert_not_reached ();
530 dest += len;
531 val += len;
533 #else
534 memcpy (dest, val, len * nelem);
535 #endif
538 static guint32
539 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
541 char blob_size [64];
542 char *b = blob_size;
543 guint32 idx = 0, len;
545 len = str->length * 2;
546 mono_metadata_encode_value (len, b, &b);
547 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
549 char *swapped = g_malloc (2 * mono_string_length (str));
550 const char *p = (const char*)mono_string_chars (str);
552 swap_with_size (swapped, p, 2, mono_string_length (str));
553 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
554 g_free (swapped);
556 #else
557 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
558 #endif
559 return idx;
562 #ifndef DISABLE_REFLECTION_EMIT
563 static MonoClass *
564 default_class_from_mono_type (MonoType *type)
566 switch (type->type) {
567 case MONO_TYPE_OBJECT:
568 return mono_defaults.object_class;
569 case MONO_TYPE_VOID:
570 return mono_defaults.void_class;
571 case MONO_TYPE_BOOLEAN:
572 return mono_defaults.boolean_class;
573 case MONO_TYPE_CHAR:
574 return mono_defaults.char_class;
575 case MONO_TYPE_I1:
576 return mono_defaults.sbyte_class;
577 case MONO_TYPE_U1:
578 return mono_defaults.byte_class;
579 case MONO_TYPE_I2:
580 return mono_defaults.int16_class;
581 case MONO_TYPE_U2:
582 return mono_defaults.uint16_class;
583 case MONO_TYPE_I4:
584 return mono_defaults.int32_class;
585 case MONO_TYPE_U4:
586 return mono_defaults.uint32_class;
587 case MONO_TYPE_I:
588 return mono_defaults.int_class;
589 case MONO_TYPE_U:
590 return mono_defaults.uint_class;
591 case MONO_TYPE_I8:
592 return mono_defaults.int64_class;
593 case MONO_TYPE_U8:
594 return mono_defaults.uint64_class;
595 case MONO_TYPE_R4:
596 return mono_defaults.single_class;
597 case MONO_TYPE_R8:
598 return mono_defaults.double_class;
599 case MONO_TYPE_STRING:
600 return mono_defaults.string_class;
601 default:
602 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
603 g_assert_not_reached ();
606 return NULL;
608 #endif
611 * mono_class_get_ref_info:
613 * Return the type builder/generic param builder corresponding to KLASS, if it exists.
615 gpointer
616 mono_class_get_ref_info (MonoClass *klass)
618 if (klass->ref_info_handle == 0)
619 return NULL;
620 else
621 return mono_gchandle_get_target (klass->ref_info_handle);
624 void
625 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
627 klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
628 g_assert (klass->ref_info_handle != 0);
631 void
632 mono_class_free_ref_info (MonoClass *klass)
634 if (klass->ref_info_handle) {
635 mono_gchandle_free (klass->ref_info_handle);
636 klass->ref_info_handle = 0;
640 static void
641 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
643 int i;
644 MonoGenericInst *class_inst;
645 MonoClass *klass;
647 g_assert (gclass);
649 class_inst = gclass->context.class_inst;
651 sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
652 klass = gclass->container_class;
653 sigbuffer_add_value (buf, klass->byval_arg.type);
654 sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
656 sigbuffer_add_value (buf, class_inst->type_argc);
657 for (i = 0; i < class_inst->type_argc; ++i)
658 encode_type (assembly, class_inst->type_argv [i], buf);
662 static void
663 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
665 if (!type) {
666 g_assert_not_reached ();
667 return;
670 if (type->byref)
671 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
673 switch (type->type){
674 case MONO_TYPE_VOID:
675 case MONO_TYPE_BOOLEAN:
676 case MONO_TYPE_CHAR:
677 case MONO_TYPE_I1:
678 case MONO_TYPE_U1:
679 case MONO_TYPE_I2:
680 case MONO_TYPE_U2:
681 case MONO_TYPE_I4:
682 case MONO_TYPE_U4:
683 case MONO_TYPE_I8:
684 case MONO_TYPE_U8:
685 case MONO_TYPE_R4:
686 case MONO_TYPE_R8:
687 case MONO_TYPE_I:
688 case MONO_TYPE_U:
689 case MONO_TYPE_STRING:
690 case MONO_TYPE_OBJECT:
691 case MONO_TYPE_TYPEDBYREF:
692 sigbuffer_add_value (buf, type->type);
693 break;
694 case MONO_TYPE_PTR:
695 sigbuffer_add_value (buf, type->type);
696 encode_type (assembly, type->data.type, buf);
697 break;
698 case MONO_TYPE_SZARRAY:
699 sigbuffer_add_value (buf, type->type);
700 encode_type (assembly, &type->data.klass->byval_arg, buf);
701 break;
702 case MONO_TYPE_VALUETYPE:
703 case MONO_TYPE_CLASS: {
704 MonoClass *k = mono_class_from_mono_type (type);
706 if (k->generic_container) {
707 MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
708 encode_generic_class (assembly, gclass, buf);
709 } else {
711 * Make sure we use the correct type.
713 sigbuffer_add_value (buf, k->byval_arg.type);
715 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
716 * otherwise two typerefs could point to the same type, leading to
717 * verification errors.
719 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
721 break;
723 case MONO_TYPE_ARRAY:
724 sigbuffer_add_value (buf, type->type);
725 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
726 sigbuffer_add_value (buf, type->data.array->rank);
727 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
728 sigbuffer_add_value (buf, 0);
729 break;
730 case MONO_TYPE_GENERICINST:
731 encode_generic_class (assembly, type->data.generic_class, buf);
732 break;
733 case MONO_TYPE_VAR:
734 case MONO_TYPE_MVAR:
735 sigbuffer_add_value (buf, type->type);
736 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
737 break;
738 default:
739 g_error ("need to encode type %x", type->type);
743 static void
744 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
746 if (!type) {
747 sigbuffer_add_value (buf, MONO_TYPE_VOID);
748 return;
751 encode_type (assembly, mono_reflection_type_get_handle (type), buf);
754 static void
755 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
757 int i;
759 if (modreq) {
760 for (i = 0; i < mono_array_length (modreq); ++i) {
761 MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
762 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
763 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
766 if (modopt) {
767 for (i = 0; i < mono_array_length (modopt); ++i) {
768 MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
769 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
770 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
775 #ifndef DISABLE_REFLECTION_EMIT
776 static guint32
777 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
779 SigBuffer buf;
780 int i;
781 guint32 nparams = sig->param_count;
782 guint32 idx;
784 if (!assembly->save)
785 return 0;
787 sigbuffer_init (&buf, 32);
789 * FIXME: vararg, explicit_this, differenc call_conv values...
791 idx = sig->call_convention;
792 if (sig->hasthis)
793 idx |= 0x20; /* hasthis */
794 if (sig->generic_param_count)
795 idx |= 0x10; /* generic */
796 sigbuffer_add_byte (&buf, idx);
797 if (sig->generic_param_count)
798 sigbuffer_add_value (&buf, sig->generic_param_count);
799 sigbuffer_add_value (&buf, nparams);
800 encode_type (assembly, sig->ret, &buf);
801 for (i = 0; i < nparams; ++i) {
802 if (i == sig->sentinelpos)
803 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
804 encode_type (assembly, sig->params [i], &buf);
806 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
807 sigbuffer_free (&buf);
808 return idx;
810 #endif
812 static guint32
813 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
816 * FIXME: reuse code from method_encode_signature().
818 SigBuffer buf;
819 int i;
820 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
821 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
822 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
823 guint32 idx;
825 sigbuffer_init (&buf, 32);
826 /* LAMESPEC: all the call conv spec is foobared */
827 idx = mb->call_conv & 0x60; /* has-this, explicit-this */
828 if (mb->call_conv & 2)
829 idx |= 0x5; /* vararg */
830 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
831 idx |= 0x20; /* hasthis */
832 if (ngparams)
833 idx |= 0x10; /* generic */
834 sigbuffer_add_byte (&buf, idx);
835 if (ngparams)
836 sigbuffer_add_value (&buf, ngparams);
837 sigbuffer_add_value (&buf, nparams + notypes);
838 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
839 encode_reflection_type (assembly, mb->rtype, &buf);
840 for (i = 0; i < nparams; ++i) {
841 MonoArray *modreq = NULL;
842 MonoArray *modopt = NULL;
843 MonoReflectionType *pt;
845 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
846 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
847 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
848 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
849 encode_custom_modifiers (assembly, modreq, modopt, &buf);
850 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
851 encode_reflection_type (assembly, pt, &buf);
853 if (notypes)
854 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
855 for (i = 0; i < notypes; ++i) {
856 MonoReflectionType *pt;
858 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
859 encode_reflection_type (assembly, pt, &buf);
862 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
863 sigbuffer_free (&buf);
864 return idx;
867 static guint32
868 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
870 MonoDynamicTable *table;
871 guint32 *values;
872 guint32 idx, sig_idx;
873 guint nl = mono_array_length (ilgen->locals);
874 SigBuffer buf;
875 int i;
877 sigbuffer_init (&buf, 32);
878 sigbuffer_add_value (&buf, 0x07);
879 sigbuffer_add_value (&buf, nl);
880 for (i = 0; i < nl; ++i) {
881 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
883 if (lb->is_pinned)
884 sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
886 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf);
888 sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
889 sigbuffer_free (&buf);
891 if (assembly->standalonesig_cache == NULL)
892 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
893 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
894 if (idx)
895 return idx;
897 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
898 idx = table->next_idx ++;
899 table->rows ++;
900 alloc_table (table, table->rows);
901 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
903 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
905 g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
907 return idx;
910 static guint32
911 method_count_clauses (MonoReflectionILGen *ilgen)
913 guint32 num_clauses = 0;
914 int i;
916 MonoILExceptionInfo *ex_info;
917 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
918 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
919 if (ex_info->handlers)
920 num_clauses += mono_array_length (ex_info->handlers);
921 else
922 num_clauses++;
925 return num_clauses;
928 #ifndef DISABLE_REFLECTION_EMIT
929 static MonoExceptionClause*
930 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
932 MonoExceptionClause *clauses;
933 MonoExceptionClause *clause;
934 MonoILExceptionInfo *ex_info;
935 MonoILExceptionBlock *ex_block;
936 guint32 finally_start;
937 int i, j, clause_index;;
939 clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
941 clause_index = 0;
942 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
943 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
944 finally_start = ex_info->start + ex_info->len;
945 if (!ex_info->handlers)
946 continue;
947 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
948 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
949 clause = &(clauses [clause_index]);
951 clause->flags = ex_block->type;
952 clause->try_offset = ex_info->start;
954 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
955 clause->try_len = finally_start - ex_info->start;
956 else
957 clause->try_len = ex_info->len;
958 clause->handler_offset = ex_block->start;
959 clause->handler_len = ex_block->len;
960 if (ex_block->extype) {
961 clause->data.catch_class = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype));
962 } else {
963 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
964 clause->data.filter_offset = ex_block->filter_offset;
965 else
966 clause->data.filter_offset = 0;
968 finally_start = ex_block->start + ex_block->len;
970 clause_index ++;
974 return clauses;
976 #endif /* !DISABLE_REFLECTION_EMIT */
978 static guint32
979 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
981 char flags = 0;
982 guint32 idx;
983 guint32 code_size;
984 gint32 max_stack, i;
985 gint32 num_locals = 0;
986 gint32 num_exception = 0;
987 gint maybe_small;
988 guint32 fat_flags;
989 char fat_header [12];
990 guint32 int_value;
991 guint16 short_value;
992 guint32 local_sig = 0;
993 guint32 header_size = 12;
994 MonoArray *code;
996 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
997 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
998 return 0;
1000 /*if (mb->name)
1001 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1002 if (mb->ilgen) {
1003 code = mb->ilgen->code;
1004 code_size = mb->ilgen->code_len;
1005 max_stack = mb->ilgen->max_stack;
1006 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1007 if (mb->ilgen->ex_handlers)
1008 num_exception = method_count_clauses (mb->ilgen);
1009 } else {
1010 code = mb->code;
1011 if (code == NULL){
1012 char *name = mono_string_to_utf8 (mb->name);
1013 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1014 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
1015 g_free (str);
1016 g_free (name);
1017 mono_raise_exception (exception);
1020 code_size = mono_array_length (code);
1021 max_stack = 8; /* we probably need to run a verifier on the code... */
1024 stream_data_align (&assembly->code);
1026 /* check for exceptions, maxstack, locals */
1027 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1028 if (maybe_small) {
1029 if (code_size < 64 && !(code_size & 1)) {
1030 flags = (code_size << 2) | 0x2;
1031 } else if (code_size < 32 && (code_size & 1)) {
1032 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1033 } else {
1034 goto fat_header;
1036 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1037 /* add to the fixup todo list */
1038 if (mb->ilgen && mb->ilgen->num_token_fixups)
1039 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1040 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1041 return assembly->text_rva + idx;
1043 fat_header:
1044 if (num_locals)
1045 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
1047 * FIXME: need to set also the header size in fat_flags.
1048 * (and more sects and init locals flags)
1050 fat_flags = 0x03;
1051 if (num_exception)
1052 fat_flags |= METHOD_HEADER_MORE_SECTS;
1053 if (mb->init_locals)
1054 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1055 fat_header [0] = fat_flags;
1056 fat_header [1] = (header_size / 4 ) << 4;
1057 short_value = GUINT16_TO_LE (max_stack);
1058 memcpy (fat_header + 2, &short_value, 2);
1059 int_value = GUINT32_TO_LE (code_size);
1060 memcpy (fat_header + 4, &int_value, 4);
1061 int_value = GUINT32_TO_LE (local_sig);
1062 memcpy (fat_header + 8, &int_value, 4);
1063 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1064 /* add to the fixup todo list */
1065 if (mb->ilgen && mb->ilgen->num_token_fixups)
1066 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1068 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1069 if (num_exception) {
1070 unsigned char sheader [4];
1071 MonoILExceptionInfo * ex_info;
1072 MonoILExceptionBlock * ex_block;
1073 int j;
1075 stream_data_align (&assembly->code);
1076 /* always use fat format for now */
1077 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1078 num_exception *= 6 * sizeof (guint32);
1079 num_exception += 4; /* include the size of the header */
1080 sheader [1] = num_exception & 0xff;
1081 sheader [2] = (num_exception >> 8) & 0xff;
1082 sheader [3] = (num_exception >> 16) & 0xff;
1083 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1084 /* fat header, so we are already aligned */
1085 /* reverse order */
1086 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1087 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1088 if (ex_info->handlers) {
1089 int finally_start = ex_info->start + ex_info->len;
1090 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1091 guint32 val;
1092 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1093 /* the flags */
1094 val = GUINT32_TO_LE (ex_block->type);
1095 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1096 /* try offset */
1097 val = GUINT32_TO_LE (ex_info->start);
1098 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1099 /* need fault, too, probably */
1100 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1101 val = GUINT32_TO_LE (finally_start - ex_info->start);
1102 else
1103 val = GUINT32_TO_LE (ex_info->len);
1104 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1105 /* handler offset */
1106 val = GUINT32_TO_LE (ex_block->start);
1107 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1108 /* handler len */
1109 val = GUINT32_TO_LE (ex_block->len);
1110 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1111 finally_start = ex_block->start + ex_block->len;
1112 if (ex_block->extype) {
1113 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype)));
1114 } else {
1115 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1116 val = ex_block->filter_offset;
1117 else
1118 val = 0;
1120 val = GUINT32_TO_LE (val);
1121 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1122 /*g_print ("out clause %d: from %d len=%d, handler at %d, %d, finally_start=%d, ex_info->start=%d, ex_info->len=%d, ex_block->type=%d, j=%d, i=%d\n",
1123 clause.flags, clause.try_offset, clause.try_len, clause.handler_offset, clause.handler_len, finally_start, ex_info->start, ex_info->len, ex_block->type, j, i);*/
1125 } else {
1126 g_error ("No clauses for ex info block %d", i);
1130 return assembly->text_rva + idx;
1133 static guint32
1134 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1136 int i;
1137 MonoDynamicTable *table;
1138 guint32 *values;
1140 table = &assembly->tables [table_idx];
1142 g_assert (col < table->columns);
1144 values = table->values + table->columns;
1145 for (i = 1; i <= table->rows; ++i) {
1146 if (values [col] == token)
1147 return i;
1148 values += table->columns;
1150 return 0;
1154 * LOCKING: Acquires the loader lock.
1156 static MonoCustomAttrInfo*
1157 lookup_custom_attr (MonoImage *image, gpointer member)
1159 MonoCustomAttrInfo* res;
1161 res = mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1163 if (!res)
1164 return NULL;
1166 res = g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1167 res->cached = 0;
1168 return res;
1171 static gboolean
1172 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1174 /* FIXME: Need to do more checks */
1175 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1176 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1178 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1179 return FALSE;
1182 return TRUE;
1185 static MonoCustomAttrInfo*
1186 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1188 int i, index, count, not_visible;
1189 MonoCustomAttrInfo *ainfo;
1190 MonoReflectionCustomAttr *cattr;
1192 if (!cattrs)
1193 return NULL;
1194 /* FIXME: check in assembly the Run flag is set */
1196 count = mono_array_length (cattrs);
1198 /* Skip nonpublic attributes since MS.NET seems to do the same */
1199 /* FIXME: This needs to be done more globally */
1200 not_visible = 0;
1201 for (i = 0; i < count; ++i) {
1202 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1203 if (!custom_attr_visible (image, cattr))
1204 not_visible ++;
1206 count -= not_visible;
1208 ainfo = image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1210 ainfo->image = image;
1211 ainfo->num_attrs = count;
1212 ainfo->cached = alloc_img != NULL;
1213 index = 0;
1214 for (i = 0; i < count; ++i) {
1215 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1216 if (custom_attr_visible (image, cattr)) {
1217 unsigned char *saved = mono_image_alloc (image, mono_array_length (cattr->data));
1218 memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1219 ainfo->attrs [index].ctor = cattr->ctor->method;
1220 ainfo->attrs [index].data = saved;
1221 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1222 index ++;
1226 return ainfo;
1229 #ifndef DISABLE_REFLECTION_EMIT
1231 * LOCKING: Acquires the loader lock.
1233 static void
1234 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1236 MonoCustomAttrInfo *ainfo, *tmp;
1238 if (!cattrs || !mono_array_length (cattrs))
1239 return;
1241 ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1243 mono_loader_lock ();
1244 tmp = mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1245 if (tmp)
1246 mono_custom_attrs_free (tmp);
1247 mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1248 mono_loader_unlock ();
1251 #endif
1253 void
1254 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1256 if (!ainfo->cached)
1257 g_free (ainfo);
1261 * idx is the table index of the object
1262 * type is one of MONO_CUSTOM_ATTR_*
1264 static void
1265 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1267 MonoDynamicTable *table;
1268 MonoReflectionCustomAttr *cattr;
1269 guint32 *values;
1270 guint32 count, i, token;
1271 char blob_size [6];
1272 char *p = blob_size;
1274 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1275 if (!cattrs)
1276 return;
1277 count = mono_array_length (cattrs);
1278 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1279 table->rows += count;
1280 alloc_table (table, table->rows);
1281 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1282 idx <<= MONO_CUSTOM_ATTR_BITS;
1283 idx |= type;
1284 for (i = 0; i < count; ++i) {
1285 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1286 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1287 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE);
1288 type = mono_metadata_token_index (token);
1289 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1290 switch (mono_metadata_token_table (token)) {
1291 case MONO_TABLE_METHOD:
1292 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1293 break;
1294 case MONO_TABLE_MEMBERREF:
1295 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1296 break;
1297 default:
1298 g_warning ("got wrong token in custom attr");
1299 continue;
1301 values [MONO_CUSTOM_ATTR_TYPE] = type;
1302 p = blob_size;
1303 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1304 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1305 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1306 values += MONO_CUSTOM_ATTR_SIZE;
1307 ++table->next_idx;
1311 static void
1312 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1314 MonoDynamicTable *table;
1315 guint32 *values;
1316 guint32 count, i, idx;
1317 MonoReflectionPermissionSet *perm;
1319 if (!permissions)
1320 return;
1322 count = mono_array_length (permissions);
1323 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1324 table->rows += count;
1325 alloc_table (table, table->rows);
1327 for (i = 0; i < mono_array_length (permissions); ++i) {
1328 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1330 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1332 idx = mono_metadata_token_index (parent_token);
1333 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1334 switch (mono_metadata_token_table (parent_token)) {
1335 case MONO_TABLE_TYPEDEF:
1336 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1337 break;
1338 case MONO_TABLE_METHOD:
1339 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1340 break;
1341 case MONO_TABLE_ASSEMBLY:
1342 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1343 break;
1344 default:
1345 g_assert_not_reached ();
1348 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1349 values [MONO_DECL_SECURITY_PARENT] = idx;
1350 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1352 ++table->next_idx;
1357 * Fill in the MethodDef and ParamDef tables for a method.
1358 * This is used for both normal methods and constructors.
1360 static void
1361 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1363 MonoDynamicTable *table;
1364 guint32 *values;
1365 guint i, count;
1367 /* room in this table is already allocated */
1368 table = &assembly->tables [MONO_TABLE_METHOD];
1369 *mb->table_idx = table->next_idx ++;
1370 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1371 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1372 values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1373 values [MONO_METHOD_FLAGS] = mb->attrs;
1374 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1375 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1376 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1378 table = &assembly->tables [MONO_TABLE_PARAM];
1379 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1381 mono_image_add_decl_security (assembly,
1382 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1384 if (mb->pinfo) {
1385 MonoDynamicTable *mtable;
1386 guint32 *mvalues;
1388 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1389 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1391 count = 0;
1392 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1393 if (mono_array_get (mb->pinfo, gpointer, i))
1394 count++;
1396 table->rows += count;
1397 alloc_table (table, table->rows);
1398 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1399 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1400 MonoReflectionParamBuilder *pb;
1401 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1402 values [MONO_PARAM_FLAGS] = pb->attrs;
1403 values [MONO_PARAM_SEQUENCE] = i;
1404 if (pb->name != NULL) {
1405 values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1406 } else {
1407 values [MONO_PARAM_NAME] = 0;
1409 values += MONO_PARAM_SIZE;
1410 if (pb->marshal_info) {
1411 mtable->rows++;
1412 alloc_table (mtable, mtable->rows);
1413 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1414 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1415 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1417 pb->table_idx = table->next_idx++;
1418 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1419 guint32 field_type = 0;
1420 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1421 mtable->rows ++;
1422 alloc_table (mtable, mtable->rows);
1423 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1424 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1425 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1426 mvalues [MONO_CONSTANT_TYPE] = field_type;
1427 mvalues [MONO_CONSTANT_PADDING] = 0;
1434 #ifndef DISABLE_REFLECTION_EMIT
1435 static void
1436 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1438 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1440 rmb->ilgen = mb->ilgen;
1441 rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype);
1442 rmb->parameters = mb->parameters;
1443 rmb->generic_params = mb->generic_params;
1444 rmb->generic_container = mb->generic_container;
1445 rmb->opt_types = NULL;
1446 rmb->pinfo = mb->pinfo;
1447 rmb->attrs = mb->attrs;
1448 rmb->iattrs = mb->iattrs;
1449 rmb->call_conv = mb->call_conv;
1450 rmb->code = mb->code;
1451 rmb->type = mb->type;
1452 rmb->name = mb->name;
1453 rmb->table_idx = &mb->table_idx;
1454 rmb->init_locals = mb->init_locals;
1455 rmb->skip_visibility = FALSE;
1456 rmb->return_modreq = mb->return_modreq;
1457 rmb->return_modopt = mb->return_modopt;
1458 rmb->param_modreq = mb->param_modreq;
1459 rmb->param_modopt = mb->param_modopt;
1460 rmb->permissions = mb->permissions;
1461 rmb->mhandle = mb->mhandle;
1462 rmb->nrefs = 0;
1463 rmb->refs = NULL;
1465 if (mb->dll) {
1466 rmb->charset = mb->charset;
1467 rmb->extra_flags = mb->extra_flags;
1468 rmb->native_cc = mb->native_cc;
1469 rmb->dllentry = mb->dllentry;
1470 rmb->dll = mb->dll;
1474 static void
1475 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1477 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1479 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1481 rmb->ilgen = mb->ilgen;
1482 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1483 rmb->parameters = mb->parameters;
1484 rmb->generic_params = NULL;
1485 rmb->generic_container = NULL;
1486 rmb->opt_types = NULL;
1487 rmb->pinfo = mb->pinfo;
1488 rmb->attrs = mb->attrs;
1489 rmb->iattrs = mb->iattrs;
1490 rmb->call_conv = mb->call_conv;
1491 rmb->code = NULL;
1492 rmb->type = mb->type;
1493 rmb->name = mono_string_new (mono_domain_get (), name);
1494 rmb->table_idx = &mb->table_idx;
1495 rmb->init_locals = mb->init_locals;
1496 rmb->skip_visibility = FALSE;
1497 rmb->return_modreq = NULL;
1498 rmb->return_modopt = NULL;
1499 rmb->param_modreq = mb->param_modreq;
1500 rmb->param_modopt = mb->param_modopt;
1501 rmb->permissions = mb->permissions;
1502 rmb->mhandle = mb->mhandle;
1503 rmb->nrefs = 0;
1504 rmb->refs = NULL;
1507 static void
1508 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1510 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1512 rmb->ilgen = mb->ilgen;
1513 rmb->rtype = mb->rtype;
1514 rmb->parameters = mb->parameters;
1515 rmb->generic_params = NULL;
1516 rmb->generic_container = NULL;
1517 rmb->opt_types = NULL;
1518 rmb->pinfo = NULL;
1519 rmb->attrs = mb->attrs;
1520 rmb->iattrs = 0;
1521 rmb->call_conv = mb->call_conv;
1522 rmb->code = NULL;
1523 rmb->type = (MonoObject *) mb->owner;
1524 rmb->name = mb->name;
1525 rmb->table_idx = NULL;
1526 rmb->init_locals = mb->init_locals;
1527 rmb->skip_visibility = mb->skip_visibility;
1528 rmb->return_modreq = NULL;
1529 rmb->return_modopt = NULL;
1530 rmb->param_modreq = NULL;
1531 rmb->param_modopt = NULL;
1532 rmb->permissions = NULL;
1533 rmb->mhandle = mb->mhandle;
1534 rmb->nrefs = 0;
1535 rmb->refs = NULL;
1537 #endif
1539 static void
1540 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1542 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1543 MonoDynamicTable *table;
1544 guint32 *values;
1545 guint32 tok;
1547 if (!mb->override_method)
1548 return;
1550 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1551 table->rows ++;
1552 alloc_table (table, table->rows);
1553 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1554 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1555 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1557 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE, FALSE);
1558 switch (mono_metadata_token_table (tok)) {
1559 case MONO_TABLE_MEMBERREF:
1560 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1561 break;
1562 case MONO_TABLE_METHOD:
1563 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1564 break;
1565 default:
1566 g_assert_not_reached ();
1568 values [MONO_METHODIMPL_DECLARATION] = tok;
1571 #ifndef DISABLE_REFLECTION_EMIT
1572 static void
1573 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1575 MonoDynamicTable *table;
1576 guint32 *values;
1577 ReflectionMethodBuilder rmb;
1578 int i;
1580 reflection_methodbuilder_from_method_builder (&rmb, mb);
1582 mono_image_basic_method (&rmb, assembly);
1583 mb->table_idx = *rmb.table_idx;
1585 if (mb->dll) { /* It's a P/Invoke method */
1586 guint32 moduleref;
1587 /* map CharSet values to on-disk values */
1588 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1589 int extra_flags = mb->extra_flags;
1590 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1591 table->rows ++;
1592 alloc_table (table, table->rows);
1593 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1595 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1596 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1597 if (mb->dllentry)
1598 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1599 else
1600 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1601 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1602 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1603 table = &assembly->tables [MONO_TABLE_MODULEREF];
1604 table->rows ++;
1605 alloc_table (table, table->rows);
1606 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1607 values [MONO_IMPLMAP_SCOPE] = table->rows;
1611 if (mb->generic_params) {
1612 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1613 table->rows += mono_array_length (mb->generic_params);
1614 alloc_table (table, table->rows);
1615 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1616 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1618 mono_image_get_generic_param_info (
1619 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1625 static void
1626 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1628 ReflectionMethodBuilder rmb;
1630 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1632 mono_image_basic_method (&rmb, assembly);
1633 mb->table_idx = *rmb.table_idx;
1635 #endif
1637 static char*
1638 type_get_fully_qualified_name (MonoType *type)
1640 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1643 static char*
1644 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1645 MonoClass *klass;
1646 MonoAssembly *ta;
1648 klass = mono_class_from_mono_type (type);
1649 if (!klass)
1650 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1651 ta = klass->image->assembly;
1652 if (ta->dynamic || (ta == ass)) {
1653 if (klass->generic_class || klass->generic_container)
1654 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1655 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1656 else
1657 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1660 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1663 #ifndef DISABLE_REFLECTION_EMIT
1664 /*field_image is the image to which the eventual custom mods have been encoded against*/
1665 static guint32
1666 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
1668 SigBuffer buf;
1669 guint32 idx, i, token;
1671 if (!assembly->save)
1672 return 0;
1674 sigbuffer_init (&buf, 32);
1676 sigbuffer_add_value (&buf, 0x06);
1677 /* encode custom attributes before the type */
1678 if (type->num_mods) {
1679 for (i = 0; i < type->num_mods; ++i) {
1680 if (field_image) {
1681 MonoClass *class = mono_class_get (field_image, type->modifiers [i].token);
1682 g_assert (class);
1683 token = mono_image_typedef_or_ref (assembly, &class->byval_arg);
1684 } else {
1685 token = type->modifiers [i].token;
1688 if (type->modifiers [i].required)
1689 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1690 else
1691 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1693 sigbuffer_add_value (&buf, token);
1696 encode_type (assembly, type, &buf);
1697 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1698 sigbuffer_free (&buf);
1699 return idx;
1701 #endif
1703 static guint32
1704 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1706 SigBuffer buf;
1707 guint32 idx;
1708 guint32 typespec = 0;
1709 MonoType *type;
1710 MonoClass *class;
1712 init_type_builder_generics (fb->type);
1714 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
1715 class = mono_class_from_mono_type (type);
1717 sigbuffer_init (&buf, 32);
1719 sigbuffer_add_value (&buf, 0x06);
1720 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1721 /* encode custom attributes before the type */
1723 if (class->generic_container)
1724 typespec = create_typespec (assembly, type);
1726 if (typespec) {
1727 MonoGenericClass *gclass;
1728 gclass = mono_metadata_lookup_generic_class (class, class->generic_container->context.class_inst, TRUE);
1729 encode_generic_class (assembly, gclass, &buf);
1730 } else {
1731 encode_type (assembly, type, &buf);
1733 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1734 sigbuffer_free (&buf);
1735 return idx;
1738 static guint32
1739 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1740 char blob_size [64];
1741 char *b = blob_size;
1742 char *p, *box_val;
1743 char* buf;
1744 guint32 idx = 0, len = 0, dummy = 0;
1745 #ifdef ARM_FPU_FPA
1746 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1747 guint32 fpa_double [2];
1748 guint32 *fpa_p;
1749 #endif
1750 #endif
1752 p = buf = g_malloc (64);
1753 if (!val) {
1754 *ret_type = MONO_TYPE_CLASS;
1755 len = 4;
1756 box_val = (char*)&dummy;
1757 } else {
1758 box_val = ((char*)val) + sizeof (MonoObject);
1759 *ret_type = val->vtable->klass->byval_arg.type;
1761 handle_enum:
1762 switch (*ret_type) {
1763 case MONO_TYPE_BOOLEAN:
1764 case MONO_TYPE_U1:
1765 case MONO_TYPE_I1:
1766 len = 1;
1767 break;
1768 case MONO_TYPE_CHAR:
1769 case MONO_TYPE_U2:
1770 case MONO_TYPE_I2:
1771 len = 2;
1772 break;
1773 case MONO_TYPE_U4:
1774 case MONO_TYPE_I4:
1775 case MONO_TYPE_R4:
1776 len = 4;
1777 break;
1778 case MONO_TYPE_U8:
1779 case MONO_TYPE_I8:
1780 len = 8;
1781 break;
1782 case MONO_TYPE_R8:
1783 len = 8;
1784 #ifdef ARM_FPU_FPA
1785 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1786 fpa_p = (guint32*)box_val;
1787 fpa_double [0] = fpa_p [1];
1788 fpa_double [1] = fpa_p [0];
1789 box_val = (char*)fpa_double;
1790 #endif
1791 #endif
1792 break;
1793 case MONO_TYPE_VALUETYPE: {
1794 MonoClass *klass = val->vtable->klass;
1796 if (klass->enumtype) {
1797 *ret_type = mono_class_enum_basetype (klass)->type;
1798 goto handle_enum;
1799 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
1800 len = 8;
1801 } else
1802 g_error ("we can't encode valuetypes, we should have never reached this line");
1803 break;
1805 case MONO_TYPE_CLASS:
1806 break;
1807 case MONO_TYPE_STRING: {
1808 MonoString *str = (MonoString*)val;
1809 /* there is no signature */
1810 len = str->length * 2;
1811 mono_metadata_encode_value (len, b, &b);
1812 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1814 char *swapped = g_malloc (2 * mono_string_length (str));
1815 const char *p = (const char*)mono_string_chars (str);
1817 swap_with_size (swapped, p, 2, mono_string_length (str));
1818 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1819 g_free (swapped);
1821 #else
1822 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1823 #endif
1825 g_free (buf);
1826 return idx;
1828 case MONO_TYPE_GENERICINST:
1829 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
1830 goto handle_enum;
1831 default:
1832 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1835 /* there is no signature */
1836 mono_metadata_encode_value (len, b, &b);
1837 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1838 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1839 swap_with_size (blob_size, box_val, len, 1);
1840 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1841 #else
1842 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1843 #endif
1845 g_free (buf);
1846 return idx;
1849 static guint32
1850 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1851 char *str;
1852 SigBuffer buf;
1853 guint32 idx, len;
1855 sigbuffer_init (&buf, 32);
1857 sigbuffer_add_value (&buf, minfo->type);
1859 switch (minfo->type) {
1860 case MONO_NATIVE_BYVALTSTR:
1861 case MONO_NATIVE_BYVALARRAY:
1862 sigbuffer_add_value (&buf, minfo->count);
1863 break;
1864 case MONO_NATIVE_LPARRAY:
1865 if (minfo->eltype || minfo->has_size) {
1866 sigbuffer_add_value (&buf, minfo->eltype);
1867 if (minfo->has_size) {
1868 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
1869 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
1871 /* LAMESPEC: ElemMult is undocumented */
1872 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1875 break;
1876 case MONO_NATIVE_SAFEARRAY:
1877 if (minfo->eltype)
1878 sigbuffer_add_value (&buf, minfo->eltype);
1879 break;
1880 case MONO_NATIVE_CUSTOM:
1881 if (minfo->guid) {
1882 str = mono_string_to_utf8 (minfo->guid);
1883 len = strlen (str);
1884 sigbuffer_add_value (&buf, len);
1885 sigbuffer_add_mem (&buf, str, len);
1886 g_free (str);
1887 } else {
1888 sigbuffer_add_value (&buf, 0);
1890 /* native type name */
1891 sigbuffer_add_value (&buf, 0);
1892 /* custom marshaler type name */
1893 if (minfo->marshaltype || minfo->marshaltyperef) {
1894 if (minfo->marshaltyperef)
1895 str = type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
1896 else
1897 str = mono_string_to_utf8 (minfo->marshaltype);
1898 len = strlen (str);
1899 sigbuffer_add_value (&buf, len);
1900 sigbuffer_add_mem (&buf, str, len);
1901 g_free (str);
1902 } else {
1903 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
1904 sigbuffer_add_value (&buf, 0);
1906 if (minfo->mcookie) {
1907 str = mono_string_to_utf8 (minfo->mcookie);
1908 len = strlen (str);
1909 sigbuffer_add_value (&buf, len);
1910 sigbuffer_add_mem (&buf, str, len);
1911 g_free (str);
1912 } else {
1913 sigbuffer_add_value (&buf, 0);
1915 break;
1916 default:
1917 break;
1919 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1920 sigbuffer_free (&buf);
1921 return idx;
1924 static void
1925 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1927 MonoDynamicTable *table;
1928 guint32 *values;
1930 /* maybe this fixup should be done in the C# code */
1931 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1932 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1933 table = &assembly->tables [MONO_TABLE_FIELD];
1934 fb->table_idx = table->next_idx ++;
1935 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1936 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1937 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
1938 values [MONO_FIELD_FLAGS] = fb->attrs;
1939 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1941 if (fb->offset != -1) {
1942 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1943 table->rows ++;
1944 alloc_table (table, table->rows);
1945 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1946 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1947 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1949 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1950 guint32 field_type = 0;
1951 table = &assembly->tables [MONO_TABLE_CONSTANT];
1952 table->rows ++;
1953 alloc_table (table, table->rows);
1954 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1955 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1956 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1957 values [MONO_CONSTANT_TYPE] = field_type;
1958 values [MONO_CONSTANT_PADDING] = 0;
1960 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1961 guint32 rva_idx;
1962 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1963 table->rows ++;
1964 alloc_table (table, table->rows);
1965 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1966 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1968 * We store it in the code section because it's simpler for now.
1970 if (fb->rva_data) {
1971 if (mono_array_length (fb->rva_data) >= 10)
1972 stream_data_align (&assembly->code);
1973 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1974 } else
1975 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1976 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1978 if (fb->marshal_info) {
1979 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1980 table->rows ++;
1981 alloc_table (table, table->rows);
1982 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1983 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1984 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1988 static guint32
1989 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1991 SigBuffer buf;
1992 guint32 nparams = 0;
1993 MonoReflectionMethodBuilder *mb = fb->get_method;
1994 MonoReflectionMethodBuilder *smb = fb->set_method;
1995 guint32 idx, i;
1997 if (mb && mb->parameters)
1998 nparams = mono_array_length (mb->parameters);
1999 if (!mb && smb && smb->parameters)
2000 nparams = mono_array_length (smb->parameters) - 1;
2001 sigbuffer_init (&buf, 32);
2002 if (fb->call_conv & 0x20)
2003 sigbuffer_add_byte (&buf, 0x28);
2004 else
2005 sigbuffer_add_byte (&buf, 0x08);
2006 sigbuffer_add_value (&buf, nparams);
2007 if (mb) {
2008 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf);
2009 for (i = 0; i < nparams; ++i) {
2010 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2011 encode_reflection_type (assembly, pt, &buf);
2013 } else if (smb && smb->parameters) {
2014 /* the property type is the last param */
2015 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
2016 for (i = 0; i < nparams; ++i) {
2017 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2018 encode_reflection_type (assembly, pt, &buf);
2020 } else {
2021 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
2024 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2025 sigbuffer_free (&buf);
2026 return idx;
2029 static void
2030 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
2032 MonoDynamicTable *table;
2033 guint32 *values;
2034 guint num_methods = 0;
2035 guint32 semaidx;
2038 * we need to set things in the following tables:
2039 * PROPERTYMAP (info already filled in _get_type_info ())
2040 * PROPERTY (rows already preallocated in _get_type_info ())
2041 * METHOD (method info already done with the generic method code)
2042 * METHODSEMANTICS
2043 * CONSTANT
2045 table = &assembly->tables [MONO_TABLE_PROPERTY];
2046 pb->table_idx = table->next_idx ++;
2047 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2048 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2049 values [MONO_PROPERTY_FLAGS] = pb->attrs;
2050 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
2052 /* FIXME: we still don't handle 'other' methods */
2053 if (pb->get_method) num_methods ++;
2054 if (pb->set_method) num_methods ++;
2056 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2057 table->rows += num_methods;
2058 alloc_table (table, table->rows);
2060 if (pb->get_method) {
2061 semaidx = table->next_idx ++;
2062 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2063 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2064 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2065 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2067 if (pb->set_method) {
2068 semaidx = table->next_idx ++;
2069 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2070 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2071 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2072 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2074 if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2075 guint32 field_type = 0;
2076 table = &assembly->tables [MONO_TABLE_CONSTANT];
2077 table->rows ++;
2078 alloc_table (table, table->rows);
2079 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2080 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2081 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2082 values [MONO_CONSTANT_TYPE] = field_type;
2083 values [MONO_CONSTANT_PADDING] = 0;
2087 static void
2088 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
2090 MonoDynamicTable *table;
2091 guint32 *values;
2092 guint num_methods = 0;
2093 guint32 semaidx;
2096 * we need to set things in the following tables:
2097 * EVENTMAP (info already filled in _get_type_info ())
2098 * EVENT (rows already preallocated in _get_type_info ())
2099 * METHOD (method info already done with the generic method code)
2100 * METHODSEMANTICS
2102 table = &assembly->tables [MONO_TABLE_EVENT];
2103 eb->table_idx = table->next_idx ++;
2104 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2105 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2106 values [MONO_EVENT_FLAGS] = eb->attrs;
2107 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (eb->type));
2110 * FIXME: we still don't handle 'other' methods
2112 if (eb->add_method) num_methods ++;
2113 if (eb->remove_method) num_methods ++;
2114 if (eb->raise_method) num_methods ++;
2116 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2117 table->rows += num_methods;
2118 alloc_table (table, table->rows);
2120 if (eb->add_method) {
2121 semaidx = table->next_idx ++;
2122 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2123 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2124 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2125 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2127 if (eb->remove_method) {
2128 semaidx = table->next_idx ++;
2129 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2130 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2131 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2132 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2134 if (eb->raise_method) {
2135 semaidx = table->next_idx ++;
2136 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2137 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2138 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2139 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2143 static void
2144 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2146 MonoDynamicTable *table;
2147 guint32 num_constraints, i;
2148 guint32 *values;
2149 guint32 table_idx;
2151 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2152 num_constraints = gparam->iface_constraints ?
2153 mono_array_length (gparam->iface_constraints) : 0;
2154 table->rows += num_constraints;
2155 if (gparam->base_type)
2156 table->rows++;
2157 alloc_table (table, table->rows);
2159 if (gparam->base_type) {
2160 table_idx = table->next_idx ++;
2161 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2163 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2164 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2165 assembly, mono_reflection_type_get_handle (gparam->base_type));
2168 for (i = 0; i < num_constraints; i++) {
2169 MonoReflectionType *constraint = mono_array_get (
2170 gparam->iface_constraints, gpointer, i);
2172 table_idx = table->next_idx ++;
2173 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2175 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2176 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2177 assembly, mono_reflection_type_get_handle (constraint));
2181 static void
2182 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2184 GenericParamTableEntry *entry;
2187 * The GenericParam table must be sorted according to the `owner' field.
2188 * We need to do this sorting prior to writing the GenericParamConstraint
2189 * table, since we have to use the final GenericParam table indices there
2190 * and they must also be sorted.
2193 entry = g_new0 (GenericParamTableEntry, 1);
2194 entry->owner = owner;
2195 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2196 MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam);
2197 entry->gparam = gparam;
2199 g_ptr_array_add (assembly->gen_params, entry);
2202 static void
2203 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2205 MonoDynamicTable *table;
2206 MonoGenericParam *param;
2207 guint32 *values;
2208 guint32 table_idx;
2210 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2211 table_idx = table->next_idx ++;
2212 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2214 param = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam)->data.generic_param;
2216 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2217 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2218 values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2219 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2221 mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2223 encode_constraints (entry->gparam, table_idx, assembly);
2226 static guint32
2227 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2229 MonoDynamicTable *table;
2230 guint32 token;
2231 guint32 *values;
2232 guint32 cols [MONO_ASSEMBLY_SIZE];
2233 const char *pubkey;
2234 guint32 publen;
2236 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2237 return token;
2239 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2240 table = &assembly->tables [MONO_TABLE_MODULEREF];
2241 token = table->next_idx ++;
2242 table->rows ++;
2243 alloc_table (table, table->rows);
2244 values = table->values + token * MONO_MODULEREF_SIZE;
2245 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2247 token <<= MONO_RESOLTION_SCOPE_BITS;
2248 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2249 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2251 return token;
2254 if (image->assembly->dynamic)
2255 /* FIXME: */
2256 memset (cols, 0, sizeof (cols));
2257 else {
2258 /* image->assembly->image is the manifest module */
2259 image = image->assembly->image;
2260 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2263 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2264 token = table->next_idx ++;
2265 table->rows ++;
2266 alloc_table (table, table->rows);
2267 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2268 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2269 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2270 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2271 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2272 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2273 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2274 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2275 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2277 if (strcmp ("", image->assembly->aname.culture)) {
2278 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2279 image->assembly->aname.culture);
2282 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2283 guchar pubtoken [9];
2284 pubtoken [0] = 8;
2285 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2286 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2287 } else {
2288 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2290 token <<= MONO_RESOLTION_SCOPE_BITS;
2291 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2292 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2293 return token;
2296 static guint32
2297 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2299 MonoDynamicTable *table;
2300 guint32 *values;
2301 guint32 token;
2302 SigBuffer buf;
2304 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2305 return token;
2307 sigbuffer_init (&buf, 32);
2308 switch (type->type) {
2309 case MONO_TYPE_FNPTR:
2310 case MONO_TYPE_PTR:
2311 case MONO_TYPE_SZARRAY:
2312 case MONO_TYPE_ARRAY:
2313 case MONO_TYPE_VAR:
2314 case MONO_TYPE_MVAR:
2315 case MONO_TYPE_GENERICINST:
2316 encode_type (assembly, type, &buf);
2317 break;
2318 case MONO_TYPE_CLASS:
2319 case MONO_TYPE_VALUETYPE: {
2320 MonoClass *k = mono_class_from_mono_type (type);
2321 if (!k || !k->generic_container) {
2322 sigbuffer_free (&buf);
2323 return 0;
2325 encode_type (assembly, type, &buf);
2326 break;
2328 default:
2329 sigbuffer_free (&buf);
2330 return 0;
2333 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2334 if (assembly->save) {
2335 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2336 alloc_table (table, table->rows + 1);
2337 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2338 values [MONO_TYPESPEC_SIGNATURE] = token;
2340 sigbuffer_free (&buf);
2342 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2343 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2344 table->next_idx ++;
2345 return token;
2348 static guint32
2349 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2351 MonoDynamicTable *table;
2352 guint32 *values;
2353 guint32 token, scope, enclosing;
2354 MonoClass *klass;
2356 /* if the type requires a typespec, we must try that first*/
2357 if (try_typespec && (token = create_typespec (assembly, type)))
2358 return token;
2359 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2360 if (token)
2361 return token;
2362 klass = mono_class_from_mono_type (type);
2363 if (!klass)
2364 klass = mono_class_from_mono_type (type);
2367 * If it's in the same module and not a generic type parameter:
2369 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2370 (type->type != MONO_TYPE_MVAR)) {
2371 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
2372 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2373 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), mono_class_get_ref_info (klass));
2374 return token;
2377 if (klass->nested_in) {
2378 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2379 /* get the typeref idx of the enclosing type */
2380 enclosing >>= MONO_TYPEDEFORREF_BITS;
2381 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2382 } else {
2383 scope = resolution_scope_from_image (assembly, klass->image);
2385 table = &assembly->tables [MONO_TABLE_TYPEREF];
2386 if (assembly->save) {
2387 alloc_table (table, table->rows + 1);
2388 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2389 values [MONO_TYPEREF_SCOPE] = scope;
2390 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2391 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2393 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2394 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2395 table->next_idx ++;
2396 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), mono_class_get_ref_info (klass));
2397 return token;
2401 * Despite the name, we handle also TypeSpec (with the above helper).
2403 static guint32
2404 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2406 return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2409 #ifndef DISABLE_REFLECTION_EMIT
2410 static guint32
2411 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2413 MonoDynamicTable *table;
2414 guint32 *values;
2415 guint32 token, pclass;
2417 switch (parent & MONO_TYPEDEFORREF_MASK) {
2418 case MONO_TYPEDEFORREF_TYPEREF:
2419 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2420 break;
2421 case MONO_TYPEDEFORREF_TYPESPEC:
2422 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2423 break;
2424 case MONO_TYPEDEFORREF_TYPEDEF:
2425 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2426 break;
2427 default:
2428 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2429 return 0;
2431 /* extract the index */
2432 parent >>= MONO_TYPEDEFORREF_BITS;
2434 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2436 if (assembly->save) {
2437 alloc_table (table, table->rows + 1);
2438 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2439 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2440 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2441 values [MONO_MEMBERREF_SIGNATURE] = sig;
2444 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2445 table->next_idx ++;
2447 return token;
2451 * Insert a memberef row into the metadata: the token that point to the memberref
2452 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2453 * mono_image_get_fieldref_token()).
2454 * The sig param is an index to an already built signature.
2456 static guint32
2457 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2459 guint32 parent = mono_image_typedef_or_ref (assembly, type);
2460 return mono_image_add_memberef_row (assembly, parent, name, sig);
2464 static guint32
2465 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2467 guint32 token;
2468 MonoMethodSignature *sig;
2470 create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2472 if (create_typespec) {
2473 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2474 if (token)
2475 return token;
2478 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2479 if (token && !create_typespec)
2480 return token;
2482 g_assert (!method->is_inflated);
2483 if (!token) {
2485 * A methodref signature can't contain an unmanaged calling convention.
2487 sig = mono_metadata_signature_dup (mono_method_signature (method));
2488 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2489 sig->call_convention = MONO_CALL_DEFAULT;
2490 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2491 method->name, method_encode_signature (assembly, sig));
2492 g_free (sig);
2493 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2496 if (create_typespec) {
2497 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2498 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2499 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2501 if (assembly->save) {
2502 guint32 *values;
2504 alloc_table (table, table->rows + 1);
2505 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2506 values [MONO_METHODSPEC_METHOD] = token;
2507 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2510 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2511 table->next_idx ++;
2512 /*methodspec and memberef tokens are diferent, */
2513 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2514 return token;
2516 return token;
2519 static guint32
2520 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2522 guint32 token, parent, sig;
2523 ReflectionMethodBuilder rmb;
2524 char *name;
2525 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2527 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2528 if (token)
2529 return token;
2531 name = mono_string_to_utf8 (method->name);
2532 reflection_methodbuilder_from_method_builder (&rmb, method);
2535 * A methodref signature can't contain an unmanaged calling convention.
2536 * Since some flags are encoded as part of call_conv, we need to check against it.
2538 if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2539 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2541 sig = method_builder_encode_signature (assembly, &rmb);
2543 if (tb->generic_params)
2544 parent = create_generic_typespec (assembly, tb);
2545 else
2546 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type));
2548 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2550 g_free (name);
2551 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2552 return token;
2555 static guint32
2556 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2557 const gchar *name, guint32 sig)
2559 MonoDynamicTable *table;
2560 guint32 token;
2561 guint32 *values;
2563 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2565 if (assembly->save) {
2566 alloc_table (table, table->rows + 1);
2567 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2568 values [MONO_MEMBERREF_CLASS] = original;
2569 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2570 values [MONO_MEMBERREF_SIGNATURE] = sig;
2573 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2574 table->next_idx ++;
2576 return token;
2579 static guint32
2580 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2582 SigBuffer buf;
2583 int i;
2584 guint32 nparams = mono_array_length (mb->generic_params);
2585 guint32 idx;
2587 if (!assembly->save)
2588 return 0;
2590 sigbuffer_init (&buf, 32);
2592 sigbuffer_add_value (&buf, 0xa);
2593 sigbuffer_add_value (&buf, nparams);
2595 for (i = 0; i < nparams; i++) {
2596 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2597 sigbuffer_add_value (&buf, i);
2600 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2601 sigbuffer_free (&buf);
2602 return idx;
2605 static guint32
2606 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2608 MonoDynamicTable *table;
2609 guint32 *values;
2610 guint32 token, mtoken = 0;
2612 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2613 if (token)
2614 return token;
2616 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2618 mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2619 switch (mono_metadata_token_table (mtoken)) {
2620 case MONO_TABLE_MEMBERREF:
2621 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2622 break;
2623 case MONO_TABLE_METHOD:
2624 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2625 break;
2626 default:
2627 g_assert_not_reached ();
2630 if (assembly->save) {
2631 alloc_table (table, table->rows + 1);
2632 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2633 values [MONO_METHODSPEC_METHOD] = mtoken;
2634 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2637 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2638 table->next_idx ++;
2640 mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2641 return token;
2644 static guint32
2645 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2647 guint32 token;
2649 if (mb->generic_params && create_methodspec)
2650 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2652 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2653 if (token)
2654 return token;
2656 token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2657 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2658 return token;
2661 static guint32
2662 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2664 guint32 token, parent, sig;
2665 ReflectionMethodBuilder rmb;
2666 char *name;
2667 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
2669 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2670 if (token)
2671 return token;
2673 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2675 if (tb->generic_params)
2676 parent = create_generic_typespec (assembly, tb);
2677 else
2678 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb));
2680 name = mono_string_to_utf8 (rmb.name);
2681 sig = method_builder_encode_signature (assembly, &rmb);
2683 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2685 g_free (name);
2686 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2687 return token;
2689 #endif
2691 static gboolean
2692 is_field_on_inst (MonoClassField *field)
2694 return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2698 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2700 static MonoType*
2701 get_field_on_inst_generic_type (MonoClassField *field)
2703 MonoClass *class, *gtd;
2704 MonoDynamicGenericClass *dgclass;
2705 int field_index;
2707 g_assert (is_field_on_inst (field));
2709 dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2711 if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
2712 field_index = field - dgclass->fields;
2713 return dgclass->field_generic_types [field_index];
2716 class = field->parent;
2717 gtd = class->generic_class->container_class;
2719 if (field >= class->fields && field - class->fields < class->field.count) {
2720 field_index = field - class->fields;
2721 return gtd->fields [field_index].type;
2724 g_assert_not_reached ();
2725 return 0;
2728 #ifndef DISABLE_REFLECTION_EMIT
2729 static guint32
2730 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
2732 MonoType *type;
2733 guint32 token;
2735 g_assert (field);
2736 g_assert (field->parent);
2738 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2739 if (token)
2740 return token;
2742 if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2743 int index = field - field->parent->fields;
2744 type = field->parent->generic_class->container_class->fields [index].type;
2745 } else {
2746 if (is_field_on_inst (field))
2747 type = get_field_on_inst_generic_type (field);
2748 else
2749 type = mono_field_get_type (field);
2751 token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
2752 mono_field_get_name (field),
2753 fieldref_encode_signature (assembly, field->parent->image, type));
2754 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
2755 return token;
2758 static guint32
2759 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
2761 guint32 token;
2762 MonoClass *klass;
2763 MonoGenericClass *gclass;
2764 MonoDynamicGenericClass *dgclass;
2765 MonoType *type;
2766 char *name;
2768 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2769 if (token)
2770 return token;
2771 if (is_sre_field_builder (mono_object_class (f->fb))) {
2772 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
2773 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2774 klass = mono_class_from_mono_type (type);
2775 gclass = type->data.generic_class;
2776 g_assert (gclass->is_dynamic);
2777 dgclass = (MonoDynamicGenericClass *) gclass;
2779 name = mono_string_to_utf8 (fb->name);
2780 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name,
2781 field_encode_signature (assembly, fb));
2782 g_free (name);
2783 } else if (is_sr_mono_field (mono_object_class (f->fb))) {
2784 guint32 sig;
2785 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
2787 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2788 klass = mono_class_from_mono_type (type);
2790 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
2791 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
2792 } else {
2793 char *name = mono_type_get_full_name (mono_object_class (f->fb));
2794 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
2797 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
2798 return token;
2801 static guint32
2802 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
2804 guint32 sig, token;
2805 MonoClass *klass;
2806 MonoGenericClass *gclass;
2807 MonoType *type;
2809 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
2811 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
2812 if (token)
2813 return token;
2815 if (is_sre_ctor_builder (mono_object_class (c->cb))) {
2816 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
2817 MonoDynamicGenericClass *dgclass;
2818 ReflectionMethodBuilder rmb;
2819 char *name;
2821 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2822 klass = mono_class_from_mono_type (type);
2824 gclass = type->data.generic_class;
2825 g_assert (gclass->is_dynamic);
2826 dgclass = (MonoDynamicGenericClass *) gclass;
2828 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
2830 name = mono_string_to_utf8 (rmb.name);
2832 sig = method_builder_encode_signature (assembly, &rmb);
2834 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2835 g_free (name);
2836 } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
2837 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
2839 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2840 klass = mono_class_from_mono_type (type);
2842 sig = method_encode_signature (assembly, mono_method_signature (mm));
2843 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2844 } else {
2845 char *name = mono_type_get_full_name (mono_object_class (c->cb));
2846 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2850 mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
2851 return token;
2854 static MonoMethod*
2855 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m)
2857 MonoClass *klass;
2858 MonoGenericContext tmp_context;
2859 MonoType **type_argv;
2860 MonoGenericInst *ginst;
2861 MonoMethod *method, *inflated;
2862 int count, i;
2864 init_type_builder_generics ((MonoObject*)m->inst);
2866 method = inflate_method (m->inst, (MonoObject*)m->mb);
2868 klass = method->klass;
2870 if (m->method_args == NULL)
2871 return method;
2873 if (method->is_inflated)
2874 method = ((MonoMethodInflated *) method)->declaring;
2876 count = mono_array_length (m->method_args);
2878 type_argv = g_new0 (MonoType *, count);
2879 for (i = 0; i < count; i++) {
2880 MonoReflectionType *garg = mono_array_get (m->method_args, gpointer, i);
2881 type_argv [i] = mono_reflection_type_get_handle (garg);
2883 ginst = mono_metadata_get_generic_inst (count, type_argv);
2884 g_free (type_argv);
2886 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
2887 tmp_context.method_inst = ginst;
2889 inflated = mono_class_inflate_generic_method (method, &tmp_context);
2890 return inflated;
2893 static guint32
2894 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
2896 guint32 sig, token = 0;
2897 MonoType *type;
2898 MonoClass *klass;
2900 if (m->method_args) {
2901 MonoMethod *inflated;
2903 inflated = mono_reflection_method_on_tb_inst_get_handle (m);
2904 if (create_methodspec)
2905 token = mono_image_get_methodspec_token (assembly, inflated);
2906 else
2907 token = mono_image_get_inflated_method_token (assembly, inflated);
2908 return token;
2911 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
2912 if (token)
2913 return token;
2915 if (is_sre_method_builder (mono_object_class (m->mb))) {
2916 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
2917 MonoGenericClass *gclass;
2918 ReflectionMethodBuilder rmb;
2919 char *name;
2921 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2922 klass = mono_class_from_mono_type (type);
2923 gclass = type->data.generic_class;
2924 g_assert (gclass->is_dynamic);
2926 reflection_methodbuilder_from_method_builder (&rmb, mb);
2928 name = mono_string_to_utf8 (rmb.name);
2930 sig = method_builder_encode_signature (assembly, &rmb);
2932 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2933 g_free (name);
2934 } else if (is_sr_mono_method (mono_object_class (m->mb))) {
2935 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
2937 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2938 klass = mono_class_from_mono_type (type);
2940 sig = method_encode_signature (assembly, mono_method_signature (mm));
2941 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2942 } else {
2943 char *name = mono_type_get_full_name (mono_object_class (m->mb));
2944 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2947 mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
2948 return token;
2951 static guint32
2952 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
2954 SigBuffer buf;
2955 int i;
2956 guint32 nparams = context->method_inst->type_argc;
2957 guint32 idx;
2959 if (!assembly->save)
2960 return 0;
2962 sigbuffer_init (&buf, 32);
2964 * FIXME: vararg, explicit_this, differenc call_conv values...
2966 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
2967 sigbuffer_add_value (&buf, nparams);
2969 for (i = 0; i < nparams; i++)
2970 encode_type (assembly, context->method_inst->type_argv [i], &buf);
2972 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2973 sigbuffer_free (&buf);
2974 return idx;
2977 static guint32
2978 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2980 MonoDynamicTable *table;
2981 guint32 *values;
2982 guint32 token, mtoken = 0, sig;
2983 MonoMethodInflated *imethod;
2984 MonoMethod *declaring;
2986 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2988 g_assert (method->is_inflated);
2989 imethod = (MonoMethodInflated *) method;
2990 declaring = imethod->declaring;
2992 sig = method_encode_signature (assembly, mono_method_signature (declaring));
2993 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2995 if (!mono_method_signature (declaring)->generic_param_count)
2996 return mtoken;
2998 switch (mono_metadata_token_table (mtoken)) {
2999 case MONO_TABLE_MEMBERREF:
3000 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3001 break;
3002 case MONO_TABLE_METHOD:
3003 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3004 break;
3005 default:
3006 g_assert_not_reached ();
3009 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3011 if (assembly->save) {
3012 alloc_table (table, table->rows + 1);
3013 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3014 values [MONO_METHODSPEC_METHOD] = mtoken;
3015 values [MONO_METHODSPEC_SIGNATURE] = sig;
3018 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3019 table->next_idx ++;
3021 return token;
3024 static guint32
3025 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3027 MonoMethodInflated *imethod;
3028 guint32 token;
3030 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3031 if (token)
3032 return token;
3034 g_assert (method->is_inflated);
3035 imethod = (MonoMethodInflated *) method;
3037 if (mono_method_signature (imethod->declaring)->generic_param_count) {
3038 token = method_encode_methodspec (assembly, method);
3039 } else {
3040 guint32 sig = method_encode_signature (
3041 assembly, mono_method_signature (imethod->declaring));
3042 token = mono_image_get_memberref_token (
3043 assembly, &method->klass->byval_arg, method->name, sig);
3046 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3047 return token;
3050 static guint32
3051 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3053 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3054 guint32 sig, token;
3056 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3057 token = mono_image_get_memberref_token (
3058 assembly, &m->klass->byval_arg, m->name, sig);
3060 return token;
3063 static guint32
3064 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
3066 MonoDynamicTable *table;
3067 MonoClass *klass;
3068 MonoType *type;
3069 guint32 *values;
3070 guint32 token;
3071 SigBuffer buf;
3072 int count, i;
3075 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3076 * ie. what we'd normally use as the generic type in a TypeSpec signature.
3077 * Because of this, we must not insert it into the `typeref' hash table.
3079 type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
3080 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3081 if (token)
3082 return token;
3084 sigbuffer_init (&buf, 32);
3086 g_assert (tb->generic_params);
3087 klass = mono_class_from_mono_type (type);
3089 if (tb->generic_container)
3090 mono_reflection_create_generic_class (tb);
3092 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3093 g_assert (klass->generic_container);
3094 sigbuffer_add_value (&buf, klass->byval_arg.type);
3095 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3097 count = mono_array_length (tb->generic_params);
3098 sigbuffer_add_value (&buf, count);
3099 for (i = 0; i < count; i++) {
3100 MonoReflectionGenericParam *gparam;
3102 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3104 encode_type (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)gparam), &buf);
3107 table = &assembly->tables [MONO_TABLE_TYPESPEC];
3109 if (assembly->save) {
3110 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3111 alloc_table (table, table->rows + 1);
3112 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3113 values [MONO_TYPESPEC_SIGNATURE] = token;
3115 sigbuffer_free (&buf);
3117 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3118 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3119 table->next_idx ++;
3120 return token;
3124 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3126 static MonoType*
3127 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
3129 int i, count, len, pos;
3130 MonoType *t;
3132 count = 0;
3133 if (modreq)
3134 count += mono_array_length (modreq);
3135 if (modopt)
3136 count += mono_array_length (modopt);
3138 if (count == 0)
3139 return mono_metadata_type_dup (NULL, type);
3141 len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3142 t = g_malloc (len);
3143 memcpy (t, type, MONO_SIZEOF_TYPE);
3145 t->num_mods = count;
3146 pos = 0;
3147 if (modreq) {
3148 for (i = 0; i < mono_array_length (modreq); ++i) {
3149 MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
3150 t->modifiers [pos].required = 1;
3151 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3152 pos ++;
3155 if (modopt) {
3156 for (i = 0; i < mono_array_length (modopt); ++i) {
3157 MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
3158 t->modifiers [pos].required = 0;
3159 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3160 pos ++;
3164 return t;
3167 static void
3168 init_type_builder_generics (MonoObject *type)
3170 MonoReflectionTypeBuilder *tb;
3172 if (!is_sre_type_builder(mono_object_class (type)))
3173 return;
3174 tb = (MonoReflectionTypeBuilder *)type;
3176 if (tb && tb->generic_container)
3177 mono_reflection_create_generic_class (tb);
3180 static guint32
3181 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3183 MonoDynamicTable *table;
3184 MonoClass *klass;
3185 MonoType *custom = NULL, *type;
3186 guint32 *values;
3187 guint32 token, pclass, parent, sig;
3188 gchar *name;
3190 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3191 if (token)
3192 return token;
3194 klass = mono_class_from_mono_type (mono_reflection_type_get_handle (fb->typeb));
3195 name = mono_string_to_utf8 (fb->name);
3197 /*FIXME this is one more layer of ugliness due how types are created.*/
3198 init_type_builder_generics (fb->type);
3200 /* fb->type does not include the custom modifiers */
3201 /* FIXME: We should do this in one place when a fieldbuilder is created */
3202 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
3203 if (fb->modreq || fb->modopt)
3204 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt);
3206 sig = fieldref_encode_signature (assembly, NULL, type);
3207 g_free (custom);
3209 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3210 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3212 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3213 parent >>= MONO_TYPEDEFORREF_BITS;
3215 table = &assembly->tables [MONO_TABLE_MEMBERREF];
3217 if (assembly->save) {
3218 alloc_table (table, table->rows + 1);
3219 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3220 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3221 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3222 values [MONO_MEMBERREF_SIGNATURE] = sig;
3225 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3226 table->next_idx ++;
3227 mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3228 g_free (name);
3229 return token;
3232 static guint32
3233 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3235 SigBuffer buf;
3236 guint32 nargs;
3237 guint32 size;
3238 guint32 i, idx;
3240 if (!assembly->save)
3241 return 0;
3243 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3244 g_assert (helper->type == 2);
3246 if (helper->arguments)
3247 nargs = mono_array_length (helper->arguments);
3248 else
3249 nargs = 0;
3251 size = 10 + (nargs * 10);
3253 sigbuffer_init (&buf, 32);
3255 /* Encode calling convention */
3256 /* Change Any to Standard */
3257 if ((helper->call_conv & 0x03) == 0x03)
3258 helper->call_conv = 0x01;
3259 /* explicit_this implies has_this */
3260 if (helper->call_conv & 0x40)
3261 helper->call_conv &= 0x20;
3263 if (helper->call_conv == 0) { /* Unmanaged */
3264 idx = helper->unmanaged_call_conv - 1;
3265 } else {
3266 /* Managed */
3267 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3268 if (helper->call_conv & 0x02) /* varargs */
3269 idx += 0x05;
3272 sigbuffer_add_byte (&buf, idx);
3273 sigbuffer_add_value (&buf, nargs);
3274 encode_reflection_type (assembly, helper->return_type, &buf);
3275 for (i = 0; i < nargs; ++i) {
3276 MonoArray *modreqs = NULL;
3277 MonoArray *modopts = NULL;
3278 MonoReflectionType *pt;
3280 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3281 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3282 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3283 modopts = mono_array_get (helper->modopts, MonoArray*, i);
3285 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3286 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3287 encode_reflection_type (assembly, pt, &buf);
3289 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3290 sigbuffer_free (&buf);
3292 return idx;
3295 static guint32
3296 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3298 guint32 idx;
3299 MonoDynamicTable *table;
3300 guint32 *values;
3302 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3303 idx = table->next_idx ++;
3304 table->rows ++;
3305 alloc_table (table, table->rows);
3306 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3308 values [MONO_STAND_ALONE_SIGNATURE] =
3309 mono_reflection_encode_sighelper (assembly, helper);
3311 return idx;
3314 static int
3315 reflection_cc_to_file (int call_conv) {
3316 switch (call_conv & 0x3) {
3317 case 0:
3318 case 1: return MONO_CALL_DEFAULT;
3319 case 2: return MONO_CALL_VARARG;
3320 default:
3321 g_assert_not_reached ();
3323 return 0;
3325 #endif /* !DISABLE_REFLECTION_EMIT */
3327 typedef struct {
3328 MonoType *parent;
3329 MonoMethodSignature *sig;
3330 char *name;
3331 guint32 token;
3332 } ArrayMethod;
3334 #ifndef DISABLE_REFLECTION_EMIT
3335 static guint32
3336 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3338 guint32 nparams, i;
3339 GList *tmp;
3340 char *name;
3341 MonoMethodSignature *sig;
3342 ArrayMethod *am;
3343 MonoType *mtype;
3345 name = mono_string_to_utf8 (m->name);
3346 nparams = mono_array_length (m->parameters);
3347 sig = g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3348 sig->hasthis = 1;
3349 sig->sentinelpos = -1;
3350 sig->call_convention = reflection_cc_to_file (m->call_conv);
3351 sig->param_count = nparams;
3352 sig->ret = m->ret ? mono_reflection_type_get_handle (m->ret): &mono_defaults.void_class->byval_arg;
3353 mtype = mono_reflection_type_get_handle (m->parent);
3354 for (i = 0; i < nparams; ++i)
3355 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i);
3357 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3358 am = tmp->data;
3359 if (strcmp (name, am->name) == 0 &&
3360 mono_metadata_type_equal (am->parent, mtype) &&
3361 mono_metadata_signature_equal (am->sig, sig)) {
3362 g_free (name);
3363 g_free (sig);
3364 m->table_idx = am->token & 0xffffff;
3365 return am->token;
3368 am = g_new0 (ArrayMethod, 1);
3369 am->name = name;
3370 am->sig = sig;
3371 am->parent = mtype;
3372 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3373 method_encode_signature (assembly, sig));
3374 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3375 m->table_idx = am->token & 0xffffff;
3376 return am->token;
3380 * Insert into the metadata tables all the info about the TypeBuilder tb.
3381 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3383 static void
3384 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3386 MonoDynamicTable *table;
3387 guint *values;
3388 int i, is_object = 0, is_system = 0;
3389 char *n;
3391 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3392 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3393 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3394 n = mono_string_to_utf8 (tb->name);
3395 if (strcmp (n, "Object") == 0)
3396 is_object++;
3397 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3398 g_free (n);
3399 n = mono_string_to_utf8 (tb->nspace);
3400 if (strcmp (n, "System") == 0)
3401 is_system++;
3402 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3403 g_free (n);
3404 if (tb->parent && !(is_system && is_object) &&
3405 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3406 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
3407 } else {
3408 values [MONO_TYPEDEF_EXTENDS] = 0;
3410 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3411 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3414 * if we have explicitlayout or sequentiallayouts, output data in the
3415 * ClassLayout table.
3417 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3418 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3419 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3420 table->rows++;
3421 alloc_table (table, table->rows);
3422 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3423 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3424 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3425 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3428 /* handle interfaces */
3429 if (tb->interfaces) {
3430 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3431 i = table->rows;
3432 table->rows += mono_array_length (tb->interfaces);
3433 alloc_table (table, table->rows);
3434 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3435 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3436 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3437 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3438 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (iface));
3439 values += MONO_INTERFACEIMPL_SIZE;
3443 /* handle fields */
3444 if (tb->fields) {
3445 table = &assembly->tables [MONO_TABLE_FIELD];
3446 table->rows += tb->num_fields;
3447 alloc_table (table, table->rows);
3448 for (i = 0; i < tb->num_fields; ++i)
3449 mono_image_get_field_info (
3450 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3453 /* handle constructors */
3454 if (tb->ctors) {
3455 table = &assembly->tables [MONO_TABLE_METHOD];
3456 table->rows += mono_array_length (tb->ctors);
3457 alloc_table (table, table->rows);
3458 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3459 mono_image_get_ctor_info (domain,
3460 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3463 /* handle methods */
3464 if (tb->methods) {
3465 table = &assembly->tables [MONO_TABLE_METHOD];
3466 table->rows += tb->num_methods;
3467 alloc_table (table, table->rows);
3468 for (i = 0; i < tb->num_methods; ++i)
3469 mono_image_get_method_info (
3470 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3473 /* Do the same with properties etc.. */
3474 if (tb->events && mono_array_length (tb->events)) {
3475 table = &assembly->tables [MONO_TABLE_EVENT];
3476 table->rows += mono_array_length (tb->events);
3477 alloc_table (table, table->rows);
3478 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3479 table->rows ++;
3480 alloc_table (table, table->rows);
3481 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3482 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3483 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3484 for (i = 0; i < mono_array_length (tb->events); ++i)
3485 mono_image_get_event_info (
3486 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3488 if (tb->properties && mono_array_length (tb->properties)) {
3489 table = &assembly->tables [MONO_TABLE_PROPERTY];
3490 table->rows += mono_array_length (tb->properties);
3491 alloc_table (table, table->rows);
3492 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3493 table->rows ++;
3494 alloc_table (table, table->rows);
3495 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3496 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3497 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3498 for (i = 0; i < mono_array_length (tb->properties); ++i)
3499 mono_image_get_property_info (
3500 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3503 /* handle generic parameters */
3504 if (tb->generic_params) {
3505 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3506 table->rows += mono_array_length (tb->generic_params);
3507 alloc_table (table, table->rows);
3508 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3509 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3511 mono_image_get_generic_param_info (
3512 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3516 mono_image_add_decl_security (assembly,
3517 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3519 if (tb->subtypes) {
3520 MonoDynamicTable *ntable;
3522 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3523 ntable->rows += mono_array_length (tb->subtypes);
3524 alloc_table (ntable, ntable->rows);
3525 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3527 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3528 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3530 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3531 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3532 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3533 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3534 mono_string_to_utf8 (tb->name), tb->table_idx,
3535 ntable->next_idx, ntable->rows);*/
3536 values += MONO_NESTED_CLASS_SIZE;
3537 ntable->next_idx++;
3541 #endif
3543 static void
3544 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
3546 int i;
3548 mono_ptr_array_append (*types, type);
3550 if (!type->subtypes)
3551 return;
3553 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3554 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3555 collect_types (types, subtype);
3559 static gint
3560 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3562 if ((*type1)->table_idx < (*type2)->table_idx)
3563 return -1;
3564 else
3565 if ((*type1)->table_idx > (*type2)->table_idx)
3566 return 1;
3567 else
3568 return 0;
3571 static void
3572 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3573 int i;
3575 if (!pinfo)
3576 return;
3577 for (i = 0; i < mono_array_length (pinfo); ++i) {
3578 MonoReflectionParamBuilder *pb;
3579 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3580 if (!pb)
3581 continue;
3582 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3586 static void
3587 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3588 int i;
3590 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3591 if (tb->fields) {
3592 for (i = 0; i < tb->num_fields; ++i) {
3593 MonoReflectionFieldBuilder* fb;
3594 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3595 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3598 if (tb->events) {
3599 for (i = 0; i < mono_array_length (tb->events); ++i) {
3600 MonoReflectionEventBuilder* eb;
3601 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3602 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3605 if (tb->properties) {
3606 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3607 MonoReflectionPropertyBuilder* pb;
3608 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3609 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3612 if (tb->ctors) {
3613 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3614 MonoReflectionCtorBuilder* cb;
3615 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3616 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3617 params_add_cattrs (assembly, cb->pinfo);
3621 if (tb->methods) {
3622 for (i = 0; i < tb->num_methods; ++i) {
3623 MonoReflectionMethodBuilder* mb;
3624 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3625 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3626 params_add_cattrs (assembly, mb->pinfo);
3630 if (tb->subtypes) {
3631 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3632 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3636 static void
3637 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3639 int i;
3641 mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3643 if (moduleb->global_methods) {
3644 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3645 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3646 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3647 params_add_cattrs (assembly, mb->pinfo);
3651 if (moduleb->global_fields) {
3652 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3653 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3654 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3658 if (moduleb->types) {
3659 for (i = 0; i < moduleb->num_types; ++i)
3660 type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3664 static void
3665 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3667 MonoDynamicTable *table;
3668 guint32 *values;
3669 char blob_size [6];
3670 guchar hash [20];
3671 char *b = blob_size;
3672 char *dir, *path;
3674 table = &assembly->tables [MONO_TABLE_FILE];
3675 table->rows++;
3676 alloc_table (table, table->rows);
3677 values = table->values + table->next_idx * MONO_FILE_SIZE;
3678 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3679 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3680 if (module->image->dynamic) {
3681 /* This depends on the fact that the main module is emitted last */
3682 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3683 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3684 } else {
3685 dir = NULL;
3686 path = g_strdup (module->image->name);
3688 mono_sha1_get_digest_from_file (path, hash);
3689 g_free (dir);
3690 g_free (path);
3691 mono_metadata_encode_value (20, b, &b);
3692 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3693 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3694 table->next_idx ++;
3697 static void
3698 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3700 MonoDynamicTable *table;
3701 int i;
3703 table = &assembly->tables [MONO_TABLE_MODULE];
3704 mb->table_idx = table->next_idx ++;
3705 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3706 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3707 i /= 16;
3708 ++i;
3709 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3710 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3711 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3712 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3715 static guint32
3716 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3717 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3719 MonoDynamicTable *table;
3720 guint32 *values;
3721 guint32 visib, res;
3723 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3724 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3725 return 0;
3727 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3728 table->rows++;
3729 alloc_table (table, table->rows);
3730 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3732 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3733 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3734 if (klass->nested_in)
3735 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3736 else
3737 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3738 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3739 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3741 res = table->next_idx;
3743 table->next_idx ++;
3745 /* Emit nested types */
3746 if (klass->ext && klass->ext->nested_classes) {
3747 GList *tmp;
3749 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
3750 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3753 return res;
3756 static void
3757 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3758 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3760 MonoClass *klass;
3761 guint32 idx, i;
3763 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
3765 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3767 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3768 parent_index, assembly);
3771 * Emit nested types
3772 * We need to do this ourselves since klass->nested_classes is not set up.
3774 if (tb->subtypes) {
3775 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3776 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3780 static void
3781 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3782 guint32 module_index, MonoDynamicImage *assembly)
3784 MonoImage *image = module->image;
3785 MonoTableInfo *t;
3786 guint32 i;
3788 t = &image->tables [MONO_TABLE_TYPEDEF];
3790 for (i = 0; i < t->rows; ++i) {
3791 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3793 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3794 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3798 static void
3799 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
3801 MonoDynamicTable *table;
3802 guint32 *values;
3803 guint32 scope, scope_idx, impl, current_idx;
3804 gboolean forwarder = TRUE;
3805 gpointer iter = NULL;
3806 MonoClass *nested;
3808 if (klass->nested_in) {
3809 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3810 forwarder = FALSE;
3811 } else {
3812 scope = resolution_scope_from_image (assembly, klass->image);
3813 g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3814 scope_idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3815 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3818 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3820 table->rows++;
3821 alloc_table (table, table->rows);
3822 current_idx = table->next_idx;
3823 values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
3825 values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
3826 values [MONO_EXP_TYPE_TYPEDEF] = 0;
3827 values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
3828 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3829 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3831 table->next_idx++;
3833 while ((nested = mono_class_get_nested_types (klass, &iter)))
3834 add_exported_type (assemblyb, assembly, nested, current_idx);
3837 static void
3838 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3840 MonoClass *klass;
3841 int i;
3843 if (!assemblyb->type_forwarders)
3844 return;
3846 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3847 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
3848 MonoType *type;
3849 if (!t)
3850 continue;
3852 type = mono_reflection_type_get_handle (t);
3853 g_assert (type);
3855 klass = mono_class_from_mono_type (type);
3857 add_exported_type (assemblyb, assembly, klass, 0);
3861 #define align_pointer(base,p)\
3862 do {\
3863 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3864 if (__diff & 3)\
3865 (p) += 4 - (__diff & 3);\
3866 } while (0)
3868 static int
3869 compare_constants (const void *a, const void *b)
3871 const guint32 *a_values = a;
3872 const guint32 *b_values = b;
3873 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3876 static int
3877 compare_semantics (const void *a, const void *b)
3879 const guint32 *a_values = a;
3880 const guint32 *b_values = b;
3881 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3882 if (assoc)
3883 return assoc;
3884 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3887 static int
3888 compare_custom_attrs (const void *a, const void *b)
3890 const guint32 *a_values = a;
3891 const guint32 *b_values = b;
3893 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3896 static int
3897 compare_field_marshal (const void *a, const void *b)
3899 const guint32 *a_values = a;
3900 const guint32 *b_values = b;
3902 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3905 static int
3906 compare_nested (const void *a, const void *b)
3908 const guint32 *a_values = a;
3909 const guint32 *b_values = b;
3911 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3914 static int
3915 compare_genericparam (const void *a, const void *b)
3917 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3918 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3920 if ((*b_entry)->owner == (*a_entry)->owner)
3921 return
3922 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam)) -
3923 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam));
3924 else
3925 return (*a_entry)->owner - (*b_entry)->owner;
3928 static int
3929 compare_declsecurity_attrs (const void *a, const void *b)
3931 const guint32 *a_values = a;
3932 const guint32 *b_values = b;
3934 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3937 static int
3938 compare_interface_impl (const void *a, const void *b)
3940 const guint32 *a_values = a;
3941 const guint32 *b_values = b;
3943 int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
3944 if (klass)
3945 return klass;
3947 return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
3950 static void
3951 pad_heap (MonoDynamicStream *sh)
3953 if (sh->index & 3) {
3954 int sz = 4 - (sh->index & 3);
3955 memset (sh->data + sh->index, 0, sz);
3956 sh->index += sz;
3960 struct StreamDesc {
3961 const char *name;
3962 MonoDynamicStream *stream;
3966 * build_compressed_metadata() fills in the blob of data that represents the
3967 * raw metadata as it will be saved in the PE file. The five streams are output
3968 * and the metadata tables are comnpressed from the guint32 array representation,
3969 * to the compressed on-disk format.
3971 static void
3972 build_compressed_metadata (MonoDynamicImage *assembly)
3974 MonoDynamicTable *table;
3975 int i;
3976 guint64 valid_mask = 0;
3977 guint64 sorted_mask;
3978 guint32 heapt_size = 0;
3979 guint32 meta_size = 256; /* allow for header and other stuff */
3980 guint32 table_offset;
3981 guint32 ntables = 0;
3982 guint64 *int64val;
3983 guint32 *int32val;
3984 guint16 *int16val;
3985 MonoImage *meta;
3986 unsigned char *p;
3987 struct StreamDesc stream_desc [5];
3989 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3990 for (i = 0; i < assembly->gen_params->len; i++){
3991 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3992 write_generic_param_entry (assembly, entry);
3995 stream_desc [0].name = "#~";
3996 stream_desc [0].stream = &assembly->tstream;
3997 stream_desc [1].name = "#Strings";
3998 stream_desc [1].stream = &assembly->sheap;
3999 stream_desc [2].name = "#US";
4000 stream_desc [2].stream = &assembly->us;
4001 stream_desc [3].name = "#Blob";
4002 stream_desc [3].stream = &assembly->blob;
4003 stream_desc [4].name = "#GUID";
4004 stream_desc [4].stream = &assembly->guid;
4006 /* tables that are sorted */
4007 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4008 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4009 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4010 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4011 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4012 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4013 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4015 /* Compute table sizes */
4016 /* the MonoImage has already been created in mono_image_basic_init() */
4017 meta = &assembly->image;
4019 /* sizes should be multiple of 4 */
4020 pad_heap (&assembly->blob);
4021 pad_heap (&assembly->guid);
4022 pad_heap (&assembly->sheap);
4023 pad_heap (&assembly->us);
4025 /* Setup the info used by compute_sizes () */
4026 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4027 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4028 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4030 meta_size += assembly->blob.index;
4031 meta_size += assembly->guid.index;
4032 meta_size += assembly->sheap.index;
4033 meta_size += assembly->us.index;
4035 for (i=0; i < MONO_TABLE_NUM; ++i)
4036 meta->tables [i].rows = assembly->tables [i].rows;
4038 for (i = 0; i < MONO_TABLE_NUM; i++){
4039 if (meta->tables [i].rows == 0)
4040 continue;
4041 valid_mask |= (guint64)1 << i;
4042 ntables ++;
4043 meta->tables [i].row_size = mono_metadata_compute_size (
4044 meta, i, &meta->tables [i].size_bitfield);
4045 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4047 heapt_size += 24; /* #~ header size */
4048 heapt_size += ntables * 4;
4049 /* make multiple of 4 */
4050 heapt_size += 3;
4051 heapt_size &= ~3;
4052 meta_size += heapt_size;
4053 meta->raw_metadata = g_malloc0 (meta_size);
4054 p = (unsigned char*)meta->raw_metadata;
4055 /* the metadata signature */
4056 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4057 /* version numbers and 4 bytes reserved */
4058 int16val = (guint16*)p;
4059 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4060 *int16val = GUINT16_TO_LE (meta->md_version_minor);
4061 p += 8;
4062 /* version string */
4063 int32val = (guint32*)p;
4064 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4065 p += 4;
4066 memcpy (p, meta->version, strlen (meta->version));
4067 p += GUINT32_FROM_LE (*int32val);
4068 align_pointer (meta->raw_metadata, p);
4069 int16val = (guint16*)p;
4070 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4071 *int16val = GUINT16_TO_LE (5); /* number of streams */
4072 p += 4;
4075 * write the stream info.
4077 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4078 table_offset += 3; table_offset &= ~3;
4080 assembly->tstream.index = heapt_size;
4081 for (i = 0; i < 5; ++i) {
4082 int32val = (guint32*)p;
4083 stream_desc [i].stream->offset = table_offset;
4084 *int32val++ = GUINT32_TO_LE (table_offset);
4085 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4086 table_offset += GUINT32_FROM_LE (*int32val);
4087 table_offset += 3; table_offset &= ~3;
4088 p += 8;
4089 strcpy ((char*)p, stream_desc [i].name);
4090 p += strlen (stream_desc [i].name) + 1;
4091 align_pointer (meta->raw_metadata, p);
4094 * now copy the data, the table stream header and contents goes first.
4096 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4097 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4098 int32val = (guint32*)p;
4099 *int32val = GUINT32_TO_LE (0); /* reserved */
4100 p += 4;
4102 *p++ = 2; /* version */
4103 *p++ = 0;
4105 if (meta->idx_string_wide)
4106 *p |= 0x01;
4107 if (meta->idx_guid_wide)
4108 *p |= 0x02;
4109 if (meta->idx_blob_wide)
4110 *p |= 0x04;
4111 ++p;
4112 *p++ = 1; /* reserved */
4113 int64val = (guint64*)p;
4114 *int64val++ = GUINT64_TO_LE (valid_mask);
4115 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
4116 p += 16;
4117 int32val = (guint32*)p;
4118 for (i = 0; i < MONO_TABLE_NUM; i++){
4119 if (meta->tables [i].rows == 0)
4120 continue;
4121 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4123 p = (unsigned char*)int32val;
4125 /* sort the tables that still need sorting */
4126 table = &assembly->tables [MONO_TABLE_CONSTANT];
4127 if (table->rows)
4128 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4129 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4130 if (table->rows)
4131 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4132 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4133 if (table->rows)
4134 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4135 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4136 if (table->rows)
4137 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4138 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4139 if (table->rows)
4140 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4141 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4142 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4143 if (table->rows)
4144 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4145 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4146 if (table->rows)
4147 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4149 /* compress the tables */
4150 for (i = 0; i < MONO_TABLE_NUM; i++){
4151 int row, col;
4152 guint32 *values;
4153 guint32 bitfield = meta->tables [i].size_bitfield;
4154 if (!meta->tables [i].rows)
4155 continue;
4156 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4157 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4158 meta->tables [i].base = (char*)p;
4159 for (row = 1; row <= meta->tables [i].rows; ++row) {
4160 values = assembly->tables [i].values + row * assembly->tables [i].columns;
4161 for (col = 0; col < assembly->tables [i].columns; ++col) {
4162 switch (mono_metadata_table_size (bitfield, col)) {
4163 case 1:
4164 *p++ = values [col];
4165 break;
4166 case 2:
4167 *p++ = values [col] & 0xff;
4168 *p++ = (values [col] >> 8) & 0xff;
4169 break;
4170 case 4:
4171 *p++ = values [col] & 0xff;
4172 *p++ = (values [col] >> 8) & 0xff;
4173 *p++ = (values [col] >> 16) & 0xff;
4174 *p++ = (values [col] >> 24) & 0xff;
4175 break;
4176 default:
4177 g_assert_not_reached ();
4181 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4184 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4185 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4186 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4187 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4188 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4190 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4194 * Some tables in metadata need to be sorted according to some criteria, but
4195 * when methods and fields are first created with reflection, they may be assigned a token
4196 * that doesn't correspond to the final token they will get assigned after the sorting.
4197 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4198 * with the reflection objects that represent them. Once all the tables are set up, the
4199 * reflection objects will contains the correct table index. fixup_method() will fixup the
4200 * tokens for the method with ILGenerator @ilgen.
4202 static void
4203 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4205 guint32 code_idx = GPOINTER_TO_UINT (value);
4206 MonoReflectionILTokenInfo *iltoken;
4207 MonoReflectionFieldBuilder *field;
4208 MonoReflectionCtorBuilder *ctor;
4209 MonoReflectionMethodBuilder *method;
4210 MonoReflectionTypeBuilder *tb;
4211 MonoReflectionArrayMethod *am;
4212 guint32 i, idx = 0;
4213 unsigned char *target;
4215 for (i = 0; i < ilgen->num_token_fixups; ++i) {
4216 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4217 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4218 switch (target [3]) {
4219 case MONO_TABLE_FIELD:
4220 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4221 field = (MonoReflectionFieldBuilder *)iltoken->member;
4222 idx = field->table_idx;
4223 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4224 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4225 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4226 } else {
4227 g_assert_not_reached ();
4229 break;
4230 case MONO_TABLE_METHOD:
4231 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4232 method = (MonoReflectionMethodBuilder *)iltoken->member;
4233 idx = method->table_idx;
4234 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4235 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4236 idx = ctor->table_idx;
4237 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4238 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4239 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4240 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4241 } else {
4242 g_assert_not_reached ();
4244 break;
4245 case MONO_TABLE_TYPEDEF:
4246 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4247 g_assert_not_reached ();
4248 tb = (MonoReflectionTypeBuilder *)iltoken->member;
4249 idx = tb->table_idx;
4250 break;
4251 case MONO_TABLE_MEMBERREF:
4252 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4253 am = (MonoReflectionArrayMethod*)iltoken->member;
4254 idx = am->table_idx;
4255 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4256 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4257 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4258 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4259 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4260 g_assert (m->klass->generic_class || m->klass->generic_container);
4261 continue;
4262 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4263 continue;
4264 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4265 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4266 g_assert (is_field_on_inst (f));
4267 continue;
4268 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4269 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4270 continue;
4271 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4272 continue;
4273 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4274 continue;
4275 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4276 continue;
4277 } else {
4278 g_assert_not_reached ();
4280 break;
4281 case MONO_TABLE_METHODSPEC:
4282 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4283 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4284 g_assert (mono_method_signature (m)->generic_param_count);
4285 continue;
4286 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4287 continue;
4288 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4289 continue;
4290 } else {
4291 g_assert_not_reached ();
4293 break;
4294 default:
4295 g_error ("got unexpected table 0x%02x in fixup", target [3]);
4297 target [0] = idx & 0xff;
4298 target [1] = (idx >> 8) & 0xff;
4299 target [2] = (idx >> 16) & 0xff;
4304 * fixup_cattrs:
4306 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4307 * value is not known when the table is emitted.
4309 static void
4310 fixup_cattrs (MonoDynamicImage *assembly)
4312 MonoDynamicTable *table;
4313 guint32 *values;
4314 guint32 type, i, idx, token;
4315 MonoObject *ctor;
4317 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4319 for (i = 0; i < table->rows; ++i) {
4320 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4322 type = values [MONO_CUSTOM_ATTR_TYPE];
4323 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4324 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4325 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4326 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4327 g_assert (ctor);
4329 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")|| !strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4330 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4331 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4332 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4338 static void
4339 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4341 MonoDynamicTable *table;
4342 guint32 *values;
4344 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4345 table->rows++;
4346 alloc_table (table, table->rows);
4347 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4348 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4349 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4350 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4351 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4352 table->next_idx++;
4355 static void
4356 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4358 MonoDynamicTable *table;
4359 guint32 *values;
4360 char blob_size [6];
4361 guchar hash [20];
4362 char *b = blob_size;
4363 char *name, *sname;
4364 guint32 idx, offset;
4366 if (rsrc->filename) {
4367 name = mono_string_to_utf8 (rsrc->filename);
4368 sname = g_path_get_basename (name);
4370 table = &assembly->tables [MONO_TABLE_FILE];
4371 table->rows++;
4372 alloc_table (table, table->rows);
4373 values = table->values + table->next_idx * MONO_FILE_SIZE;
4374 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4375 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4376 g_free (sname);
4378 mono_sha1_get_digest_from_file (name, hash);
4379 mono_metadata_encode_value (20, b, &b);
4380 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4381 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4382 g_free (name);
4383 idx = table->next_idx++;
4384 rsrc->offset = 0;
4385 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4386 } else {
4387 char sizebuf [4];
4388 char *data;
4389 guint len;
4390 if (rsrc->data) {
4391 data = mono_array_addr (rsrc->data, char, 0);
4392 len = mono_array_length (rsrc->data);
4393 } else {
4394 data = NULL;
4395 len = 0;
4397 offset = len;
4398 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4399 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4400 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4401 mono_image_add_stream_data (&assembly->resources, data, len);
4403 if (!mb->is_main)
4405 * The entry should be emitted into the MANIFESTRESOURCE table of
4406 * the main module, but that needs to reference the FILE table
4407 * which isn't emitted yet.
4409 return;
4410 else
4411 idx = 0;
4414 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4417 static void
4418 set_version_from_string (MonoString *version, guint32 *values)
4420 gchar *ver, *p, *str;
4421 guint32 i;
4423 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4424 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4425 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4426 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4427 if (!version)
4428 return;
4429 ver = str = mono_string_to_utf8 (version);
4430 for (i = 0; i < 4; ++i) {
4431 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4432 switch (*p) {
4433 case '.':
4434 p++;
4435 break;
4436 case '*':
4437 /* handle Revision and Build */
4438 p++;
4439 break;
4441 ver = p;
4443 g_free (str);
4446 static guint32
4447 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4448 gsize len;
4449 guint32 token = 0;
4450 char blob_size [6];
4451 char *b = blob_size;
4453 if (!pkey)
4454 return token;
4456 len = mono_array_length (pkey);
4457 mono_metadata_encode_value (len, b, &b);
4458 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4459 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4461 assembly->public_key = g_malloc (len);
4462 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4463 assembly->public_key_len = len;
4465 /* Special case: check for ECMA key (16 bytes) */
4466 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4467 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4468 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4469 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4470 /* minimum key size (in 2.0) is 384 bits */
4471 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4472 } else {
4473 /* FIXME - verifier */
4474 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4475 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4477 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
4479 return token;
4482 static void
4483 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4485 MonoDynamicTable *table;
4486 MonoDynamicImage *assembly;
4487 MonoReflectionAssemblyBuilder *assemblyb;
4488 MonoDomain *domain;
4489 guint32 *values;
4490 int i;
4491 guint32 module_index;
4493 assemblyb = moduleb->assemblyb;
4494 assembly = moduleb->dynamic_image;
4495 domain = mono_object_domain (assemblyb);
4497 /* Emit ASSEMBLY table */
4498 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4499 alloc_table (table, 1);
4500 values = table->values + MONO_ASSEMBLY_SIZE;
4501 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4502 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4503 if (assemblyb->culture) {
4504 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4505 } else {
4506 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4508 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4509 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4510 set_version_from_string (assemblyb->version, values);
4512 /* Emit FILE + EXPORTED_TYPE table */
4513 module_index = 0;
4514 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4515 int j;
4516 MonoReflectionModuleBuilder *file_module =
4517 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4518 if (file_module != moduleb) {
4519 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4520 module_index ++;
4521 if (file_module->types) {
4522 for (j = 0; j < file_module->num_types; ++j) {
4523 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4524 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4529 if (assemblyb->loaded_modules) {
4530 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4531 MonoReflectionModule *file_module =
4532 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4533 mono_image_fill_file_table (domain, file_module, assembly);
4534 module_index ++;
4535 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4538 if (assemblyb->type_forwarders)
4539 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4541 /* Emit MANIFESTRESOURCE table */
4542 module_index = 0;
4543 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4544 int j;
4545 MonoReflectionModuleBuilder *file_module =
4546 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4547 /* The table for the main module is emitted later */
4548 if (file_module != moduleb) {
4549 module_index ++;
4550 if (file_module->resources) {
4551 int len = mono_array_length (file_module->resources);
4552 for (j = 0; j < len; ++j) {
4553 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4554 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4561 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4564 * mono_image_build_metadata() will fill the info in all the needed metadata tables
4565 * for the modulebuilder @moduleb.
4566 * At the end of the process, method and field tokens are fixed up and the
4567 * on-disk compressed metadata representation is created.
4569 void
4570 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4572 MonoDynamicTable *table;
4573 MonoDynamicImage *assembly;
4574 MonoReflectionAssemblyBuilder *assemblyb;
4575 MonoDomain *domain;
4576 MonoPtrArray types;
4577 guint32 *values;
4578 int i, j;
4580 assemblyb = moduleb->assemblyb;
4581 assembly = moduleb->dynamic_image;
4582 domain = mono_object_domain (assemblyb);
4584 if (assembly->text_rva)
4585 return;
4587 assembly->text_rva = START_TEXT_RVA;
4589 if (moduleb->is_main) {
4590 mono_image_emit_manifest (moduleb);
4593 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4594 table->rows = 1; /* .<Module> */
4595 table->next_idx++;
4596 alloc_table (table, table->rows);
4598 * Set the first entry.
4600 values = table->values + table->columns;
4601 values [MONO_TYPEDEF_FLAGS] = 0;
4602 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4603 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4604 values [MONO_TYPEDEF_EXTENDS] = 0;
4605 values [MONO_TYPEDEF_FIELD_LIST] = 1;
4606 values [MONO_TYPEDEF_METHOD_LIST] = 1;
4609 * handle global methods
4610 * FIXME: test what to do when global methods are defined in multiple modules.
4612 if (moduleb->global_methods) {
4613 table = &assembly->tables [MONO_TABLE_METHOD];
4614 table->rows += mono_array_length (moduleb->global_methods);
4615 alloc_table (table, table->rows);
4616 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4617 mono_image_get_method_info (
4618 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4620 if (moduleb->global_fields) {
4621 table = &assembly->tables [MONO_TABLE_FIELD];
4622 table->rows += mono_array_length (moduleb->global_fields);
4623 alloc_table (table, table->rows);
4624 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4625 mono_image_get_field_info (
4626 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4629 table = &assembly->tables [MONO_TABLE_MODULE];
4630 alloc_table (table, 1);
4631 mono_image_fill_module_table (domain, moduleb, assembly);
4633 /* Collect all types into a list sorted by their table_idx */
4634 mono_ptr_array_init (types, moduleb->num_types);
4636 if (moduleb->types)
4637 for (i = 0; i < moduleb->num_types; ++i) {
4638 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4639 collect_types (&types, type);
4642 mono_ptr_array_sort (types, (gpointer)compare_types_by_table_idx);
4643 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4644 table->rows += mono_ptr_array_size (types);
4645 alloc_table (table, table->rows);
4648 * Emit type names + namespaces at one place inside the string heap,
4649 * so load_class_names () needs to touch fewer pages.
4651 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4652 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4653 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4655 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4656 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4657 string_heap_insert_mstring (&assembly->sheap, tb->name);
4660 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4661 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4662 mono_image_get_type_info (domain, type, assembly);
4666 * table->rows is already set above and in mono_image_fill_module_table.
4668 /* add all the custom attributes at the end, once all the indexes are stable */
4669 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4671 /* CAS assembly permissions */
4672 if (assemblyb->permissions_minimum)
4673 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4674 if (assemblyb->permissions_optional)
4675 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4676 if (assemblyb->permissions_refused)
4677 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4679 module_add_cattrs (assembly, moduleb);
4681 /* fixup tokens */
4682 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4684 /* Create the MethodImpl table. We do this after emitting all methods so we already know
4685 * the final tokens and don't need another fixup pass. */
4687 if (moduleb->global_methods) {
4688 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4689 MonoReflectionMethodBuilder *mb = mono_array_get (
4690 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4691 mono_image_add_methodimpl (assembly, mb);
4695 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4696 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4697 if (type->methods) {
4698 for (j = 0; j < type->num_methods; ++j) {
4699 MonoReflectionMethodBuilder *mb = mono_array_get (
4700 type->methods, MonoReflectionMethodBuilder*, j);
4702 mono_image_add_methodimpl (assembly, mb);
4707 mono_ptr_array_destroy (types);
4709 fixup_cattrs (assembly);
4712 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4714 void
4715 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4717 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4720 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4723 typedef struct {
4724 guint32 import_lookup_table;
4725 guint32 timestamp;
4726 guint32 forwarder;
4727 guint32 name_rva;
4728 guint32 import_address_table_rva;
4729 } MonoIDT;
4731 typedef struct {
4732 guint32 name_rva;
4733 guint32 flags;
4734 } MonoILT;
4736 #ifndef DISABLE_REFLECTION_EMIT
4739 * mono_image_insert_string:
4740 * @module: module builder object
4741 * @str: a string
4743 * Insert @str into the user string stream of @module.
4745 guint32
4746 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4748 MonoDynamicImage *assembly;
4749 guint32 idx;
4750 char buf [16];
4751 char *b = buf;
4753 MONO_ARCH_SAVE_REGS;
4755 if (!module->dynamic_image)
4756 mono_image_module_basic_init (module);
4758 assembly = module->dynamic_image;
4760 if (assembly->save) {
4761 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4762 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4763 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4765 char *swapped = g_malloc (2 * mono_string_length (str));
4766 const char *p = (const char*)mono_string_chars (str);
4768 swap_with_size (swapped, p, 2, mono_string_length (str));
4769 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4770 g_free (swapped);
4772 #else
4773 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4774 #endif
4775 mono_image_add_stream_data (&assembly->us, "", 1);
4776 } else {
4777 idx = assembly->us.index ++;
4780 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4782 return MONO_TOKEN_STRING | idx;
4785 guint32
4786 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4788 MonoClass *klass;
4789 guint32 token = 0;
4790 MonoMethodSignature *sig;
4792 klass = obj->vtable->klass;
4793 if (strcmp (klass->name, "MonoMethod") == 0) {
4794 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4795 MonoMethodSignature *old;
4796 guint32 sig_token, parent;
4797 int nargs, i;
4799 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4801 nargs = mono_array_length (opt_param_types);
4802 old = mono_method_signature (method);
4803 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4805 sig->hasthis = old->hasthis;
4806 sig->explicit_this = old->explicit_this;
4807 sig->call_convention = old->call_convention;
4808 sig->generic_param_count = old->generic_param_count;
4809 sig->param_count = old->param_count + nargs;
4810 sig->sentinelpos = old->param_count;
4811 sig->ret = old->ret;
4813 for (i = 0; i < old->param_count; i++)
4814 sig->params [i] = old->params [i];
4816 for (i = 0; i < nargs; i++) {
4817 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4818 sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt);
4821 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4822 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4823 parent >>= MONO_TYPEDEFORREF_BITS;
4825 parent <<= MONO_MEMBERREF_PARENT_BITS;
4826 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4828 sig_token = method_encode_signature (assembly, sig);
4829 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4830 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4831 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4832 ReflectionMethodBuilder rmb;
4833 guint32 parent, sig_token;
4834 int nopt_args, nparams, ngparams, i;
4835 char *name;
4837 reflection_methodbuilder_from_method_builder (&rmb, mb);
4838 rmb.opt_types = opt_param_types;
4839 nopt_args = mono_array_length (opt_param_types);
4841 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
4842 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
4843 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
4845 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
4846 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
4847 sig->call_convention = rmb.call_conv;
4848 sig->generic_param_count = ngparams;
4849 sig->param_count = nparams + nopt_args;
4850 sig->sentinelpos = nparams;
4851 sig->ret = mono_reflection_type_get_handle (rmb.rtype);
4853 for (i = 0; i < nparams; i++) {
4854 MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
4855 sig->params [i] = mono_reflection_type_get_handle (rt);
4858 for (i = 0; i < nopt_args; i++) {
4859 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4860 sig->params [nparams + i] = mono_reflection_type_get_handle (rt);
4863 sig_token = method_builder_encode_signature (assembly, &rmb);
4865 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
4866 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4868 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4869 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4871 name = mono_string_to_utf8 (rmb.name);
4872 token = mono_image_get_varargs_method_token (
4873 assembly, parent, name, sig_token);
4874 g_free (name);
4875 } else {
4876 g_error ("requested method token for %s\n", klass->name);
4879 g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
4880 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4881 return token;
4885 * mono_image_create_token:
4886 * @assembly: a dynamic assembly
4887 * @obj:
4888 * @register_token: Whenever to register the token in the assembly->tokens hash.
4890 * Get a token to insert in the IL code stream for the given MemberInfo.
4891 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
4892 * the table_idx-es were recomputed, so registering the token would overwrite an existing
4893 * entry.
4895 guint32
4896 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
4897 gboolean create_open_instance, gboolean register_token)
4899 MonoClass *klass;
4900 guint32 token = 0;
4902 klass = obj->vtable->klass;
4904 /* Check for user defined reflection objects */
4905 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
4906 if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0))
4907 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported")); \
4909 if (strcmp (klass->name, "MethodBuilder") == 0) {
4910 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4911 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4913 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
4914 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4915 else
4916 token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance);
4917 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4918 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4919 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4920 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4922 if (tb->module->dynamic_image == assembly && !tb->generic_params)
4923 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4924 else
4925 token = mono_image_get_ctorbuilder_token (assembly, mb);
4926 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4927 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4928 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4929 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4930 if (tb->generic_params) {
4931 token = mono_image_get_generic_field_token (assembly, fb);
4932 } else {
4933 if (tb->module->dynamic_image == assembly) {
4934 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4935 } else {
4936 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
4939 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4940 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4941 if (create_open_instance && tb->generic_params) {
4942 MonoType *type;
4943 init_type_builder_generics (obj);
4944 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4945 token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
4946 token = mono_metadata_token_from_dor (token);
4947 } else if (tb->module->dynamic_image == assembly) {
4948 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4949 } else {
4950 MonoType *type;
4951 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4952 token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
4954 } else if (strcmp (klass->name, "MonoType") == 0) {
4955 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4956 MonoClass *mc = mono_class_from_mono_type (type);
4957 token = mono_metadata_token_from_dor (
4958 mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
4959 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4960 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4961 token = mono_metadata_token_from_dor (
4962 mono_image_typedef_or_ref (assembly, type));
4963 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4964 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4965 token = mono_metadata_token_from_dor (
4966 mono_image_typedef_or_ref (assembly, type));
4967 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4968 strcmp (klass->name, "MonoMethod") == 0 ||
4969 strcmp (klass->name, "MonoGenericMethod") == 0 ||
4970 strcmp (klass->name, "MonoGenericCMethod") == 0) {
4971 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4972 if (m->method->is_inflated) {
4973 if (create_open_instance)
4974 token = mono_image_get_methodspec_token (assembly, m->method);
4975 else
4976 token = mono_image_get_inflated_method_token (assembly, m->method);
4977 } else if ((m->method->klass->image == &assembly->image) &&
4978 !m->method->klass->generic_class) {
4979 static guint32 method_table_idx = 0xffffff;
4980 if (m->method->klass->wastypebuilder) {
4981 /* we use the same token as the one that was assigned
4982 * to the Methodbuilder.
4983 * FIXME: do the equivalent for Fields.
4985 token = m->method->token;
4986 } else {
4988 * Each token should have a unique index, but the indexes are
4989 * assigned by managed code, so we don't know about them. An
4990 * easy solution is to count backwards...
4992 method_table_idx --;
4993 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4995 } else {
4996 token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
4998 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4999 } else if (strcmp (klass->name, "MonoField") == 0) {
5000 MonoReflectionField *f = (MonoReflectionField *)obj;
5001 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5002 static guint32 field_table_idx = 0xffffff;
5003 field_table_idx --;
5004 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5005 } else {
5006 token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5008 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5009 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5010 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5011 token = mono_image_get_array_token (assembly, m);
5012 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5013 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5014 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
5015 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5016 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5017 token = mono_metadata_token_from_dor (
5018 mono_image_typedef_or_ref (assembly, type));
5019 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5020 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5021 token = mono_image_get_field_on_inst_token (assembly, f);
5022 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5023 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5024 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance);
5025 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5026 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5027 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance);
5028 } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5029 MonoReflectionType *type = (MonoReflectionType *)obj;
5030 token = mono_metadata_token_from_dor (
5031 mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (type)));
5032 } else {
5033 g_error ("requested token for %s\n", klass->name);
5036 if (register_token)
5037 mono_image_register_token (assembly, token, obj);
5039 return token;
5043 * mono_image_register_token:
5045 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5046 * the Module.ResolveXXXToken () methods to work.
5048 void
5049 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5051 MonoObject *prev = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5052 if (prev) {
5053 /* There could be multiple MethodInfo objects with the same token */
5054 //g_assert (prev == obj);
5055 } else {
5056 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5060 static MonoDynamicImage*
5061 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5063 static const guchar entrycode [16] = {0xff, 0x25, 0};
5064 MonoDynamicImage *image;
5065 int i;
5067 const char *version;
5069 if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5070 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5071 else
5072 version = mono_get_runtime_info ()->runtime_version;
5074 #if HAVE_BOEHM_GC
5075 /* The MonoGHashTable's need GC tracking */
5076 image = GC_MALLOC (sizeof (MonoDynamicImage));
5077 #else
5078 image = g_new0 (MonoDynamicImage, 1);
5079 #endif
5081 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5083 /*g_print ("created image %p\n", image);*/
5084 /* keep in sync with image.c */
5085 image->image.name = assembly_name;
5086 image->image.assembly_name = image->image.name; /* they may be different */
5087 image->image.module_name = module_name;
5088 image->image.version = g_strdup (version);
5089 image->image.md_version_major = 1;
5090 image->image.md_version_minor = 1;
5091 image->image.dynamic = TRUE;
5093 image->image.references = g_new0 (MonoAssembly*, 1);
5094 image->image.references [0] = NULL;
5096 mono_image_init (&image->image);
5098 image->token_fixups = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5099 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5100 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5101 image->method_aux_hash = g_hash_table_new (NULL, NULL);
5102 image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5103 image->handleref = g_hash_table_new (NULL, NULL);
5104 image->handleref_managed = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5105 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5106 image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5107 image->methodspec = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5108 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5109 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5110 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5111 image->gen_params = g_ptr_array_new ();
5113 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5114 string_heap_init (&image->sheap);
5115 mono_image_add_stream_data (&image->us, "", 1);
5116 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5117 /* import tables... */
5118 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5119 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5120 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5121 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5122 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5123 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5124 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5125 stream_data_align (&image->code);
5127 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5129 for (i=0; i < MONO_TABLE_NUM; ++i) {
5130 image->tables [i].next_idx = 1;
5131 image->tables [i].columns = table_sizes [i];
5134 image->image.assembly = (MonoAssembly*)assembly;
5135 image->run = assembly->run;
5136 image->save = assembly->save;
5137 image->pe_kind = 0x1; /* ILOnly */
5138 image->machine = 0x14c; /* I386 */
5140 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5142 return image;
5144 #endif
5146 static void
5147 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5149 g_free (key);
5152 void
5153 mono_dynamic_image_free (MonoDynamicImage *image)
5155 MonoDynamicImage *di = image;
5156 GList *list;
5157 int i;
5159 if (di->methodspec)
5160 mono_g_hash_table_destroy (di->methodspec);
5161 if (di->typespec)
5162 g_hash_table_destroy (di->typespec);
5163 if (di->typeref)
5164 g_hash_table_destroy (di->typeref);
5165 if (di->handleref)
5166 g_hash_table_destroy (di->handleref);
5167 if (di->handleref_managed)
5168 mono_g_hash_table_destroy (di->handleref_managed);
5169 if (di->tokens)
5170 mono_g_hash_table_destroy (di->tokens);
5171 if (di->generic_def_objects)
5172 mono_g_hash_table_destroy (di->generic_def_objects);
5173 if (di->blob_cache) {
5174 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5175 g_hash_table_destroy (di->blob_cache);
5177 if (di->standalonesig_cache)
5178 g_hash_table_destroy (di->standalonesig_cache);
5179 for (list = di->array_methods; list; list = list->next) {
5180 ArrayMethod *am = (ArrayMethod *)list->data;
5181 g_free (am->sig);
5182 g_free (am->name);
5183 g_free (am);
5185 g_list_free (di->array_methods);
5186 if (di->gen_params) {
5187 for (i = 0; i < di->gen_params->len; i++) {
5188 GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
5189 mono_gc_deregister_root ((char*) &entry->gparam);
5190 g_free (entry);
5192 g_ptr_array_free (di->gen_params, TRUE);
5194 if (di->token_fixups)
5195 mono_g_hash_table_destroy (di->token_fixups);
5196 if (di->method_to_table_idx)
5197 g_hash_table_destroy (di->method_to_table_idx);
5198 if (di->field_to_table_idx)
5199 g_hash_table_destroy (di->field_to_table_idx);
5200 if (di->method_aux_hash)
5201 g_hash_table_destroy (di->method_aux_hash);
5202 if (di->vararg_aux_hash)
5203 g_hash_table_destroy (di->vararg_aux_hash);
5204 g_free (di->strong_name);
5205 g_free (di->win32_res);
5206 if (di->public_key)
5207 g_free (di->public_key);
5209 /*g_print ("string heap destroy for image %p\n", di);*/
5210 mono_dynamic_stream_reset (&di->sheap);
5211 mono_dynamic_stream_reset (&di->code);
5212 mono_dynamic_stream_reset (&di->resources);
5213 mono_dynamic_stream_reset (&di->us);
5214 mono_dynamic_stream_reset (&di->blob);
5215 mono_dynamic_stream_reset (&di->tstream);
5216 mono_dynamic_stream_reset (&di->guid);
5217 for (i = 0; i < MONO_TABLE_NUM; ++i) {
5218 g_free (di->tables [i].values);
5222 #ifndef DISABLE_REFLECTION_EMIT
5225 * mono_image_basic_init:
5226 * @assembly: an assembly builder object
5228 * Create the MonoImage that represents the assembly builder and setup some
5229 * of the helper hash table and the basic metadata streams.
5231 void
5232 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5234 MonoDynamicAssembly *assembly;
5235 MonoDynamicImage *image;
5236 MonoDomain *domain = mono_object_domain (assemblyb);
5238 MONO_ARCH_SAVE_REGS;
5240 if (assemblyb->dynamic_assembly)
5241 return;
5243 #if HAVE_BOEHM_GC
5244 /* assembly->assembly.image might be GC allocated */
5245 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
5246 #else
5247 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5248 #endif
5250 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5252 assembly->assembly.ref_count = 1;
5253 assembly->assembly.dynamic = TRUE;
5254 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5255 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5256 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5257 if (assemblyb->culture)
5258 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5259 else
5260 assembly->assembly.aname.culture = g_strdup ("");
5262 if (assemblyb->version) {
5263 char *vstr = mono_string_to_utf8 (assemblyb->version);
5264 char **version = g_strsplit (vstr, ".", 4);
5265 char **parts = version;
5266 assembly->assembly.aname.major = atoi (*parts++);
5267 assembly->assembly.aname.minor = atoi (*parts++);
5268 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5269 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5271 g_strfreev (version);
5272 g_free (vstr);
5273 } else {
5274 assembly->assembly.aname.major = 0;
5275 assembly->assembly.aname.minor = 0;
5276 assembly->assembly.aname.build = 0;
5277 assembly->assembly.aname.revision = 0;
5280 assembly->run = assemblyb->access != 2;
5281 assembly->save = assemblyb->access != 1;
5282 assembly->domain = domain;
5284 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5285 image->initial_image = TRUE;
5286 assembly->assembly.aname.name = image->image.name;
5287 assembly->assembly.image = &image->image;
5288 if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5289 /* -1 to correct for the trailing NULL byte */
5290 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5291 g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5293 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);
5296 mono_domain_assemblies_lock (domain);
5297 domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
5298 mono_domain_assemblies_unlock (domain);
5300 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5302 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5304 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5307 #endif /* !DISABLE_REFLECTION_EMIT */
5309 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5311 static int
5312 calc_section_size (MonoDynamicImage *assembly)
5314 int nsections = 0;
5316 /* alignment constraints */
5317 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5318 g_assert ((assembly->code.index % 4) == 0);
5319 assembly->meta_size += 3;
5320 assembly->meta_size &= ~3;
5321 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5322 g_assert ((assembly->resources.index % 4) == 0);
5324 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5325 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5326 nsections++;
5328 if (assembly->win32_res) {
5329 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5331 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5332 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5333 nsections++;
5336 assembly->sections [MONO_SECTION_RELOC].size = 12;
5337 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5338 nsections++;
5340 return nsections;
5343 typedef struct {
5344 guint32 id;
5345 guint32 offset;
5346 GSList *children;
5347 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5348 } ResTreeNode;
5350 static int
5351 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5353 ResTreeNode *t1 = (ResTreeNode*)a;
5354 ResTreeNode *t2 = (ResTreeNode*)b;
5356 return t1->id - t2->id;
5360 * resource_tree_create:
5362 * Organize the resources into a resource tree.
5364 static ResTreeNode *
5365 resource_tree_create (MonoArray *win32_resources)
5367 ResTreeNode *tree, *res_node, *type_node, *lang_node;
5368 GSList *l;
5369 int i;
5371 tree = g_new0 (ResTreeNode, 1);
5373 for (i = 0; i < mono_array_length (win32_resources); ++i) {
5374 MonoReflectionWin32Resource *win32_res =
5375 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5377 /* Create node */
5379 /* FIXME: BUG: this stores managed references in unmanaged memory */
5380 lang_node = g_new0 (ResTreeNode, 1);
5381 lang_node->id = win32_res->lang_id;
5382 lang_node->win32_res = win32_res;
5384 /* Create type node if neccesary */
5385 type_node = NULL;
5386 for (l = tree->children; l; l = l->next)
5387 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5388 type_node = (ResTreeNode*)l->data;
5389 break;
5392 if (!type_node) {
5393 type_node = g_new0 (ResTreeNode, 1);
5394 type_node->id = win32_res->res_type;
5397 * The resource types have to be sorted otherwise
5398 * Windows Explorer can't display the version information.
5400 tree->children = g_slist_insert_sorted (tree->children,
5401 type_node, resource_tree_compare_by_id);
5404 /* Create res node if neccesary */
5405 res_node = NULL;
5406 for (l = type_node->children; l; l = l->next)
5407 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5408 res_node = (ResTreeNode*)l->data;
5409 break;
5412 if (!res_node) {
5413 res_node = g_new0 (ResTreeNode, 1);
5414 res_node->id = win32_res->res_id;
5415 type_node->children = g_slist_append (type_node->children, res_node);
5418 res_node->children = g_slist_append (res_node->children, lang_node);
5421 return tree;
5425 * resource_tree_encode:
5427 * Encode the resource tree into the format used in the PE file.
5429 static void
5430 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5432 char *entries;
5433 MonoPEResourceDir dir;
5434 MonoPEResourceDirEntry dir_entry;
5435 MonoPEResourceDataEntry data_entry;
5436 GSList *l;
5437 guint32 res_id_entries;
5440 * For the format of the resource directory, see the article
5441 * "An In-Depth Look into the Win32 Portable Executable File Format" by
5442 * Matt Pietrek
5445 memset (&dir, 0, sizeof (dir));
5446 memset (&dir_entry, 0, sizeof (dir_entry));
5447 memset (&data_entry, 0, sizeof (data_entry));
5449 g_assert (sizeof (dir) == 16);
5450 g_assert (sizeof (dir_entry) == 8);
5451 g_assert (sizeof (data_entry) == 16);
5453 node->offset = p - begin;
5455 /* IMAGE_RESOURCE_DIRECTORY */
5456 res_id_entries = g_slist_length (node->children);
5457 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5459 memcpy (p, &dir, sizeof (dir));
5460 p += sizeof (dir);
5462 /* Reserve space for entries */
5463 entries = p;
5464 p += sizeof (dir_entry) * res_id_entries;
5466 /* Write children */
5467 for (l = node->children; l; l = l->next) {
5468 ResTreeNode *child = (ResTreeNode*)l->data;
5470 if (child->win32_res) {
5471 guint32 size;
5473 child->offset = p - begin;
5475 /* IMAGE_RESOURCE_DATA_ENTRY */
5476 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5477 size = mono_array_length (child->win32_res->res_data);
5478 data_entry.rde_size = GUINT32_TO_LE (size);
5480 memcpy (p, &data_entry, sizeof (data_entry));
5481 p += sizeof (data_entry);
5483 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5484 p += size;
5485 } else {
5486 resource_tree_encode (child, begin, p, &p);
5490 /* IMAGE_RESOURCE_ENTRY */
5491 for (l = node->children; l; l = l->next) {
5492 ResTreeNode *child = (ResTreeNode*)l->data;
5494 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5495 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5497 memcpy (entries, &dir_entry, sizeof (dir_entry));
5498 entries += sizeof (dir_entry);
5501 *endbuf = p;
5504 static void
5505 resource_tree_free (ResTreeNode * node)
5507 GSList * list;
5508 for (list = node->children; list; list = list->next)
5509 resource_tree_free ((ResTreeNode*)list->data);
5510 g_slist_free(node->children);
5511 g_free (node);
5514 static void
5515 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5517 char *buf;
5518 char *p;
5519 guint32 size, i;
5520 MonoReflectionWin32Resource *win32_res;
5521 ResTreeNode *tree;
5523 if (!assemblyb->win32_resources)
5524 return;
5527 * Resources are stored in a three level tree inside the PE file.
5528 * - level one contains a node for each type of resource
5529 * - level two contains a node for each resource
5530 * - level three contains a node for each instance of a resource for a
5531 * specific language.
5534 tree = resource_tree_create (assemblyb->win32_resources);
5536 /* Estimate the size of the encoded tree */
5537 size = 0;
5538 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5539 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5540 size += mono_array_length (win32_res->res_data);
5542 /* Directory structure */
5543 size += mono_array_length (assemblyb->win32_resources) * 256;
5544 p = buf = g_malloc (size);
5546 resource_tree_encode (tree, p, p, &p);
5548 g_assert (p - buf <= size);
5550 assembly->win32_res = g_malloc (p - buf);
5551 assembly->win32_res_size = p - buf;
5552 memcpy (assembly->win32_res, buf, p - buf);
5554 g_free (buf);
5555 resource_tree_free (tree);
5558 static void
5559 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5561 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5562 int i;
5564 p += sizeof (MonoPEResourceDir);
5565 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5566 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5567 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5568 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5569 fixup_resource_directory (res_section, child, rva);
5570 } else {
5571 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5572 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5575 p += sizeof (MonoPEResourceDirEntry);
5579 static void
5580 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5582 guint32 dummy;
5583 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5584 g_error ("WriteFile returned %d\n", GetLastError ());
5588 * mono_image_create_pefile:
5589 * @mb: a module builder object
5591 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
5592 * assembly->pefile where it can be easily retrieved later in chunks.
5594 void
5595 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5597 MonoMSDOSHeader *msdos;
5598 MonoDotNetHeader *header;
5599 MonoSectionTable *section;
5600 MonoCLIHeader *cli_header;
5601 guint32 size, image_size, virtual_base, text_offset;
5602 guint32 header_start, section_start, file_offset, virtual_offset;
5603 MonoDynamicImage *assembly;
5604 MonoReflectionAssemblyBuilder *assemblyb;
5605 MonoDynamicStream pefile_stream = {0};
5606 MonoDynamicStream *pefile = &pefile_stream;
5607 int i, nsections;
5608 guint32 *rva, value;
5609 guchar *p;
5610 static const unsigned char msheader[] = {
5611 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5612 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5613 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5614 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5615 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5616 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5617 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5618 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5621 assemblyb = mb->assemblyb;
5623 mono_image_basic_init (assemblyb);
5624 assembly = mb->dynamic_image;
5626 assembly->pe_kind = assemblyb->pe_kind;
5627 assembly->machine = assemblyb->machine;
5628 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5629 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5631 mono_image_build_metadata (mb);
5633 if (mb->is_main && assemblyb->resources) {
5634 int len = mono_array_length (assemblyb->resources);
5635 for (i = 0; i < len; ++i)
5636 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5639 if (mb->resources) {
5640 int len = mono_array_length (mb->resources);
5641 for (i = 0; i < len; ++i)
5642 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5645 build_compressed_metadata (assembly);
5647 if (mb->is_main)
5648 assembly_add_win32_resources (assembly, assemblyb);
5650 nsections = calc_section_size (assembly);
5652 /* The DOS header and stub */
5653 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5654 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5656 /* the dotnet header */
5657 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5659 /* the section tables */
5660 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5662 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5663 virtual_offset = VIRT_ALIGN;
5664 image_size = 0;
5666 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5667 if (!assembly->sections [i].size)
5668 continue;
5669 /* align offsets */
5670 file_offset += FILE_ALIGN - 1;
5671 file_offset &= ~(FILE_ALIGN - 1);
5672 virtual_offset += VIRT_ALIGN - 1;
5673 virtual_offset &= ~(VIRT_ALIGN - 1);
5675 assembly->sections [i].offset = file_offset;
5676 assembly->sections [i].rva = virtual_offset;
5678 file_offset += assembly->sections [i].size;
5679 virtual_offset += assembly->sections [i].size;
5680 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5683 file_offset += FILE_ALIGN - 1;
5684 file_offset &= ~(FILE_ALIGN - 1);
5686 image_size += section_start + sizeof (MonoSectionTable) * nsections;
5688 /* back-patch info */
5689 msdos = (MonoMSDOSHeader*)pefile->data;
5690 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5692 header = (MonoDotNetHeader*)(pefile->data + header_start);
5693 header->pesig [0] = 'P';
5694 header->pesig [1] = 'E';
5696 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5697 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5698 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5699 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5700 if (assemblyb->pekind == 1) {
5701 /* it's a dll */
5702 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5703 } else {
5704 /* it's an exe */
5705 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5708 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5710 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5711 header->pe.pe_major = 6;
5712 header->pe.pe_minor = 0;
5713 size = assembly->sections [MONO_SECTION_TEXT].size;
5714 size += FILE_ALIGN - 1;
5715 size &= ~(FILE_ALIGN - 1);
5716 header->pe.pe_code_size = GUINT32_FROM_LE(size);
5717 size = assembly->sections [MONO_SECTION_RSRC].size;
5718 size += FILE_ALIGN - 1;
5719 size &= ~(FILE_ALIGN - 1);
5720 header->pe.pe_data_size = GUINT32_FROM_LE(size);
5721 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5722 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5723 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5724 /* pe_rva_entry_point always at the beginning of the text section */
5725 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5727 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5728 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5729 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5730 header->nt.pe_os_major = GUINT16_FROM_LE (4);
5731 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5732 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5733 size = section_start;
5734 size += FILE_ALIGN - 1;
5735 size &= ~(FILE_ALIGN - 1);
5736 header->nt.pe_header_size = GUINT32_FROM_LE (size);
5737 size = image_size;
5738 size += VIRT_ALIGN - 1;
5739 size &= ~(VIRT_ALIGN - 1);
5740 header->nt.pe_image_size = GUINT32_FROM_LE (size);
5743 // Translate the PEFileKind value to the value expected by the Windows loader
5746 short kind;
5749 // PEFileKinds.Dll == 1
5750 // PEFileKinds.ConsoleApplication == 2
5751 // PEFileKinds.WindowApplication == 3
5753 // need to get:
5754 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5755 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5757 if (assemblyb->pekind == 3)
5758 kind = 2;
5759 else
5760 kind = 3;
5762 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5764 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5765 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5766 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5767 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5768 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5769 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
5771 /* fill data directory entries */
5773 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
5774 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5776 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
5777 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
5779 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
5780 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
5781 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
5782 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5783 /* patch entrypoint name */
5784 if (assemblyb->pekind == 1)
5785 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
5786 else
5787 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
5788 /* patch imported function RVA name */
5789 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
5790 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
5792 /* the import table */
5793 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
5794 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
5795 /* patch imported dll RVA name and other entries in the dir */
5796 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
5797 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
5798 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
5799 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5800 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
5801 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
5803 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
5804 value = (assembly->text_rva + assembly->imp_names_offset);
5805 *p++ = (value) & 0xff;
5806 *p++ = (value >> 8) & (0xff);
5807 *p++ = (value >> 16) & (0xff);
5808 *p++ = (value >> 24) & (0xff);
5810 /* the CLI header info */
5811 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
5812 cli_header->ch_size = GUINT32_FROM_LE (72);
5813 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
5814 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
5815 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
5816 if (assemblyb->entry_point) {
5817 guint32 table_idx = 0;
5818 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
5819 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
5820 table_idx = methodb->table_idx;
5821 } else {
5822 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
5824 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
5825 } else {
5826 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
5828 /* The embedded managed resources */
5829 text_offset = assembly->text_rva + assembly->code.index;
5830 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
5831 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
5832 text_offset += assembly->resources.index;
5833 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
5834 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
5835 text_offset += assembly->meta_size;
5836 if (assembly->strong_name_size) {
5837 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
5838 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
5839 text_offset += assembly->strong_name_size;
5842 /* write the section tables and section content */
5843 section = (MonoSectionTable*)(pefile->data + section_start);
5844 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5845 static const char section_names [][7] = {
5846 ".text", ".rsrc", ".reloc"
5848 if (!assembly->sections [i].size)
5849 continue;
5850 strcpy (section->st_name, section_names [i]);
5851 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5852 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5853 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5854 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5855 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5856 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5857 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5858 section ++;
5861 checked_write_file (file, pefile->data, pefile->index);
5863 mono_dynamic_stream_reset (pefile);
5865 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5866 if (!assembly->sections [i].size)
5867 continue;
5869 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5870 g_error ("SetFilePointer returned %d\n", GetLastError ());
5872 switch (i) {
5873 case MONO_SECTION_TEXT:
5874 /* patch entry point */
5875 p = (guchar*)(assembly->code.data + 2);
5876 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5877 *p++ = (value) & 0xff;
5878 *p++ = (value >> 8) & 0xff;
5879 *p++ = (value >> 16) & 0xff;
5880 *p++ = (value >> 24) & 0xff;
5882 checked_write_file (file, assembly->code.data, assembly->code.index);
5883 checked_write_file (file, assembly->resources.data, assembly->resources.index);
5884 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5885 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5888 g_free (assembly->image.raw_metadata);
5889 break;
5890 case MONO_SECTION_RELOC: {
5891 struct {
5892 guint32 page_rva;
5893 guint32 block_size;
5894 guint16 type_and_offset;
5895 guint16 term;
5896 } reloc;
5898 g_assert (sizeof (reloc) == 12);
5900 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5901 reloc.block_size = GUINT32_FROM_LE (12);
5904 * the entrypoint is always at the start of the text section
5905 * 3 is IMAGE_REL_BASED_HIGHLOW
5906 * 2 is patch_size_rva - text_rva
5908 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5909 reloc.term = 0;
5911 checked_write_file (file, &reloc, sizeof (reloc));
5913 break;
5915 case MONO_SECTION_RSRC:
5916 if (assembly->win32_res) {
5918 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5919 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5920 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5922 break;
5923 default:
5924 g_assert_not_reached ();
5928 /* check that the file is properly padded */
5929 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5930 g_error ("SetFilePointer returned %d\n", GetLastError ());
5931 if (! SetEndOfFile (file))
5932 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5934 mono_dynamic_stream_reset (&assembly->code);
5935 mono_dynamic_stream_reset (&assembly->us);
5936 mono_dynamic_stream_reset (&assembly->blob);
5937 mono_dynamic_stream_reset (&assembly->guid);
5938 mono_dynamic_stream_reset (&assembly->sheap);
5940 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5941 g_hash_table_destroy (assembly->blob_cache);
5942 assembly->blob_cache = NULL;
5945 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5947 void
5948 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5950 g_assert_not_reached ();
5953 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5955 #ifndef DISABLE_REFLECTION_EMIT
5957 MonoReflectionModule *
5958 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5960 char *name;
5961 MonoImage *image;
5962 MonoImageOpenStatus status;
5963 MonoDynamicAssembly *assembly;
5964 guint32 module_count;
5965 MonoImage **new_modules;
5966 gboolean *new_modules_loaded;
5968 name = mono_string_to_utf8 (fileName);
5970 image = mono_image_open (name, &status);
5971 if (!image) {
5972 MonoException *exc;
5973 if (status == MONO_IMAGE_ERROR_ERRNO)
5974 exc = mono_get_exception_file_not_found (fileName);
5975 else
5976 exc = mono_get_exception_bad_image_format (name);
5977 g_free (name);
5978 mono_raise_exception (exc);
5981 g_free (name);
5983 assembly = ab->dynamic_assembly;
5984 image->assembly = (MonoAssembly*)assembly;
5986 module_count = image->assembly->image->module_count;
5987 new_modules = g_new0 (MonoImage *, module_count + 1);
5988 new_modules_loaded = g_new0 (gboolean, module_count + 1);
5990 if (image->assembly->image->modules)
5991 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5992 if (image->assembly->image->modules_loaded)
5993 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
5994 new_modules [module_count] = image;
5995 new_modules_loaded [module_count] = TRUE;
5996 mono_image_addref (image);
5998 g_free (image->assembly->image->modules);
5999 image->assembly->image->modules = new_modules;
6000 image->assembly->image->modules_loaded = new_modules_loaded;
6001 image->assembly->image->module_count ++;
6003 mono_assembly_load_references (image, &status);
6004 if (status) {
6005 mono_image_close (image);
6006 mono_raise_exception (mono_get_exception_file_not_found (fileName));
6009 return mono_module_get_object (mono_domain_get (), image);
6012 #endif /* DISABLE_REFLECTION_EMIT */
6015 * We need to return always the same object for MethodInfo, FieldInfo etc..
6016 * but we need to consider the reflected type.
6017 * type uses a different hash, since it uses custom hash/equal functions.
6020 typedef struct {
6021 gpointer item;
6022 MonoClass *refclass;
6023 } ReflectedEntry;
6025 static gboolean
6026 reflected_equal (gconstpointer a, gconstpointer b) {
6027 const ReflectedEntry *ea = a;
6028 const ReflectedEntry *eb = b;
6030 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6033 static guint
6034 reflected_hash (gconstpointer a) {
6035 const ReflectedEntry *ea = a;
6036 return mono_aligned_addr_hash (ea->item);
6039 #define CHECK_OBJECT(t,p,k) \
6040 do { \
6041 t _obj; \
6042 ReflectedEntry e; \
6043 e.item = (p); \
6044 e.refclass = (k); \
6045 mono_domain_lock (domain); \
6046 if (!domain->refobject_hash) \
6047 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
6048 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
6049 mono_domain_unlock (domain); \
6050 return _obj; \
6052 mono_domain_unlock (domain); \
6053 } while (0)
6055 #ifdef HAVE_BOEHM_GC
6056 /* ReflectedEntry doesn't need to be GC tracked */
6057 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6058 #define FREE_REFENTRY(entry) g_free ((entry))
6059 #define REFENTRY_REQUIRES_CLEANUP
6060 #else
6061 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6062 /* FIXME: */
6063 #define FREE_REFENTRY(entry)
6064 #endif
6066 #define CACHE_OBJECT(t,p,o,k) \
6067 do { \
6068 t _obj; \
6069 ReflectedEntry pe; \
6070 pe.item = (p); \
6071 pe.refclass = (k); \
6072 mono_domain_lock (domain); \
6073 if (!domain->refobject_hash) \
6074 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
6075 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6076 if (!_obj) { \
6077 ReflectedEntry *e = ALLOC_REFENTRY; \
6078 e->item = (p); \
6079 e->refclass = (k); \
6080 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
6081 _obj = o; \
6083 mono_domain_unlock (domain); \
6084 return _obj; \
6085 } while (0)
6087 static void
6088 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6090 mono_domain_lock (domain);
6091 if (domain->refobject_hash) {
6092 ReflectedEntry pe;
6093 gpointer orig_pe, orig_value;
6095 pe.item = o;
6096 pe.refclass = klass;
6097 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6098 mono_g_hash_table_remove (domain->refobject_hash, &pe);
6099 FREE_REFENTRY (orig_pe);
6102 mono_domain_unlock (domain);
6105 #ifdef REFENTRY_REQUIRES_CLEANUP
6106 static void
6107 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6109 FREE_REFENTRY (key);
6111 #endif
6113 void
6114 mono_reflection_cleanup_domain (MonoDomain *domain)
6116 if (domain->refobject_hash) {
6117 /*let's avoid scanning the whole hashtable if not needed*/
6118 #ifdef REFENTRY_REQUIRES_CLEANUP
6119 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6120 #endif
6121 mono_g_hash_table_destroy (domain->refobject_hash);
6122 domain->refobject_hash = NULL;
6126 #ifndef DISABLE_REFLECTION_EMIT
6127 static gpointer
6128 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6130 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6133 static gpointer
6134 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6136 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6139 void
6140 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6142 MonoDynamicImage *image = moduleb->dynamic_image;
6143 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6144 if (!image) {
6145 MonoError error;
6146 int module_count;
6147 MonoImage **new_modules;
6148 MonoImage *ass;
6149 char *name, *fqname;
6151 * FIXME: we already created an image in mono_image_basic_init (), but
6152 * we don't know which module it belongs to, since that is only
6153 * determined at assembly save time.
6155 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6156 name = mono_string_to_utf8 (ab->name);
6157 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6158 if (!mono_error_ok (&error)) {
6159 g_free (name);
6160 mono_error_raise_exception (&error);
6162 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6164 moduleb->module.image = &image->image;
6165 moduleb->dynamic_image = image;
6166 register_module (mono_object_domain (moduleb), moduleb, image);
6168 /* register the module with the assembly */
6169 ass = ab->dynamic_assembly->assembly.image;
6170 module_count = ass->module_count;
6171 new_modules = g_new0 (MonoImage *, module_count + 1);
6173 if (ass->modules)
6174 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6175 new_modules [module_count] = &image->image;
6176 mono_image_addref (&image->image);
6178 g_free (ass->modules);
6179 ass->modules = new_modules;
6180 ass->module_count ++;
6184 void
6185 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6187 MonoDynamicImage *image = moduleb->dynamic_image;
6189 g_assert (type->type);
6190 image->wrappers_type = mono_class_from_mono_type (type->type);
6193 #endif
6196 * mono_assembly_get_object:
6197 * @domain: an app domain
6198 * @assembly: an assembly
6200 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6202 MonoReflectionAssembly*
6203 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6205 static MonoClass *assembly_type;
6206 MonoReflectionAssembly *res;
6208 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6209 if (!assembly_type) {
6210 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoAssembly");
6211 if (class == NULL)
6212 class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Assembly");
6213 g_assert (class);
6214 assembly_type = class;
6216 res = (MonoReflectionAssembly *)mono_object_new (domain, assembly_type);
6217 res->assembly = assembly;
6219 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6224 MonoReflectionModule*
6225 mono_module_get_object (MonoDomain *domain, MonoImage *image)
6227 static MonoClass *module_type;
6228 MonoReflectionModule *res;
6229 char* basename;
6231 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6232 if (!module_type) {
6233 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6234 if (class == NULL)
6235 class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6236 g_assert (class);
6237 module_type = class;
6239 res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6241 res->image = image;
6242 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6244 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6245 basename = g_path_get_basename (image->name);
6246 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6247 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6249 g_free (basename);
6251 if (image->assembly->image == image) {
6252 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6253 } else {
6254 int i;
6255 res->token = 0;
6256 if (image->assembly->image->modules) {
6257 for (i = 0; i < image->assembly->image->module_count; i++) {
6258 if (image->assembly->image->modules [i] == image)
6259 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6261 g_assert (res->token);
6265 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6268 MonoReflectionModule*
6269 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6271 static MonoClass *module_type;
6272 MonoReflectionModule *res;
6273 MonoTableInfo *table;
6274 guint32 cols [MONO_FILE_SIZE];
6275 const char *name;
6276 guint32 i, name_idx;
6277 const char *val;
6279 if (!module_type) {
6280 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6281 if (class == NULL)
6282 class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6283 g_assert (class);
6284 module_type = class;
6286 res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6288 table = &image->tables [MONO_TABLE_FILE];
6289 g_assert (table_index < table->rows);
6290 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6292 res->image = NULL;
6293 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6294 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6296 /* Check whenever the row has a corresponding row in the moduleref table */
6297 table = &image->tables [MONO_TABLE_MODULEREF];
6298 for (i = 0; i < table->rows; ++i) {
6299 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6300 val = mono_metadata_string_heap (image, name_idx);
6301 if (strcmp (val, name) == 0)
6302 res->image = image->modules [i];
6305 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6306 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6307 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6308 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6309 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6311 return res;
6314 static gboolean
6315 verify_safe_for_managed_space (MonoType *type)
6317 switch (type->type) {
6318 #ifdef DEBUG_HARDER
6319 case MONO_TYPE_ARRAY:
6320 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6321 case MONO_TYPE_PTR:
6322 return verify_safe_for_managed_space (type->data.type);
6323 case MONO_TYPE_SZARRAY:
6324 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6325 case MONO_TYPE_GENERICINST: {
6326 MonoGenericInst *inst = type->data.generic_class->inst;
6327 int i;
6328 if (!inst->is_open)
6329 break;
6330 for (i = 0; i < inst->type_argc; ++i)
6331 if (!verify_safe_for_managed_space (inst->type_argv [i]))
6332 return FALSE;
6333 break;
6335 #endif
6336 case MONO_TYPE_VAR:
6337 case MONO_TYPE_MVAR:
6338 return TRUE;
6340 return TRUE;
6343 static MonoType*
6344 mono_type_normalize (MonoType *type)
6346 int i;
6347 MonoGenericClass *gclass;
6348 MonoGenericInst *ginst;
6349 MonoClass *gtd;
6350 MonoGenericContainer *gcontainer;
6351 MonoType **argv = NULL;
6352 gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
6354 if (type->type != MONO_TYPE_GENERICINST)
6355 return type;
6357 gclass = type->data.generic_class;
6358 ginst = gclass->context.class_inst;
6359 if (!ginst->is_open)
6360 return type;
6362 gtd = gclass->container_class;
6363 gcontainer = gtd->generic_container;
6364 argv = g_newa (MonoType*, ginst->type_argc);
6366 for (i = 0; i < ginst->type_argc; ++i) {
6367 MonoType *t = ginst->type_argv [i], *norm;
6368 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
6369 is_denorm_gtd = FALSE;
6370 norm = mono_type_normalize (t);
6371 argv [i] = norm;
6372 if (norm != t)
6373 requires_rebind = TRUE;
6376 if (is_denorm_gtd)
6377 return type->byref == gtd->byval_arg.byref ? &gtd->byval_arg : &gtd->this_arg;
6379 if (requires_rebind) {
6380 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
6381 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
6384 return type;
6387 * mono_type_get_object:
6388 * @domain: an app domain
6389 * @type: a type
6391 * Return an System.MonoType object representing the type @type.
6393 MonoReflectionType*
6394 mono_type_get_object (MonoDomain *domain, MonoType *type)
6396 MonoType *norm_type;
6397 MonoReflectionType *res;
6398 MonoClass *klass = mono_class_from_mono_type (type);
6400 /*we must avoid using @type as it might have come
6401 * from a mono_metadata_type_dup and the caller
6402 * expects that is can be freed.
6403 * Using the right type from
6405 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6407 /* void is very common */
6408 if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6409 return (MonoReflectionType*)domain->typeof_void;
6412 * If the vtable of the given class was already created, we can use
6413 * the MonoType from there and avoid all locking and hash table lookups.
6415 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6416 * that the resulting object is different.
6418 if (type == &klass->byval_arg && !klass->image->dynamic) {
6419 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6420 if (vtable && vtable->type)
6421 return vtable->type;
6424 mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6425 mono_domain_lock (domain);
6426 if (!domain->type_hash)
6427 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
6428 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC);
6429 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
6430 mono_domain_unlock (domain);
6431 mono_loader_unlock ();
6432 return res;
6435 /*Types must be normalized so a generic instance of the GTD get's the same inner type.
6436 * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
6437 * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
6438 * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
6439 * artifact of how generics are encoded and should be transparent to managed code so we
6440 * need to weed out this diference when retrieving managed System.Type objects.
6442 norm_type = mono_type_normalize (type);
6443 if (norm_type != type) {
6444 res = mono_type_get_object (domain, norm_type);
6445 mono_g_hash_table_insert (domain->type_hash, type, res);
6446 mono_domain_unlock (domain);
6447 mono_loader_unlock ();
6448 return res;
6451 /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
6452 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
6453 g_assert (0);
6455 if (!verify_safe_for_managed_space (type)) {
6456 mono_domain_unlock (domain);
6457 mono_loader_unlock ();
6458 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6461 if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
6462 gboolean is_type_done = TRUE;
6463 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
6464 * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
6465 * We can't simply close the types as this will interfere with other parts of the generics machinery.
6467 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
6468 MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
6470 if (gparam->owner && gparam->owner->is_method) {
6471 MonoMethod *method = gparam->owner->owner.method;
6472 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
6473 is_type_done = FALSE;
6474 } else if (gparam->owner && !gparam->owner->is_method) {
6475 MonoClass *klass = gparam->owner->owner.klass;
6476 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
6477 is_type_done = FALSE;
6481 /* g_assert_not_reached (); */
6482 /* should this be considered an error condition? */
6483 if (is_type_done && !type->byref) {
6484 mono_domain_unlock (domain);
6485 mono_loader_unlock ();
6486 return mono_class_get_ref_info (klass);
6489 /* This is stored in vtables/JITted code so it has to be pinned */
6490 res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class);
6491 res->type = type;
6492 mono_g_hash_table_insert (domain->type_hash, type, res);
6494 if (type->type == MONO_TYPE_VOID)
6495 domain->typeof_void = (MonoObject*)res;
6497 mono_domain_unlock (domain);
6498 mono_loader_unlock ();
6499 return res;
6503 * mono_method_get_object:
6504 * @domain: an app domain
6505 * @method: a method
6506 * @refclass: the reflected type (can be NULL)
6508 * Return an System.Reflection.MonoMethod object representing the method @method.
6510 MonoReflectionMethod*
6511 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6514 * We use the same C representation for methods and constructors, but the type
6515 * name in C# is different.
6517 static MonoClass *System_Reflection_MonoMethod = NULL;
6518 static MonoClass *System_Reflection_MonoCMethod = NULL;
6519 static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6520 static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6521 MonoClass *klass;
6522 MonoReflectionMethod *ret;
6524 if (method->is_inflated) {
6525 MonoReflectionGenericMethod *gret;
6527 refclass = method->klass;
6528 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6529 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6530 if (!System_Reflection_MonoGenericCMethod)
6531 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6532 klass = System_Reflection_MonoGenericCMethod;
6533 } else {
6534 if (!System_Reflection_MonoGenericMethod)
6535 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6536 klass = System_Reflection_MonoGenericMethod;
6538 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6539 gret->method.method = method;
6540 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6541 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6542 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6545 if (!refclass)
6546 refclass = method->klass;
6548 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6549 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6550 if (!System_Reflection_MonoCMethod)
6551 System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6552 klass = System_Reflection_MonoCMethod;
6554 else {
6555 if (!System_Reflection_MonoMethod)
6556 System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6557 klass = System_Reflection_MonoMethod;
6559 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6560 ret->method = method;
6561 MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6562 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6566 * mono_method_clear_object:
6568 * Clear the cached reflection objects for the dynamic method METHOD.
6570 void
6571 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
6573 MonoClass *klass;
6574 g_assert (method->dynamic);
6576 klass = method->klass;
6577 while (klass) {
6578 clear_cached_object (domain, method, klass);
6579 klass = klass->parent;
6581 /* Added by mono_param_get_objects () */
6582 clear_cached_object (domain, &(method->signature), NULL);
6583 klass = method->klass;
6584 while (klass) {
6585 clear_cached_object (domain, &(method->signature), klass);
6586 klass = klass->parent;
6591 * mono_field_get_object:
6592 * @domain: an app domain
6593 * @klass: a type
6594 * @field: a field
6596 * Return an System.Reflection.MonoField object representing the field @field
6597 * in class @klass.
6599 MonoReflectionField*
6600 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6602 MonoReflectionField *res;
6603 static MonoClass *monofield_klass;
6605 CHECK_OBJECT (MonoReflectionField *, field, klass);
6606 if (!monofield_klass)
6607 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6608 res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6609 res->klass = klass;
6610 res->field = field;
6611 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6613 if (is_field_on_inst (field)) {
6614 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6615 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6616 } else {
6617 if (field->type)
6618 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6619 res->attrs = mono_field_get_flags (field);
6621 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6625 * mono_property_get_object:
6626 * @domain: an app domain
6627 * @klass: a type
6628 * @property: a property
6630 * Return an System.Reflection.MonoProperty object representing the property @property
6631 * in class @klass.
6633 MonoReflectionProperty*
6634 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6636 MonoReflectionProperty *res;
6637 static MonoClass *monoproperty_klass;
6639 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6640 if (!monoproperty_klass)
6641 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6642 res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6643 res->klass = klass;
6644 res->property = property;
6645 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6649 * mono_event_get_object:
6650 * @domain: an app domain
6651 * @klass: a type
6652 * @event: a event
6654 * Return an System.Reflection.MonoEvent object representing the event @event
6655 * in class @klass.
6657 MonoReflectionEvent*
6658 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6660 MonoReflectionEvent *res;
6661 MonoReflectionMonoEvent *mono_event;
6662 static MonoClass *monoevent_klass;
6664 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6665 if (!monoevent_klass)
6666 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6667 mono_event = (MonoReflectionMonoEvent *)mono_object_new (domain, monoevent_klass);
6668 mono_event->klass = klass;
6669 mono_event->event = event;
6670 res = (MonoReflectionEvent*)mono_event;
6671 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6675 * mono_get_reflection_missing_object:
6676 * @domain: Domain where the object lives
6678 * Returns the System.Reflection.Missing.Value singleton object
6679 * (of type System.Reflection.Missing).
6681 * Used as the value for ParameterInfo.DefaultValue when Optional
6682 * is present
6684 static MonoObject *
6685 mono_get_reflection_missing_object (MonoDomain *domain)
6687 MonoObject *obj;
6688 static MonoClassField *missing_value_field = NULL;
6690 if (!missing_value_field) {
6691 MonoClass *missing_klass;
6692 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6693 mono_class_init (missing_klass);
6694 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6695 g_assert (missing_value_field);
6697 obj = mono_field_get_value_object (domain, missing_value_field, NULL);
6698 g_assert (obj);
6699 return obj;
6702 static MonoObject*
6703 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6705 if (!*dbnull)
6706 *dbnull = mono_get_dbnull_object (domain);
6707 return *dbnull;
6710 static MonoObject*
6711 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6713 if (!*reflection_missing)
6714 *reflection_missing = mono_get_reflection_missing_object (domain);
6715 return *reflection_missing;
6719 * mono_param_get_objects:
6720 * @domain: an app domain
6721 * @method: a method
6723 * Return an System.Reflection.ParameterInfo array object representing the parameters
6724 * in the method @method.
6726 MonoArray*
6727 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6729 static MonoClass *System_Reflection_ParameterInfo;
6730 static MonoClass *System_Reflection_ParameterInfo_array;
6731 MonoError error;
6732 MonoArray *res = NULL;
6733 MonoReflectionMethod *member = NULL;
6734 MonoReflectionParameter *param = NULL;
6735 char **names, **blobs = NULL;
6736 guint32 *types = NULL;
6737 MonoType *type = NULL;
6738 MonoObject *dbnull = NULL;
6739 MonoObject *missing = NULL;
6740 MonoMarshalSpec **mspecs;
6741 MonoMethodSignature *sig;
6742 MonoVTable *pinfo_vtable;
6743 int i;
6745 if (!System_Reflection_ParameterInfo_array) {
6746 MonoClass *klass;
6748 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6749 mono_memory_barrier ();
6750 System_Reflection_ParameterInfo = klass;
6752 klass = mono_array_class_get (klass, 1);
6753 mono_memory_barrier ();
6754 System_Reflection_ParameterInfo_array = klass;
6757 sig = mono_method_signature_checked (method, &error);
6758 if (!mono_error_ok (&error))
6759 mono_error_raise_exception (&error);
6761 if (!sig->param_count)
6762 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6764 /* Note: the cache is based on the address of the signature into the method
6765 * since we already cache MethodInfos with the method as keys.
6767 CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
6769 member = mono_method_get_object (domain, method, refclass);
6770 names = g_new (char *, sig->param_count);
6771 mono_method_get_param_names (method, (const char **) names);
6773 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
6774 mono_method_get_marshal_info (method, mspecs);
6776 res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
6777 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
6778 for (i = 0; i < sig->param_count; ++i) {
6779 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
6780 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
6781 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
6782 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
6783 param->PositionImpl = i;
6784 param->AttrsImpl = sig->params [i]->attrs;
6786 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
6787 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6788 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6789 else
6790 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6791 } else {
6793 if (!blobs) {
6794 blobs = g_new0 (char *, sig->param_count);
6795 types = g_new0 (guint32, sig->param_count);
6796 get_default_param_value_blobs (method, blobs, types);
6799 /* Build MonoType for the type from the Constant Table */
6800 if (!type)
6801 type = g_new0 (MonoType, 1);
6802 type->type = types [i];
6803 type->data.klass = NULL;
6804 if (types [i] == MONO_TYPE_CLASS)
6805 type->data.klass = mono_defaults.object_class;
6806 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
6807 /* For enums, types [i] contains the base type */
6809 type->type = MONO_TYPE_VALUETYPE;
6810 type->data.klass = mono_class_from_mono_type (sig->params [i]);
6811 } else
6812 type->data.klass = mono_class_from_mono_type (type);
6814 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
6816 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6817 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
6818 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6819 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6820 else
6821 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6826 if (mspecs [i + 1])
6827 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
6829 mono_array_setref (res, i, param);
6831 g_free (names);
6832 g_free (blobs);
6833 g_free (types);
6834 g_free (type);
6836 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
6837 if (mspecs [i])
6838 mono_metadata_free_marshal_spec (mspecs [i]);
6839 g_free (mspecs);
6841 CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
6844 MonoArray*
6845 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
6847 return mono_param_get_objects_internal (domain, method, NULL);
6851 * mono_method_body_get_object:
6852 * @domain: an app domain
6853 * @method: a method
6855 * Return an System.Reflection.MethodBody object representing the method @method.
6857 MonoReflectionMethodBody*
6858 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
6860 static MonoClass *System_Reflection_MethodBody = NULL;
6861 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
6862 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
6863 MonoReflectionMethodBody *ret;
6864 MonoMethodHeader *header;
6865 MonoImage *image;
6866 guint32 method_rva, local_var_sig_token;
6867 char *ptr;
6868 unsigned char format, flags;
6869 int i;
6871 /* for compatibility with .net */
6872 if (method->dynamic)
6873 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
6875 if (!System_Reflection_MethodBody)
6876 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
6877 if (!System_Reflection_LocalVariableInfo)
6878 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
6879 if (!System_Reflection_ExceptionHandlingClause)
6880 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
6882 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
6884 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6885 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
6886 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
6887 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
6888 return NULL;
6890 image = method->klass->image;
6891 header = mono_method_get_header (method);
6893 if (!image->dynamic) {
6894 /* Obtain local vars signature token */
6895 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
6896 ptr = mono_image_rva_map (image, method_rva);
6897 flags = *(const unsigned char *) ptr;
6898 format = flags & METHOD_HEADER_FORMAT_MASK;
6899 switch (format){
6900 case METHOD_HEADER_TINY_FORMAT:
6901 local_var_sig_token = 0;
6902 break;
6903 case METHOD_HEADER_FAT_FORMAT:
6904 ptr += 2;
6905 ptr += 2;
6906 ptr += 4;
6907 local_var_sig_token = read32 (ptr);
6908 break;
6909 default:
6910 g_assert_not_reached ();
6912 } else
6913 local_var_sig_token = 0; //FIXME
6915 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
6917 ret->init_locals = header->init_locals;
6918 ret->max_stack = header->max_stack;
6919 ret->local_var_sig_token = local_var_sig_token;
6920 MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
6921 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
6923 /* Locals */
6924 MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
6925 for (i = 0; i < header->num_locals; ++i) {
6926 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
6927 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
6928 info->is_pinned = header->locals [i]->pinned;
6929 info->local_index = i;
6930 mono_array_setref (ret->locals, i, info);
6933 /* Exceptions */
6934 MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
6935 for (i = 0; i < header->num_clauses; ++i) {
6936 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
6937 MonoExceptionClause *clause = &header->clauses [i];
6939 info->flags = clause->flags;
6940 info->try_offset = clause->try_offset;
6941 info->try_length = clause->try_len;
6942 info->handler_offset = clause->handler_offset;
6943 info->handler_length = clause->handler_len;
6944 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
6945 info->filter_offset = clause->data.filter_offset;
6946 else if (clause->data.catch_class)
6947 MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
6949 mono_array_setref (ret->clauses, i, info);
6952 mono_metadata_free_mh (header);
6953 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
6954 return ret;
6958 * mono_get_dbnull_object:
6959 * @domain: Domain where the object lives
6961 * Returns the System.DBNull.Value singleton object
6963 * Used as the value for ParameterInfo.DefaultValue
6965 MonoObject *
6966 mono_get_dbnull_object (MonoDomain *domain)
6968 MonoObject *obj;
6969 static MonoClassField *dbnull_value_field = NULL;
6971 if (!dbnull_value_field) {
6972 MonoClass *dbnull_klass;
6973 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
6974 mono_class_init (dbnull_klass);
6975 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
6976 g_assert (dbnull_value_field);
6978 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
6979 g_assert (obj);
6980 return obj;
6983 static void
6984 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
6986 guint32 param_index, i, lastp, crow = 0;
6987 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
6988 gint32 idx;
6990 MonoClass *klass = method->klass;
6991 MonoImage *image = klass->image;
6992 MonoMethodSignature *methodsig = mono_method_signature (method);
6994 MonoTableInfo *constt;
6995 MonoTableInfo *methodt;
6996 MonoTableInfo *paramt;
6998 if (!methodsig->param_count)
6999 return;
7001 mono_class_init (klass);
7003 if (klass->image->dynamic) {
7004 MonoReflectionMethodAux *aux;
7005 if (method->is_inflated)
7006 method = ((MonoMethodInflated*)method)->declaring;
7007 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7008 if (aux && aux->param_defaults) {
7009 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7010 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7012 return;
7015 methodt = &klass->image->tables [MONO_TABLE_METHOD];
7016 paramt = &klass->image->tables [MONO_TABLE_PARAM];
7017 constt = &image->tables [MONO_TABLE_CONSTANT];
7019 idx = mono_method_get_index (method) - 1;
7020 g_assert (idx != -1);
7022 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7023 if (idx + 1 < methodt->rows)
7024 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7025 else
7026 lastp = paramt->rows + 1;
7028 for (i = param_index; i < lastp; ++i) {
7029 guint32 paramseq;
7031 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7032 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7034 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7035 continue;
7037 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7038 if (!crow) {
7039 continue;
7042 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7043 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7044 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7047 return;
7050 MonoObject *
7051 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7053 void *retval;
7054 MonoClass *klass;
7055 MonoObject *object;
7056 MonoType *basetype = type;
7058 if (!blob)
7059 return NULL;
7061 klass = mono_class_from_mono_type (type);
7062 if (klass->valuetype) {
7063 object = mono_object_new (domain, klass);
7064 retval = ((gchar *) object + sizeof (MonoObject));
7065 if (klass->enumtype)
7066 basetype = mono_class_enum_basetype (klass);
7067 } else {
7068 retval = &object;
7071 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
7072 return object;
7073 else
7074 return NULL;
7077 static int
7078 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7079 int found_sep;
7080 char *s;
7081 gboolean quoted = FALSE;
7083 memset (assembly, 0, sizeof (MonoAssemblyName));
7084 assembly->culture = "";
7085 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7087 if (*p == '"') {
7088 quoted = TRUE;
7089 p++;
7091 assembly->name = p;
7092 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7093 p++;
7094 if (quoted) {
7095 if (*p != '"')
7096 return 1;
7097 *p = 0;
7098 p++;
7100 if (*p != ',')
7101 return 1;
7102 *p = 0;
7103 /* Remove trailing whitespace */
7104 s = p - 1;
7105 while (*s && g_ascii_isspace (*s))
7106 *s-- = 0;
7107 p ++;
7108 while (g_ascii_isspace (*p))
7109 p++;
7110 while (*p) {
7111 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7112 p += 8;
7113 assembly->major = strtoul (p, &s, 10);
7114 if (s == p || *s != '.')
7115 return 1;
7116 p = ++s;
7117 assembly->minor = strtoul (p, &s, 10);
7118 if (s == p || *s != '.')
7119 return 1;
7120 p = ++s;
7121 assembly->build = strtoul (p, &s, 10);
7122 if (s == p || *s != '.')
7123 return 1;
7124 p = ++s;
7125 assembly->revision = strtoul (p, &s, 10);
7126 if (s == p)
7127 return 1;
7128 p = s;
7129 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7130 p += 8;
7131 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7132 assembly->culture = "";
7133 p += 7;
7134 } else {
7135 assembly->culture = p;
7136 while (*p && *p != ',') {
7137 p++;
7140 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7141 p += 15;
7142 if (strncmp (p, "null", 4) == 0) {
7143 p += 4;
7144 } else {
7145 int len;
7146 gchar *start = p;
7147 while (*p && *p != ',') {
7148 p++;
7150 len = (p - start + 1);
7151 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7152 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7153 g_strlcpy ((char*)assembly->public_key_token, start, len);
7155 } else {
7156 while (*p && *p != ',')
7157 p++;
7159 found_sep = 0;
7160 while (g_ascii_isspace (*p) || *p == ',') {
7161 *p++ = 0;
7162 found_sep = 1;
7163 continue;
7165 /* failed */
7166 if (!found_sep)
7167 return 1;
7170 return 0;
7174 * mono_reflection_parse_type:
7175 * @name: type name
7177 * Parse a type name as accepted by the GetType () method and output the info
7178 * extracted in the info structure.
7179 * the name param will be mangled, so, make a copy before passing it to this function.
7180 * The fields in info will be valid until the memory pointed to by name is valid.
7182 * See also mono_type_get_name () below.
7184 * Returns: 0 on parse error.
7186 static int
7187 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7188 MonoTypeNameParse *info)
7190 char *start, *p, *w, *temp, *last_point, *startn;
7191 int in_modifiers = 0;
7192 int isbyref = 0, rank, arity = 0, i;
7194 start = p = w = name;
7196 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7197 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7198 info->name = info->name_space = NULL;
7199 info->nested = NULL;
7200 info->modifiers = NULL;
7201 info->type_arguments = NULL;
7203 /* last_point separates the namespace from the name */
7204 last_point = NULL;
7205 /* Skips spaces */
7206 while (*p == ' ') p++, start++, w++, name++;
7208 while (*p) {
7209 switch (*p) {
7210 case '+':
7211 *p = 0; /* NULL terminate the name */
7212 startn = p + 1;
7213 info->nested = g_list_append (info->nested, startn);
7214 /* we have parsed the nesting namespace + name */
7215 if (info->name)
7216 break;
7217 if (last_point) {
7218 info->name_space = start;
7219 *last_point = 0;
7220 info->name = last_point + 1;
7221 } else {
7222 info->name_space = (char *)"";
7223 info->name = start;
7225 break;
7226 case '.':
7227 last_point = p;
7228 break;
7229 case '\\':
7230 ++p;
7231 break;
7232 case '&':
7233 case '*':
7234 case '[':
7235 case ',':
7236 case ']':
7237 in_modifiers = 1;
7238 break;
7239 case '`':
7240 ++p;
7241 i = strtol (p, &temp, 10);
7242 arity += i;
7243 if (p == temp)
7244 return 0;
7245 p = temp-1;
7246 break;
7247 default:
7248 break;
7250 if (in_modifiers)
7251 break;
7252 // *w++ = *p++;
7253 p++;
7256 if (!info->name) {
7257 if (last_point) {
7258 info->name_space = start;
7259 *last_point = 0;
7260 info->name = last_point + 1;
7261 } else {
7262 info->name_space = (char *)"";
7263 info->name = start;
7266 while (*p) {
7267 switch (*p) {
7268 case '&':
7269 if (isbyref) /* only one level allowed by the spec */
7270 return 0;
7271 isbyref = 1;
7272 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7273 *p++ = 0;
7274 break;
7275 case '*':
7276 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7277 *p++ = 0;
7278 break;
7279 case '[':
7280 if (arity != 0) {
7281 *p++ = 0;
7282 info->type_arguments = g_ptr_array_new ();
7283 for (i = 0; i < arity; i++) {
7284 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7285 gboolean fqname = FALSE;
7287 g_ptr_array_add (info->type_arguments, subinfo);
7289 if (*p == '[') {
7290 p++;
7291 fqname = TRUE;
7294 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7295 return 0;
7297 /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
7298 if (fqname && (*p != ']')) {
7299 char *aname;
7301 if (*p != ',')
7302 return 0;
7303 *p++ = 0;
7305 aname = p;
7306 while (*p && (*p != ']'))
7307 p++;
7309 if (*p != ']')
7310 return 0;
7312 *p++ = 0;
7313 while (*aname) {
7314 if (g_ascii_isspace (*aname)) {
7315 ++aname;
7316 continue;
7318 break;
7320 if (!*aname ||
7321 !assembly_name_to_aname (&subinfo->assembly, aname))
7322 return 0;
7323 } else if (fqname && (*p == ']')) {
7324 *p++ = 0;
7327 if (i + 1 < arity) {
7328 if (*p != ',')
7329 return 0;
7330 } else {
7331 if (*p != ']')
7332 return 0;
7334 *p++ = 0;
7337 arity = 0;
7338 break;
7340 rank = 1;
7341 *p++ = 0;
7342 while (*p) {
7343 if (*p == ']')
7344 break;
7345 if (*p == ',')
7346 rank++;
7347 else if (*p == '*') /* '*' means unknown lower bound */
7348 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7349 else
7350 return 0;
7351 ++p;
7353 if (*p++ != ']')
7354 return 0;
7355 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7356 break;
7357 case ']':
7358 if (is_recursed)
7359 goto end;
7360 return 0;
7361 case ',':
7362 if (is_recursed)
7363 goto end;
7364 *p++ = 0;
7365 while (*p) {
7366 if (g_ascii_isspace (*p)) {
7367 ++p;
7368 continue;
7370 break;
7372 if (!*p)
7373 return 0; /* missing assembly name */
7374 if (!assembly_name_to_aname (&info->assembly, p))
7375 return 0;
7376 break;
7377 default:
7378 return 0;
7380 if (info->assembly.name)
7381 break;
7383 // *w = 0; /* terminate class name */
7384 end:
7385 if (!info->name || !*info->name)
7386 return 0;
7387 if (endptr)
7388 *endptr = p;
7389 /* add other consistency checks */
7390 return 1;
7394 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7396 return _mono_reflection_parse_type (name, NULL, FALSE, info);
7399 static MonoType*
7400 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7402 gboolean type_resolve = FALSE;
7403 MonoType *type;
7404 MonoImage *rootimage = image;
7406 if (info->assembly.name) {
7407 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7408 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7410 * This could happen in the AOT compiler case when the search hook is not
7411 * installed.
7413 assembly = image->assembly;
7414 if (!assembly) {
7415 /* then we must load the assembly ourselve - see #60439 */
7416 assembly = mono_assembly_load (&info->assembly, NULL, NULL);
7417 if (!assembly)
7418 return NULL;
7420 image = assembly->image;
7421 } else if (!image) {
7422 image = mono_defaults.corlib;
7425 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7426 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7427 image = mono_defaults.corlib;
7428 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7431 return type;
7434 static MonoType*
7435 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7437 MonoClass *klass;
7438 GList *mod;
7439 int modval;
7440 gboolean bounded = FALSE;
7442 if (!image)
7443 image = mono_defaults.corlib;
7445 if (ignorecase)
7446 klass = mono_class_from_name_case (image, info->name_space, info->name);
7447 else
7448 klass = mono_class_from_name (image, info->name_space, info->name);
7449 if (!klass)
7450 return NULL;
7451 for (mod = info->nested; mod; mod = mod->next) {
7452 gpointer iter = NULL;
7453 MonoClass *parent;
7455 parent = klass;
7456 mono_class_init (parent);
7458 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7459 if (ignorecase) {
7460 if (mono_utf8_strcasecmp (klass->name, mod->data) == 0)
7461 break;
7462 } else {
7463 if (strcmp (klass->name, mod->data) == 0)
7464 break;
7467 if (!klass)
7468 break;
7470 if (!klass)
7471 return NULL;
7473 if (info->type_arguments) {
7474 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7475 MonoReflectionType *the_type;
7476 MonoType *instance;
7477 int i;
7479 for (i = 0; i < info->type_arguments->len; i++) {
7480 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7482 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7483 if (!type_args [i]) {
7484 g_free (type_args);
7485 return NULL;
7489 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7491 instance = mono_reflection_bind_generic_parameters (
7492 the_type, info->type_arguments->len, type_args);
7494 g_free (type_args);
7495 if (!instance)
7496 return NULL;
7498 klass = mono_class_from_mono_type (instance);
7501 for (mod = info->modifiers; mod; mod = mod->next) {
7502 modval = GPOINTER_TO_UINT (mod->data);
7503 if (!modval) { /* byref: must be last modifier */
7504 return &klass->this_arg;
7505 } else if (modval == -1) {
7506 klass = mono_ptr_class_get (&klass->byval_arg);
7507 } else if (modval == -2) {
7508 bounded = TRUE;
7509 } else { /* array rank */
7510 klass = mono_bounded_array_class_get (klass, modval, bounded);
7514 return &klass->byval_arg;
7518 * mono_reflection_get_type:
7519 * @image: a metadata context
7520 * @info: type description structure
7521 * @ignorecase: flag for case-insensitive string compares
7522 * @type_resolve: whenever type resolve was already tried
7524 * Build a MonoType from the type description in @info.
7528 MonoType*
7529 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7530 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7533 static MonoType*
7534 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7536 MonoReflectionAssemblyBuilder *abuilder;
7537 MonoType *type;
7538 int i;
7540 g_assert (assembly->dynamic);
7541 abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (((MonoDynamicAssembly*)assembly)->domain, assembly);
7543 /* Enumerate all modules */
7545 type = NULL;
7546 if (abuilder->modules) {
7547 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7548 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7549 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7550 if (type)
7551 break;
7555 if (!type && abuilder->loaded_modules) {
7556 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7557 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7558 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7559 if (type)
7560 break;
7564 return type;
7567 MonoType*
7568 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7570 MonoType *type;
7571 MonoReflectionAssembly *assembly;
7572 GString *fullName;
7573 GList *mod;
7575 if (image && image->dynamic)
7576 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7577 else
7578 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7579 if (type)
7580 return type;
7581 if (!mono_domain_has_type_resolve (mono_domain_get ()))
7582 return NULL;
7584 if (type_resolve) {
7585 if (*type_resolve)
7586 return NULL;
7587 else
7588 *type_resolve = TRUE;
7591 /* Reconstruct the type name */
7592 fullName = g_string_new ("");
7593 if (info->name_space && (info->name_space [0] != '\0'))
7594 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7595 else
7596 g_string_printf (fullName, "%s", info->name);
7597 for (mod = info->nested; mod; mod = mod->next)
7598 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7600 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7601 if (assembly) {
7602 if (assembly->assembly->dynamic)
7603 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7604 else
7605 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
7606 info, ignorecase);
7608 g_string_free (fullName, TRUE);
7609 return type;
7612 void
7613 mono_reflection_free_type_info (MonoTypeNameParse *info)
7615 g_list_free (info->modifiers);
7616 g_list_free (info->nested);
7618 if (info->type_arguments) {
7619 int i;
7621 for (i = 0; i < info->type_arguments->len; i++) {
7622 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7624 mono_reflection_free_type_info (subinfo);
7625 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7626 g_free (subinfo);
7629 g_ptr_array_free (info->type_arguments, TRUE);
7634 * mono_reflection_type_from_name:
7635 * @name: type name.
7636 * @image: a metadata context (can be NULL).
7638 * Retrieves a MonoType from its @name. If the name is not fully qualified,
7639 * it defaults to get the type from @image or, if @image is NULL or loading
7640 * from it fails, uses corlib.
7643 MonoType*
7644 mono_reflection_type_from_name (char *name, MonoImage *image)
7646 MonoType *type = NULL;
7647 MonoTypeNameParse info;
7648 char *tmp;
7650 /* Make a copy since parse_type modifies its argument */
7651 tmp = g_strdup (name);
7653 /*g_print ("requested type %s\n", str);*/
7654 if (mono_reflection_parse_type (tmp, &info)) {
7655 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7658 g_free (tmp);
7659 mono_reflection_free_type_info (&info);
7660 return type;
7664 * mono_reflection_get_token:
7666 * Return the metadata token of OBJ which should be an object
7667 * representing a metadata element.
7669 guint32
7670 mono_reflection_get_token (MonoObject *obj)
7672 MonoClass *klass;
7673 guint32 token = 0;
7675 klass = obj->vtable->klass;
7677 if (strcmp (klass->name, "MethodBuilder") == 0) {
7678 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7680 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7681 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7682 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7684 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7685 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7686 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7688 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
7689 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7690 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7691 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7692 } else if (strcmp (klass->name, "MonoType") == 0) {
7693 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
7694 MonoClass *mc = mono_class_from_mono_type (type);
7695 if (!mono_class_init (mc))
7696 mono_raise_exception (mono_class_get_exception_for_failure (mc));
7698 token = mc->type_token;
7699 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7700 strcmp (klass->name, "MonoMethod") == 0 ||
7701 strcmp (klass->name, "MonoGenericMethod") == 0 ||
7702 strcmp (klass->name, "MonoGenericCMethod") == 0) {
7703 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7704 if (m->method->is_inflated) {
7705 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7706 return inflated->declaring->token;
7707 } else {
7708 token = m->method->token;
7710 } else if (strcmp (klass->name, "MonoField") == 0) {
7711 MonoReflectionField *f = (MonoReflectionField*)obj;
7713 if (is_field_on_inst (f->field)) {
7714 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
7715 int field_index = f->field - dgclass->fields;
7716 MonoObject *obj;
7718 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
7719 obj = dgclass->field_objects [field_index];
7720 return mono_reflection_get_token (obj);
7722 token = mono_class_get_field_token (f->field);
7723 } else if (strcmp (klass->name, "MonoProperty") == 0) {
7724 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7726 token = mono_class_get_property_token (p->property);
7727 } else if (strcmp (klass->name, "MonoEvent") == 0) {
7728 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
7730 token = mono_class_get_event_token (p->event);
7731 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
7732 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7733 MonoClass *member_class = mono_object_class (p->MemberImpl);
7734 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
7736 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7737 } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
7738 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7740 token = m->token;
7741 } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
7742 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7743 } else {
7744 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7745 MonoException *ex = mono_get_exception_not_implemented (msg);
7746 g_free (msg);
7747 mono_raise_exception (ex);
7750 return token;
7753 static void*
7754 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
7756 int slen, type = t->type;
7757 MonoClass *tklass = t->data.klass;
7759 handle_enum:
7760 switch (type) {
7761 case MONO_TYPE_U1:
7762 case MONO_TYPE_I1:
7763 case MONO_TYPE_BOOLEAN: {
7764 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7765 *bval = *p;
7766 *end = p + 1;
7767 return bval;
7769 case MONO_TYPE_CHAR:
7770 case MONO_TYPE_U2:
7771 case MONO_TYPE_I2: {
7772 guint16 *val = g_malloc (sizeof (guint16));
7773 *val = read16 (p);
7774 *end = p + 2;
7775 return val;
7777 #if SIZEOF_VOID_P == 4
7778 case MONO_TYPE_U:
7779 case MONO_TYPE_I:
7780 #endif
7781 case MONO_TYPE_R4:
7782 case MONO_TYPE_U4:
7783 case MONO_TYPE_I4: {
7784 guint32 *val = g_malloc (sizeof (guint32));
7785 *val = read32 (p);
7786 *end = p + 4;
7787 return val;
7789 #if SIZEOF_VOID_P == 8
7790 case MONO_TYPE_U: /* error out instead? this should probably not happen */
7791 case MONO_TYPE_I:
7792 #endif
7793 case MONO_TYPE_U8:
7794 case MONO_TYPE_I8: {
7795 guint64 *val = g_malloc (sizeof (guint64));
7796 *val = read64 (p);
7797 *end = p + 8;
7798 return val;
7800 case MONO_TYPE_R8: {
7801 double *val = g_malloc (sizeof (double));
7802 readr8 (p, val);
7803 *end = p + 8;
7804 return val;
7806 case MONO_TYPE_VALUETYPE:
7807 if (t->data.klass->enumtype) {
7808 type = mono_class_enum_basetype (t->data.klass)->type;
7809 goto handle_enum;
7810 } else {
7811 MonoClass *k = t->data.klass;
7813 if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
7814 guint64 *val = g_malloc (sizeof (guint64));
7815 *val = read64 (p);
7816 *end = p + 8;
7817 return val;
7820 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7821 break;
7823 case MONO_TYPE_STRING:
7824 if (*p == (char)0xFF) {
7825 *end = p + 1;
7826 return NULL;
7828 slen = mono_metadata_decode_value (p, &p);
7829 *end = p + slen;
7830 return mono_string_new_len (mono_domain_get (), p, slen);
7831 case MONO_TYPE_CLASS: {
7832 char *n;
7833 MonoType *t;
7834 if (*p == (char)0xFF) {
7835 *end = p + 1;
7836 return NULL;
7838 handle_type:
7839 slen = mono_metadata_decode_value (p, &p);
7840 n = g_memdup (p, slen + 1);
7841 n [slen] = 0;
7842 t = mono_reflection_type_from_name (n, image);
7843 if (!t)
7844 g_warning ("Cannot load type '%s'", n);
7845 g_free (n);
7846 *end = p + slen;
7847 if (t)
7848 return mono_type_get_object (mono_domain_get (), t);
7849 else
7850 return NULL;
7852 case MONO_TYPE_OBJECT: {
7853 char subt = *p++;
7854 MonoObject *obj;
7855 MonoClass *subc = NULL;
7856 void *val;
7858 if (subt == 0x50) {
7859 goto handle_type;
7860 } else if (subt == 0x0E) {
7861 type = MONO_TYPE_STRING;
7862 goto handle_enum;
7863 } else if (subt == 0x1D) {
7864 MonoType simple_type = {{0}};
7865 int etype = *p;
7866 p ++;
7868 type = MONO_TYPE_SZARRAY;
7869 if (etype == 0x50) {
7870 tklass = mono_defaults.systemtype_class;
7871 } else {
7872 if (etype == 0x51)
7873 /* See Partition II, Appendix B3 */
7874 etype = MONO_TYPE_OBJECT;
7875 simple_type.type = etype;
7876 tklass = mono_class_from_mono_type (&simple_type);
7878 goto handle_enum;
7879 } else if (subt == 0x55) {
7880 char *n;
7881 MonoType *t;
7882 slen = mono_metadata_decode_value (p, &p);
7883 n = g_memdup (p, slen + 1);
7884 n [slen] = 0;
7885 t = mono_reflection_type_from_name (n, image);
7886 if (!t)
7887 g_error ("Cannot load type '%s'", n);
7888 g_free (n);
7889 p += slen;
7890 subc = mono_class_from_mono_type (t);
7891 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
7892 MonoType simple_type = {{0}};
7893 simple_type.type = subt;
7894 subc = mono_class_from_mono_type (&simple_type);
7895 } else {
7896 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
7898 val = load_cattr_value (image, &subc->byval_arg, p, end);
7899 obj = mono_object_new (mono_domain_get (), subc);
7900 g_assert (!subc->has_references);
7901 mono_gc_memmove ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
7902 g_free (val);
7903 return obj;
7905 case MONO_TYPE_SZARRAY: {
7906 MonoArray *arr;
7907 guint32 i, alen, basetype;
7908 alen = read32 (p);
7909 p += 4;
7910 if (alen == 0xffffffff) {
7911 *end = p;
7912 return NULL;
7914 arr = mono_array_new (mono_domain_get(), tklass, alen);
7915 basetype = tklass->byval_arg.type;
7916 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
7917 basetype = mono_class_enum_basetype (tklass)->type;
7918 switch (basetype)
7920 case MONO_TYPE_U1:
7921 case MONO_TYPE_I1:
7922 case MONO_TYPE_BOOLEAN:
7923 for (i = 0; i < alen; i++) {
7924 MonoBoolean val = *p++;
7925 mono_array_set (arr, MonoBoolean, i, val);
7927 break;
7928 case MONO_TYPE_CHAR:
7929 case MONO_TYPE_U2:
7930 case MONO_TYPE_I2:
7931 for (i = 0; i < alen; i++) {
7932 guint16 val = read16 (p);
7933 mono_array_set (arr, guint16, i, val);
7934 p += 2;
7936 break;
7937 case MONO_TYPE_R4:
7938 case MONO_TYPE_U4:
7939 case MONO_TYPE_I4:
7940 for (i = 0; i < alen; i++) {
7941 guint32 val = read32 (p);
7942 mono_array_set (arr, guint32, i, val);
7943 p += 4;
7945 break;
7946 case MONO_TYPE_R8:
7947 for (i = 0; i < alen; i++) {
7948 double val;
7949 readr8 (p, &val);
7950 mono_array_set (arr, double, i, val);
7951 p += 8;
7953 break;
7954 case MONO_TYPE_U8:
7955 case MONO_TYPE_I8:
7956 for (i = 0; i < alen; i++) {
7957 guint64 val = read64 (p);
7958 mono_array_set (arr, guint64, i, val);
7959 p += 8;
7961 break;
7962 case MONO_TYPE_CLASS:
7963 case MONO_TYPE_OBJECT:
7964 case MONO_TYPE_STRING:
7965 for (i = 0; i < alen; i++) {
7966 MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
7967 mono_array_setref (arr, i, item);
7969 break;
7970 default:
7971 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
7973 *end=p;
7974 return arr;
7976 default:
7977 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
7979 return NULL;
7982 static MonoObject*
7983 create_cattr_typed_arg (MonoType *t, MonoObject *val)
7985 static MonoClass *klass;
7986 static MonoMethod *ctor;
7987 MonoObject *retval;
7988 void *params [2], *unboxed;
7990 if (!klass)
7991 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
7992 if (!ctor)
7993 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7995 params [0] = mono_type_get_object (mono_domain_get (), t);
7996 params [1] = val;
7997 retval = mono_object_new (mono_domain_get (), klass);
7998 unboxed = mono_object_unbox (retval);
7999 mono_runtime_invoke (ctor, unboxed, params, NULL);
8001 return retval;
8004 static MonoObject*
8005 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
8007 static MonoClass *klass;
8008 static MonoMethod *ctor;
8009 MonoObject *retval;
8010 void *unboxed, *params [2];
8012 if (!klass)
8013 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
8014 if (!ctor)
8015 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8017 params [0] = minfo;
8018 params [1] = typedarg;
8019 retval = mono_object_new (mono_domain_get (), klass);
8020 unboxed = mono_object_unbox (retval);
8021 mono_runtime_invoke (ctor, unboxed, params, NULL);
8023 return retval;
8026 static gboolean
8027 type_is_reference (MonoType *type)
8029 switch (type->type) {
8030 case MONO_TYPE_BOOLEAN:
8031 case MONO_TYPE_CHAR:
8032 case MONO_TYPE_U:
8033 case MONO_TYPE_I:
8034 case MONO_TYPE_U1:
8035 case MONO_TYPE_I1:
8036 case MONO_TYPE_U2:
8037 case MONO_TYPE_I2:
8038 case MONO_TYPE_U4:
8039 case MONO_TYPE_I4:
8040 case MONO_TYPE_U8:
8041 case MONO_TYPE_I8:
8042 case MONO_TYPE_R8:
8043 case MONO_TYPE_R4:
8044 case MONO_TYPE_VALUETYPE:
8045 return FALSE;
8046 default:
8047 return TRUE;
8051 static void
8052 free_param_data (MonoMethodSignature *sig, void **params) {
8053 int i;
8054 for (i = 0; i < sig->param_count; ++i) {
8055 if (!type_is_reference (sig->params [i]))
8056 g_free (params [i]);
8061 * Find the field index in the metadata FieldDef table.
8063 static guint32
8064 find_field_index (MonoClass *klass, MonoClassField *field) {
8065 int i;
8067 for (i = 0; i < klass->field.count; ++i) {
8068 if (field == &klass->fields [i])
8069 return klass->field.first + 1 + i;
8071 return 0;
8075 * Find the property index in the metadata Property table.
8077 static guint32
8078 find_property_index (MonoClass *klass, MonoProperty *property) {
8079 int i;
8081 for (i = 0; i < klass->ext->property.count; ++i) {
8082 if (property == &klass->ext->properties [i])
8083 return klass->ext->property.first + 1 + i;
8085 return 0;
8089 * Find the event index in the metadata Event table.
8091 static guint32
8092 find_event_index (MonoClass *klass, MonoEvent *event) {
8093 int i;
8095 for (i = 0; i < klass->ext->event.count; ++i) {
8096 if (event == &klass->ext->events [i])
8097 return klass->ext->event.first + 1 + i;
8099 return 0;
8102 static MonoObject*
8103 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
8105 const char *p = (const char*)data;
8106 const char *named;
8107 guint32 i, j, num_named;
8108 MonoObject *attr;
8109 void *params_buf [32];
8110 void **params;
8111 MonoMethodSignature *sig;
8113 mono_error_init (error);
8115 mono_class_init (method->klass);
8117 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8118 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8119 return NULL;
8122 if (len == 0) {
8123 attr = mono_object_new (mono_domain_get (), method->klass);
8124 mono_runtime_invoke (method, attr, NULL, NULL);
8125 return attr;
8128 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8129 return NULL;
8131 /*g_print ("got attr %s\n", method->klass->name);*/
8133 sig = mono_method_signature (method);
8134 if (sig->param_count < 32)
8135 params = params_buf;
8136 else
8137 /* Allocate using GC so it gets GC tracking */
8138 params = mono_gc_alloc_fixed (sig->param_count * sizeof (void*), NULL);
8140 /* skip prolog */
8141 p += 2;
8142 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8143 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8146 named = p;
8147 attr = mono_object_new (mono_domain_get (), method->klass);
8148 mono_runtime_invoke (method, attr, params, NULL);
8149 free_param_data (method->signature, params);
8150 num_named = read16 (named);
8151 named += 2;
8152 for (j = 0; j < num_named; j++) {
8153 gint name_len;
8154 char *name, named_type, data_type;
8155 named_type = *named++;
8156 data_type = *named++; /* type of data */
8157 if (data_type == MONO_TYPE_SZARRAY)
8158 data_type = *named++;
8159 if (data_type == MONO_TYPE_ENUM) {
8160 gint type_len;
8161 char *type_name;
8162 type_len = mono_metadata_decode_blob_size (named, &named);
8163 type_name = g_malloc (type_len + 1);
8164 memcpy (type_name, named, type_len);
8165 type_name [type_len] = 0;
8166 named += type_len;
8167 /* FIXME: lookup the type and check type consistency */
8168 g_free (type_name);
8170 name_len = mono_metadata_decode_blob_size (named, &named);
8171 name = g_malloc (name_len + 1);
8172 memcpy (name, named, name_len);
8173 name [name_len] = 0;
8174 named += name_len;
8175 if (named_type == 0x53) {
8176 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
8177 void *val = load_cattr_value (image, field->type, named, &named);
8178 mono_field_set_value (attr, field, val);
8179 if (!type_is_reference (field->type))
8180 g_free (val);
8181 } else if (named_type == 0x54) {
8182 MonoProperty *prop;
8183 void *pparams [1];
8184 MonoType *prop_type;
8186 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
8187 /* can we have more that 1 arg in a custom attr named property? */
8188 prop_type = prop->get? mono_method_signature (prop->get)->ret :
8189 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8190 pparams [0] = load_cattr_value (image, prop_type, named, &named);
8191 mono_property_set_value (prop, attr, pparams, NULL);
8192 if (!type_is_reference (prop_type))
8193 g_free (pparams [0]);
8195 g_free (name);
8198 if (params != params_buf)
8199 mono_gc_free_fixed (params);
8201 return attr;
8205 * mono_reflection_create_custom_attr_data_args:
8207 * Create an array of typed and named arguments from the cattr blob given by DATA.
8208 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
8209 * NAMED_ARG_INFO will contain information about the named arguments.
8211 void
8212 mono_reflection_create_custom_attr_data_args (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoArray **typed_args, MonoArray **named_args, CattrNamedArg **named_arg_info)
8214 MonoArray *typedargs, *namedargs;
8215 MonoClass *attrklass;
8216 MonoDomain *domain;
8217 const char *p = (const char*)data;
8218 const char *named;
8219 guint32 i, j, num_named;
8220 CattrNamedArg *arginfo = NULL;
8222 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL))
8223 return;
8225 mono_class_init (method->klass);
8227 *typed_args = NULL;
8228 *named_args = NULL;
8229 *named_arg_info = NULL;
8231 domain = mono_domain_get ();
8233 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8234 return;
8236 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
8238 /* skip prolog */
8239 p += 2;
8240 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8241 MonoObject *obj;
8242 void *val;
8244 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8245 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
8246 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
8247 mono_array_setref (typedargs, i, obj);
8249 if (!type_is_reference (mono_method_signature (method)->params [i]))
8250 g_free (val);
8253 named = p;
8254 num_named = read16 (named);
8255 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
8256 named += 2;
8257 attrklass = method->klass;
8259 arginfo = g_new0 (CattrNamedArg, num_named);
8260 *named_arg_info = arginfo;
8262 for (j = 0; j < num_named; j++) {
8263 gint name_len;
8264 char *name, named_type, data_type;
8265 named_type = *named++;
8266 data_type = *named++; /* type of data */
8267 if (data_type == MONO_TYPE_SZARRAY)
8268 data_type = *named++;
8269 if (data_type == MONO_TYPE_ENUM) {
8270 gint type_len;
8271 char *type_name;
8272 type_len = mono_metadata_decode_blob_size (named, &named);
8273 type_name = g_malloc (type_len + 1);
8274 memcpy (type_name, named, type_len);
8275 type_name [type_len] = 0;
8276 named += type_len;
8277 /* FIXME: lookup the type and check type consistency */
8278 g_free (type_name);
8280 name_len = mono_metadata_decode_blob_size (named, &named);
8281 name = g_malloc (name_len + 1);
8282 memcpy (name, named, name_len);
8283 name [name_len] = 0;
8284 named += name_len;
8285 if (named_type == 0x53) {
8286 MonoObject *obj;
8287 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
8288 void *val;
8290 arginfo [j].type = field->type;
8291 arginfo [j].field = field;
8293 val = load_cattr_value (image, field->type, named, &named);
8294 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
8295 mono_array_setref (namedargs, j, obj);
8296 if (!type_is_reference (field->type))
8297 g_free (val);
8298 } else if (named_type == 0x54) {
8299 MonoObject *obj;
8300 MonoType *prop_type;
8301 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
8302 void *val;
8304 prop_type = prop->get? mono_method_signature (prop->get)->ret :
8305 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8307 arginfo [j].type = prop_type;
8308 arginfo [j].prop = prop;
8310 val = load_cattr_value (image, prop_type, named, &named);
8311 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
8312 mono_array_setref (namedargs, j, obj);
8313 if (!type_is_reference (prop_type))
8314 g_free (val);
8316 g_free (name);
8319 *typed_args = typedargs;
8320 *named_args = namedargs;
8323 void
8324 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
8326 MonoDomain *domain;
8327 MonoArray *typedargs, *namedargs;
8328 MonoImage *image;
8329 MonoMethod *method;
8330 CattrNamedArg *arginfo;
8331 int i;
8333 *ctor_args = NULL;
8334 *named_args = NULL;
8336 if (len == 0)
8337 return;
8339 image = assembly->assembly->image;
8340 method = ref_method->method;
8341 domain = mono_object_domain (ref_method);
8343 if (!mono_class_init (method->klass))
8344 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
8346 mono_reflection_create_custom_attr_data_args (image, method, data, len, &typedargs, &namedargs, &arginfo);
8347 if (mono_loader_get_last_error ())
8348 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
8350 if (!typedargs || !namedargs)
8351 return;
8353 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8354 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
8355 MonoObject *typedarg;
8357 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
8358 mono_array_setref (typedargs, i, typedarg);
8361 for (i = 0; i < mono_array_length (namedargs); ++i) {
8362 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
8363 MonoObject *typedarg, *namedarg, *minfo;
8365 if (arginfo [i].prop)
8366 minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
8367 else
8368 minfo = (MonoObject*)mono_field_get_object (domain, NULL, arginfo [i].field);
8370 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
8371 namedarg = create_cattr_named_arg (minfo, typedarg);
8373 mono_array_setref (namedargs, i, namedarg);
8376 *ctor_args = typedargs;
8377 *named_args = namedargs;
8380 static MonoObject*
8381 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr)
8383 static MonoMethod *ctor;
8384 MonoDomain *domain;
8385 MonoObject *attr;
8386 void *params [4];
8388 g_assert (image->assembly);
8390 if (!ctor)
8391 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
8393 domain = mono_domain_get ();
8394 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8395 params [0] = mono_method_get_object (domain, cattr->ctor, NULL);
8396 params [1] = mono_assembly_get_object (domain, image->assembly);
8397 params [2] = (gpointer)&cattr->data;
8398 params [3] = &cattr->data_size;
8399 mono_runtime_invoke (ctor, attr, params, NULL);
8400 return attr;
8403 static MonoArray*
8404 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
8406 MonoArray *result;
8407 MonoObject *attr;
8408 int i, n;
8410 mono_error_init (error);
8412 n = 0;
8413 for (i = 0; i < cinfo->num_attrs; ++i) {
8414 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
8415 n ++;
8418 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
8419 n = 0;
8420 for (i = 0; i < cinfo->num_attrs; ++i) {
8421 if (!cinfo->attrs [i].ctor)
8422 /* The cattr type is not finished yet */
8423 /* We should include the type name but cinfo doesn't contain it */
8424 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
8425 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
8426 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
8427 if (!mono_error_ok (error))
8428 return result;
8429 mono_array_setref (result, n, attr);
8430 n ++;
8433 return result;
8436 MonoArray*
8437 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
8439 MonoError error;
8441 return mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
8444 static MonoArray*
8445 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
8447 MonoArray *result;
8448 MonoObject *attr;
8449 int i;
8451 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
8452 for (i = 0; i < cinfo->num_attrs; ++i) {
8453 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i]);
8454 mono_array_setref (result, i, attr);
8456 return result;
8460 * mono_custom_attrs_from_index:
8462 * Returns: NULL if no attributes are found or if a loading error occurs.
8464 MonoCustomAttrInfo*
8465 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
8467 guint32 mtoken, i, len;
8468 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
8469 MonoTableInfo *ca;
8470 MonoCustomAttrInfo *ainfo;
8471 GList *tmp, *list = NULL;
8472 const char *data;
8474 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
8476 i = mono_metadata_custom_attrs_from_index (image, idx);
8477 if (!i)
8478 return NULL;
8479 i --;
8480 while (i < ca->rows) {
8481 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
8482 break;
8483 list = g_list_prepend (list, GUINT_TO_POINTER (i));
8484 ++i;
8486 len = g_list_length (list);
8487 if (!len)
8488 return NULL;
8489 ainfo = g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
8490 ainfo->num_attrs = len;
8491 ainfo->image = image;
8492 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
8493 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
8494 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
8495 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
8496 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
8497 mtoken |= MONO_TOKEN_METHOD_DEF;
8498 break;
8499 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
8500 mtoken |= MONO_TOKEN_MEMBER_REF;
8501 break;
8502 default:
8503 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
8504 break;
8506 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
8507 if (!ainfo->attrs [i].ctor) {
8508 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
8509 g_list_free (list);
8510 g_free (ainfo);
8511 return NULL;
8514 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
8515 /*FIXME raising an exception here doesn't make any sense*/
8516 g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
8517 g_list_free (list);
8518 g_free (ainfo);
8519 return NULL;
8521 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
8522 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
8523 ainfo->attrs [i].data = (guchar*)data;
8525 g_list_free (list);
8527 return ainfo;
8530 MonoCustomAttrInfo*
8531 mono_custom_attrs_from_method (MonoMethod *method)
8533 guint32 idx;
8536 * An instantiated method has the same cattrs as the generic method definition.
8538 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8539 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8541 if (method->is_inflated)
8542 method = ((MonoMethodInflated *) method)->declaring;
8544 if (method->dynamic || method->klass->image->dynamic)
8545 return lookup_custom_attr (method->klass->image, method);
8547 if (!method->token)
8548 /* Synthetic methods */
8549 return NULL;
8551 idx = mono_method_get_index (method);
8552 idx <<= MONO_CUSTOM_ATTR_BITS;
8553 idx |= MONO_CUSTOM_ATTR_METHODDEF;
8554 return mono_custom_attrs_from_index (method->klass->image, idx);
8557 MonoCustomAttrInfo*
8558 mono_custom_attrs_from_class (MonoClass *klass)
8560 guint32 idx;
8562 if (klass->generic_class)
8563 klass = klass->generic_class->container_class;
8565 if (klass->image->dynamic)
8566 return lookup_custom_attr (klass->image, klass);
8568 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
8569 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
8570 idx <<= MONO_CUSTOM_ATTR_BITS;
8571 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
8572 } else {
8573 idx = mono_metadata_token_index (klass->type_token);
8574 idx <<= MONO_CUSTOM_ATTR_BITS;
8575 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
8577 return mono_custom_attrs_from_index (klass->image, idx);
8580 MonoCustomAttrInfo*
8581 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
8583 guint32 idx;
8585 if (assembly->image->dynamic)
8586 return lookup_custom_attr (assembly->image, assembly);
8587 idx = 1; /* there is only one assembly */
8588 idx <<= MONO_CUSTOM_ATTR_BITS;
8589 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
8590 return mono_custom_attrs_from_index (assembly->image, idx);
8593 static MonoCustomAttrInfo*
8594 mono_custom_attrs_from_module (MonoImage *image)
8596 guint32 idx;
8598 if (image->dynamic)
8599 return lookup_custom_attr (image, image);
8600 idx = 1; /* there is only one module */
8601 idx <<= MONO_CUSTOM_ATTR_BITS;
8602 idx |= MONO_CUSTOM_ATTR_MODULE;
8603 return mono_custom_attrs_from_index (image, idx);
8606 MonoCustomAttrInfo*
8607 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
8609 guint32 idx;
8611 if (klass->image->dynamic) {
8612 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
8613 return lookup_custom_attr (klass->image, property);
8615 idx = find_property_index (klass, property);
8616 idx <<= MONO_CUSTOM_ATTR_BITS;
8617 idx |= MONO_CUSTOM_ATTR_PROPERTY;
8618 return mono_custom_attrs_from_index (klass->image, idx);
8621 MonoCustomAttrInfo*
8622 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
8624 guint32 idx;
8626 if (klass->image->dynamic) {
8627 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
8628 return lookup_custom_attr (klass->image, event);
8630 idx = find_event_index (klass, event);
8631 idx <<= MONO_CUSTOM_ATTR_BITS;
8632 idx |= MONO_CUSTOM_ATTR_EVENT;
8633 return mono_custom_attrs_from_index (klass->image, idx);
8636 MonoCustomAttrInfo*
8637 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
8639 guint32 idx;
8640 if (klass->image->dynamic) {
8641 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
8642 return lookup_custom_attr (klass->image, field);
8644 idx = find_field_index (klass, field);
8645 idx <<= MONO_CUSTOM_ATTR_BITS;
8646 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
8647 return mono_custom_attrs_from_index (klass->image, idx);
8650 MonoCustomAttrInfo*
8651 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
8653 MonoTableInfo *ca;
8654 guint32 i, idx, method_index;
8655 guint32 param_list, param_last, param_pos, found;
8656 MonoImage *image;
8657 MonoReflectionMethodAux *aux;
8660 * An instantiated method has the same cattrs as the generic method definition.
8662 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8663 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8665 if (method->is_inflated)
8666 method = ((MonoMethodInflated *) method)->declaring;
8668 if (method->klass->image->dynamic) {
8669 MonoCustomAttrInfo *res, *ainfo;
8670 int size;
8672 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8673 if (!aux || !aux->param_cattr)
8674 return NULL;
8676 /* Need to copy since it will be freed later */
8677 ainfo = aux->param_cattr [param];
8678 if (!ainfo)
8679 return NULL;
8680 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
8681 res = g_malloc0 (size);
8682 memcpy (res, ainfo, size);
8683 return res;
8686 image = method->klass->image;
8687 method_index = mono_method_get_index (method);
8688 if (!method_index)
8689 return NULL;
8690 ca = &image->tables [MONO_TABLE_METHOD];
8692 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
8693 if (method_index == ca->rows) {
8694 ca = &image->tables [MONO_TABLE_PARAM];
8695 param_last = ca->rows + 1;
8696 } else {
8697 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
8698 ca = &image->tables [MONO_TABLE_PARAM];
8700 found = FALSE;
8701 for (i = param_list; i < param_last; ++i) {
8702 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
8703 if (param_pos == param) {
8704 found = TRUE;
8705 break;
8708 if (!found)
8709 return NULL;
8710 idx = i;
8711 idx <<= MONO_CUSTOM_ATTR_BITS;
8712 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
8713 return mono_custom_attrs_from_index (image, idx);
8716 gboolean
8717 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8719 int i;
8720 MonoClass *klass;
8721 for (i = 0; i < ainfo->num_attrs; ++i) {
8722 klass = ainfo->attrs [i].ctor->klass;
8723 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
8724 return TRUE;
8726 return FALSE;
8729 MonoObject*
8730 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8732 int i, attr_index;
8733 MonoClass *klass;
8734 MonoArray *attrs;
8736 attr_index = -1;
8737 for (i = 0; i < ainfo->num_attrs; ++i) {
8738 klass = ainfo->attrs [i].ctor->klass;
8739 if (mono_class_has_parent (klass, attr_klass)) {
8740 attr_index = i;
8741 break;
8744 if (attr_index == -1)
8745 return NULL;
8747 attrs = mono_custom_attrs_construct (ainfo);
8748 if (attrs)
8749 return mono_array_get (attrs, MonoObject*, attr_index);
8750 else
8751 return NULL;
8755 * mono_reflection_get_custom_attrs_info:
8756 * @obj: a reflection object handle
8758 * Return the custom attribute info for attributes defined for the
8759 * reflection handle @obj. The objects.
8761 * FIXME this function leaks like a sieve for SRE objects.
8763 MonoCustomAttrInfo*
8764 mono_reflection_get_custom_attrs_info (MonoObject *obj)
8766 MonoClass *klass;
8767 MonoCustomAttrInfo *cinfo = NULL;
8769 klass = obj->vtable->klass;
8770 if (klass == mono_defaults.monotype_class) {
8771 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
8772 klass = mono_class_from_mono_type (type);
8773 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
8774 cinfo = mono_custom_attrs_from_class (klass);
8775 } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
8776 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
8777 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
8778 } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
8779 MonoReflectionModule *module = (MonoReflectionModule*)obj;
8780 cinfo = mono_custom_attrs_from_module (module->image);
8781 } else if (strcmp ("MonoProperty", klass->name) == 0) {
8782 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
8783 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
8784 } else if (strcmp ("MonoEvent", klass->name) == 0) {
8785 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
8786 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
8787 } else if (strcmp ("MonoField", klass->name) == 0) {
8788 MonoReflectionField *rfield = (MonoReflectionField*)obj;
8789 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
8790 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
8791 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8792 cinfo = mono_custom_attrs_from_method (rmethod->method);
8793 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
8794 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8795 cinfo = mono_custom_attrs_from_method (rmethod->method);
8796 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
8797 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
8798 MonoClass *member_class = mono_object_class (param->MemberImpl);
8799 if (mono_class_is_reflection_method_or_constructor (member_class)) {
8800 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8801 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
8802 } else if (is_sr_mono_property (member_class)) {
8803 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
8804 MonoMethod *method;
8805 if (!(method = prop->property->get))
8806 method = prop->property->set;
8807 g_assert (method);
8809 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8811 #ifndef DISABLE_REFLECTION_EMIT
8812 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
8813 MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl);
8814 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8815 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
8816 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
8817 MonoMethod *method = NULL;
8818 if (is_sre_ctor_builder (mono_object_class (c->cb)))
8819 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
8820 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
8821 method = ((MonoReflectionMethod *)c->cb)->method;
8822 else
8823 g_error ("mono_reflection_get_custom_attrs_info:: can't handle a CTBI with base_method of type %s", mono_type_get_full_name (member_class));
8825 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8827 #endif
8828 else {
8829 char *type_name = mono_type_get_full_name (member_class);
8830 char *msg = g_strdup_printf ("Custom attributes on a ParamInfo with member %s are not supported", type_name);
8831 MonoException *ex = mono_get_exception_not_supported (msg);
8832 g_free (type_name);
8833 g_free (msg);
8834 mono_raise_exception (ex);
8836 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
8837 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
8838 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
8839 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
8840 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8841 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
8842 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
8843 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
8844 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
8845 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
8846 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8847 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
8848 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
8849 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8850 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
8851 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
8852 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8853 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
8854 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
8855 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
8856 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
8857 } else { /* handle other types here... */
8858 g_error ("get custom attrs not yet supported for %s", klass->name);
8861 return cinfo;
8865 * mono_reflection_get_custom_attrs_by_type:
8866 * @obj: a reflection object handle
8868 * Return an array with all the custom attributes defined of the
8869 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
8870 * of that type are returned. The objects are fully build. Return NULL if a loading error
8871 * occurs.
8873 MonoArray*
8874 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
8876 MonoArray *result;
8877 MonoCustomAttrInfo *cinfo;
8879 mono_error_init (error);
8881 cinfo = mono_reflection_get_custom_attrs_info (obj);
8882 if (cinfo) {
8883 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
8884 if (!cinfo->cached)
8885 mono_custom_attrs_free (cinfo);
8886 } else {
8887 if (mono_loader_get_last_error ())
8888 return NULL;
8889 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
8892 return result;
8896 * mono_reflection_get_custom_attrs:
8897 * @obj: a reflection object handle
8899 * Return an array with all the custom attributes defined of the
8900 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
8901 * occurs.
8903 MonoArray*
8904 mono_reflection_get_custom_attrs (MonoObject *obj)
8906 MonoError error;
8908 return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
8912 * mono_reflection_get_custom_attrs_data:
8913 * @obj: a reflection obj handle
8915 * Returns an array of System.Reflection.CustomAttributeData,
8916 * which include information about attributes reflected on
8917 * types loaded using the Reflection Only methods
8919 MonoArray*
8920 mono_reflection_get_custom_attrs_data (MonoObject *obj)
8922 MonoArray *result;
8923 MonoCustomAttrInfo *cinfo;
8925 cinfo = mono_reflection_get_custom_attrs_info (obj);
8926 if (cinfo) {
8927 result = mono_custom_attrs_data_construct (cinfo);
8928 if (!cinfo->cached)
8929 mono_custom_attrs_free (cinfo);
8930 } else
8931 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
8933 return result;
8936 static MonoReflectionType*
8937 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
8939 static MonoMethod *method_get_underlying_system_type = NULL;
8940 MonoMethod *usertype_method;
8942 if (!method_get_underlying_system_type)
8943 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
8944 usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
8945 return (MonoReflectionType *) mono_runtime_invoke (usertype_method, t, NULL, NULL);
8949 static gboolean
8950 is_corlib_type (MonoClass *class)
8952 return class->image == mono_defaults.corlib;
8955 #define check_corlib_type_cached(_class, _namespace, _name) do { \
8956 static MonoClass *cached_class; \
8957 if (cached_class) \
8958 return cached_class == _class; \
8959 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
8960 cached_class = _class; \
8961 return TRUE; \
8963 return FALSE; \
8964 } while (0) \
8967 #ifndef DISABLE_REFLECTION_EMIT
8968 static gboolean
8969 is_sre_array (MonoClass *class)
8971 check_corlib_type_cached (class, "System.Reflection.Emit", "ArrayType");
8974 static gboolean
8975 is_sre_byref (MonoClass *class)
8977 check_corlib_type_cached (class, "System.Reflection.Emit", "ByRefType");
8980 static gboolean
8981 is_sre_pointer (MonoClass *class)
8983 check_corlib_type_cached (class, "System.Reflection.Emit", "PointerType");
8986 static gboolean
8987 is_sre_generic_instance (MonoClass *class)
8989 check_corlib_type_cached (class, "System.Reflection", "MonoGenericClass");
8992 static gboolean
8993 is_sre_type_builder (MonoClass *class)
8995 check_corlib_type_cached (class, "System.Reflection.Emit", "TypeBuilder");
8998 static gboolean
8999 is_sre_method_builder (MonoClass *class)
9001 check_corlib_type_cached (class, "System.Reflection.Emit", "MethodBuilder");
9004 static gboolean
9005 is_sre_ctor_builder (MonoClass *class)
9007 check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorBuilder");
9010 static gboolean
9011 is_sre_field_builder (MonoClass *class)
9013 check_corlib_type_cached (class, "System.Reflection.Emit", "FieldBuilder");
9016 static gboolean
9017 is_sre_method_on_tb_inst (MonoClass *class)
9019 check_corlib_type_cached (class, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
9022 static gboolean
9023 is_sre_ctor_on_tb_inst (MonoClass *class)
9025 check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
9028 MonoType*
9029 mono_reflection_type_get_handle (MonoReflectionType* ref)
9031 MonoClass *class;
9032 if (!ref)
9033 return NULL;
9034 if (ref->type)
9035 return ref->type;
9037 if (is_usertype (ref)) {
9038 ref = mono_reflection_type_get_underlying_system_type (ref);
9039 if (ref == NULL || is_usertype (ref))
9040 return NULL;
9041 if (ref->type)
9042 return ref->type;
9045 class = mono_object_class (ref);
9047 if (is_sre_array (class)) {
9048 MonoType *res;
9049 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
9050 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
9051 g_assert (base);
9052 if (sre_array->rank == 0) //single dimentional array
9053 res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
9054 else
9055 res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
9056 sre_array->type.type = res;
9057 return res;
9058 } else if (is_sre_byref (class)) {
9059 MonoType *res;
9060 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
9061 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
9062 g_assert (base);
9063 res = &mono_class_from_mono_type (base)->this_arg;
9064 sre_byref->type.type = res;
9065 return res;
9066 } else if (is_sre_pointer (class)) {
9067 MonoType *res;
9068 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
9069 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
9070 g_assert (base);
9071 res = &mono_ptr_class_get (base)->byval_arg;
9072 sre_pointer->type.type = res;
9073 return res;
9074 } else if (is_sre_generic_instance (class)) {
9075 MonoType *res, **types;
9076 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
9077 int i, count;
9079 count = mono_array_length (gclass->type_arguments);
9080 types = g_new0 (MonoType*, count);
9081 for (i = 0; i < count; ++i) {
9082 MonoReflectionType *t = mono_array_get (gclass->type_arguments, gpointer, i);
9083 types [i] = mono_reflection_type_get_handle (t);
9084 if (!types[i]) {
9085 g_free (types);
9086 return NULL;
9090 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
9091 g_free (types);
9092 g_assert (res);
9093 gclass->type.type = res;
9094 return res;
9097 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
9098 return NULL;
9103 void
9104 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
9106 mono_reflection_type_get_handle (type);
9109 void
9110 mono_reflection_register_with_runtime (MonoReflectionType *type)
9112 MonoType *res = mono_reflection_type_get_handle (type);
9113 MonoDomain *domain = mono_object_domain ((MonoObject*)type);
9114 MonoClass *class;
9116 if (!res)
9117 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
9119 class = mono_class_from_mono_type (res);
9121 mono_loader_lock (); /*same locking as mono_type_get_object*/
9122 mono_domain_lock (domain);
9124 if (!class->image->dynamic) {
9125 mono_class_setup_supertypes (class);
9126 } else {
9127 if (!domain->type_hash)
9128 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
9129 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC);
9130 mono_g_hash_table_insert (domain->type_hash, res, type);
9132 mono_domain_unlock (domain);
9133 mono_loader_unlock ();
9137 * LOCKING: Assumes the loader lock is held.
9139 static MonoMethodSignature*
9140 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
9141 MonoMethodSignature *sig;
9142 int count, i;
9144 count = parameters? mono_array_length (parameters): 0;
9146 sig = image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
9147 sig->param_count = count;
9148 sig->sentinelpos = -1; /* FIXME */
9149 for (i = 0; i < count; ++i)
9150 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
9151 return sig;
9155 * LOCKING: Assumes the loader lock is held.
9157 static MonoMethodSignature*
9158 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
9159 MonoMethodSignature *sig;
9161 sig = parameters_to_signature (image, ctor->parameters);
9162 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9163 sig->ret = &mono_defaults.void_class->byval_arg;
9164 return sig;
9168 * LOCKING: Assumes the loader lock is held.
9170 static MonoMethodSignature*
9171 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
9172 MonoMethodSignature *sig;
9174 sig = parameters_to_signature (image, method->parameters);
9175 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9176 sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
9177 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
9178 return sig;
9181 static MonoMethodSignature*
9182 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
9183 MonoMethodSignature *sig;
9185 sig = parameters_to_signature (NULL, method->parameters);
9186 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9187 sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
9188 sig->generic_param_count = 0;
9189 return sig;
9192 static void
9193 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
9195 MonoClass *klass = mono_object_class (prop);
9196 if (strcmp (klass->name, "PropertyBuilder") == 0) {
9197 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
9198 *name = mono_string_to_utf8 (pb->name);
9199 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
9200 } else {
9201 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
9202 *name = g_strdup (p->property->name);
9203 if (p->property->get)
9204 *type = mono_method_signature (p->property->get)->ret;
9205 else
9206 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
9210 static void
9211 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
9213 MonoClass *klass = mono_object_class (field);
9214 if (strcmp (klass->name, "FieldBuilder") == 0) {
9215 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
9216 *name = mono_string_to_utf8 (fb->name);
9217 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9218 } else {
9219 MonoReflectionField *f = (MonoReflectionField *)field;
9220 *name = g_strdup (mono_field_get_name (f->field));
9221 *type = f->field->type;
9225 #else /* DISABLE_REFLECTION_EMIT */
9227 void
9228 mono_reflection_register_with_runtime (MonoReflectionType *type)
9230 /* This is empty */
9233 static gboolean
9234 is_sre_type_builder (MonoClass *class)
9236 return FALSE;
9239 static gboolean
9240 is_sre_generic_instance (MonoClass *class)
9242 return FALSE;
9245 static void
9246 init_type_builder_generics (MonoObject *type)
9250 #endif /* !DISABLE_REFLECTION_EMIT */
9253 static gboolean
9254 is_sr_mono_field (MonoClass *class)
9256 check_corlib_type_cached (class, "System.Reflection", "MonoField");
9259 static gboolean
9260 is_sr_mono_property (MonoClass *class)
9262 check_corlib_type_cached (class, "System.Reflection", "MonoProperty");
9265 static gboolean
9266 is_sr_mono_method (MonoClass *class)
9268 check_corlib_type_cached (class, "System.Reflection", "MonoMethod");
9271 static gboolean
9272 is_sr_mono_cmethod (MonoClass *class)
9274 check_corlib_type_cached (class, "System.Reflection", "MonoCMethod");
9277 static gboolean
9278 is_sr_mono_generic_method (MonoClass *class)
9280 check_corlib_type_cached (class, "System.Reflection", "MonoGenericMethod");
9283 static gboolean
9284 is_sr_mono_generic_cmethod (MonoClass *class)
9286 check_corlib_type_cached (class, "System.Reflection", "MonoGenericCMethod");
9289 gboolean
9290 mono_class_is_reflection_method_or_constructor (MonoClass *class)
9292 return is_sr_mono_method (class) || is_sr_mono_cmethod (class) || is_sr_mono_generic_method (class) || is_sr_mono_generic_cmethod (class);
9295 static gboolean
9296 is_usertype (MonoReflectionType *ref)
9298 MonoClass *class = mono_object_class (ref);
9299 return class->image != mono_defaults.corlib || strcmp ("TypeDelegator", class->name) == 0;
9302 static MonoReflectionType*
9303 mono_reflection_type_resolve_user_types (MonoReflectionType *type)
9305 if (!type || type->type)
9306 return type;
9308 if (is_usertype (type)) {
9309 type = mono_reflection_type_get_underlying_system_type (type);
9310 if (is_usertype (type))
9311 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported22"));
9314 return type;
9317 * Encode a value in a custom attribute stream of bytes.
9318 * The value to encode is either supplied as an object in argument val
9319 * (valuetypes are boxed), or as a pointer to the data in the
9320 * argument argval.
9321 * @type represents the type of the value
9322 * @buffer is the start of the buffer
9323 * @p the current position in the buffer
9324 * @buflen contains the size of the buffer and is used to return the new buffer size
9325 * if this needs to be realloced.
9326 * @retbuffer and @retp return the start and the position of the buffer
9328 static void
9329 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
9331 MonoTypeEnum simple_type;
9333 if ((p-buffer) + 10 >= *buflen) {
9334 char *newbuf;
9335 *buflen *= 2;
9336 newbuf = g_realloc (buffer, *buflen);
9337 p = newbuf + (p-buffer);
9338 buffer = newbuf;
9340 if (!argval)
9341 argval = ((char*)arg + sizeof (MonoObject));
9342 simple_type = type->type;
9343 handle_enum:
9344 switch (simple_type) {
9345 case MONO_TYPE_BOOLEAN:
9346 case MONO_TYPE_U1:
9347 case MONO_TYPE_I1:
9348 *p++ = *argval;
9349 break;
9350 case MONO_TYPE_CHAR:
9351 case MONO_TYPE_U2:
9352 case MONO_TYPE_I2:
9353 swap_with_size (p, argval, 2, 1);
9354 p += 2;
9355 break;
9356 case MONO_TYPE_U4:
9357 case MONO_TYPE_I4:
9358 case MONO_TYPE_R4:
9359 swap_with_size (p, argval, 4, 1);
9360 p += 4;
9361 break;
9362 case MONO_TYPE_R8:
9363 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
9364 p [0] = argval [4];
9365 p [1] = argval [5];
9366 p [2] = argval [6];
9367 p [3] = argval [7];
9368 p [4] = argval [0];
9369 p [5] = argval [1];
9370 p [6] = argval [2];
9371 p [7] = argval [3];
9372 #else
9373 swap_with_size (p, argval, 8, 1);
9374 #endif
9375 p += 8;
9376 break;
9377 case MONO_TYPE_U8:
9378 case MONO_TYPE_I8:
9379 swap_with_size (p, argval, 8, 1);
9380 p += 8;
9381 break;
9382 case MONO_TYPE_VALUETYPE:
9383 if (type->data.klass->enumtype) {
9384 simple_type = mono_class_enum_basetype (type->data.klass)->type;
9385 goto handle_enum;
9386 } else {
9387 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
9389 break;
9390 case MONO_TYPE_STRING: {
9391 char *str;
9392 guint32 slen;
9393 if (!arg) {
9394 *p++ = 0xFF;
9395 break;
9397 str = mono_string_to_utf8 ((MonoString*)arg);
9398 slen = strlen (str);
9399 if ((p-buffer) + 10 + slen >= *buflen) {
9400 char *newbuf;
9401 *buflen *= 2;
9402 *buflen += slen;
9403 newbuf = g_realloc (buffer, *buflen);
9404 p = newbuf + (p-buffer);
9405 buffer = newbuf;
9407 mono_metadata_encode_value (slen, p, &p);
9408 memcpy (p, str, slen);
9409 p += slen;
9410 g_free (str);
9411 break;
9413 case MONO_TYPE_CLASS: {
9414 char *str;
9415 guint32 slen;
9416 if (!arg) {
9417 *p++ = 0xFF;
9418 break;
9420 handle_type:
9421 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
9422 slen = strlen (str);
9423 if ((p-buffer) + 10 + slen >= *buflen) {
9424 char *newbuf;
9425 *buflen *= 2;
9426 *buflen += slen;
9427 newbuf = g_realloc (buffer, *buflen);
9428 p = newbuf + (p-buffer);
9429 buffer = newbuf;
9431 mono_metadata_encode_value (slen, p, &p);
9432 memcpy (p, str, slen);
9433 p += slen;
9434 g_free (str);
9435 break;
9437 case MONO_TYPE_SZARRAY: {
9438 int len, i;
9439 MonoClass *eclass, *arg_eclass;
9441 if (!arg) {
9442 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
9443 break;
9445 len = mono_array_length ((MonoArray*)arg);
9446 *p++ = len & 0xff;
9447 *p++ = (len >> 8) & 0xff;
9448 *p++ = (len >> 16) & 0xff;
9449 *p++ = (len >> 24) & 0xff;
9450 *retp = p;
9451 *retbuffer = buffer;
9452 eclass = type->data.klass;
9453 arg_eclass = mono_object_class (arg)->element_class;
9455 if (!eclass) {
9456 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
9457 eclass = mono_defaults.object_class;
9459 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
9460 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9461 int elsize = mono_class_array_element_size (arg_eclass);
9462 for (i = 0; i < len; ++i) {
9463 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
9464 elptr += elsize;
9466 } else if (eclass->valuetype && arg_eclass->valuetype) {
9467 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9468 int elsize = mono_class_array_element_size (eclass);
9469 for (i = 0; i < len; ++i) {
9470 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
9471 elptr += elsize;
9473 } else {
9474 for (i = 0; i < len; ++i) {
9475 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
9478 break;
9480 case MONO_TYPE_OBJECT: {
9481 MonoClass *klass;
9482 char *str;
9483 guint32 slen;
9486 * The parameter type is 'object' but the type of the actual
9487 * argument is not. So we have to add type information to the blob
9488 * too. This is completely undocumented in the spec.
9491 if (arg == NULL) {
9492 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
9493 *p++ = 0xFF;
9494 break;
9497 klass = mono_object_class (arg);
9499 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
9500 *p++ = 0x50;
9501 goto handle_type;
9502 } else if (klass->enumtype) {
9503 *p++ = 0x55;
9504 } else if (klass == mono_defaults.string_class) {
9505 simple_type = MONO_TYPE_STRING;
9506 *p++ = 0x0E;
9507 goto handle_enum;
9508 } else if (klass->rank == 1) {
9509 *p++ = 0x1D;
9510 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
9511 /* See Partition II, Appendix B3 */
9512 *p++ = 0x51;
9513 else
9514 *p++ = klass->element_class->byval_arg.type;
9515 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
9516 break;
9517 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
9518 *p++ = simple_type = klass->byval_arg.type;
9519 goto handle_enum;
9520 } else {
9521 g_error ("unhandled type in custom attr");
9523 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
9524 slen = strlen (str);
9525 if ((p-buffer) + 10 + slen >= *buflen) {
9526 char *newbuf;
9527 *buflen *= 2;
9528 *buflen += slen;
9529 newbuf = g_realloc (buffer, *buflen);
9530 p = newbuf + (p-buffer);
9531 buffer = newbuf;
9533 mono_metadata_encode_value (slen, p, &p);
9534 memcpy (p, str, slen);
9535 p += slen;
9536 g_free (str);
9537 simple_type = mono_class_enum_basetype (klass)->type;
9538 goto handle_enum;
9540 default:
9541 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
9543 *retp = p;
9544 *retbuffer = buffer;
9547 static void
9548 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
9550 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9551 char *str = type_get_qualified_name (type, NULL);
9552 int slen = strlen (str);
9554 *p++ = 0x55;
9556 * This seems to be optional...
9557 * *p++ = 0x80;
9559 mono_metadata_encode_value (slen, p, &p);
9560 memcpy (p, str, slen);
9561 p += slen;
9562 g_free (str);
9563 } else if (type->type == MONO_TYPE_OBJECT) {
9564 *p++ = 0x51;
9565 } else if (type->type == MONO_TYPE_CLASS) {
9566 /* it should be a type: encode_cattr_value () has the check */
9567 *p++ = 0x50;
9568 } else {
9569 mono_metadata_encode_value (type->type, p, &p);
9570 if (type->type == MONO_TYPE_SZARRAY)
9571 /* See the examples in Partition VI, Annex B */
9572 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
9575 *retp = p;
9578 #ifndef DISABLE_REFLECTION_EMIT
9579 static void
9580 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
9582 int len;
9583 /* Preallocate a large enough buffer */
9584 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9585 char *str = type_get_qualified_name (type, NULL);
9586 len = strlen (str);
9587 g_free (str);
9588 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
9589 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
9590 len = strlen (str);
9591 g_free (str);
9592 } else {
9593 len = 0;
9595 len += strlen (name);
9597 if ((p-buffer) + 20 + len >= *buflen) {
9598 char *newbuf;
9599 *buflen *= 2;
9600 *buflen += len;
9601 newbuf = g_realloc (buffer, *buflen);
9602 p = newbuf + (p-buffer);
9603 buffer = newbuf;
9606 encode_field_or_prop_type (type, p, &p);
9608 len = strlen (name);
9609 mono_metadata_encode_value (len, p, &p);
9610 memcpy (p, name, len);
9611 p += len;
9612 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
9613 *retp = p;
9614 *retbuffer = buffer;
9618 * mono_reflection_get_custom_attrs_blob:
9619 * @ctor: custom attribute constructor
9620 * @ctorArgs: arguments o the constructor
9621 * @properties:
9622 * @propValues:
9623 * @fields:
9624 * @fieldValues:
9626 * Creates the blob of data that needs to be saved in the metadata and that represents
9627 * the custom attributed described by @ctor, @ctorArgs etc.
9628 * Returns: a Byte array representing the blob of data.
9630 MonoArray*
9631 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
9633 MonoArray *result;
9634 MonoMethodSignature *sig;
9635 MonoObject *arg;
9636 char *buffer, *p;
9637 guint32 buflen, i;
9639 MONO_ARCH_SAVE_REGS;
9641 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
9642 /* sig is freed later so allocate it in the heap */
9643 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
9644 } else {
9645 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
9648 g_assert (mono_array_length (ctorArgs) == sig->param_count);
9649 buflen = 256;
9650 p = buffer = g_malloc (buflen);
9651 /* write the prolog */
9652 *p++ = 1;
9653 *p++ = 0;
9654 for (i = 0; i < sig->param_count; ++i) {
9655 arg = mono_array_get (ctorArgs, MonoObject*, i);
9656 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
9658 i = 0;
9659 if (properties)
9660 i += mono_array_length (properties);
9661 if (fields)
9662 i += mono_array_length (fields);
9663 *p++ = i & 0xff;
9664 *p++ = (i >> 8) & 0xff;
9665 if (properties) {
9666 MonoObject *prop;
9667 for (i = 0; i < mono_array_length (properties); ++i) {
9668 MonoType *ptype;
9669 char *pname;
9671 prop = mono_array_get (properties, gpointer, i);
9672 get_prop_name_and_type (prop, &pname, &ptype);
9673 *p++ = 0x54; /* PROPERTY signature */
9674 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
9675 g_free (pname);
9679 if (fields) {
9680 MonoObject *field;
9681 for (i = 0; i < mono_array_length (fields); ++i) {
9682 MonoType *ftype;
9683 char *fname;
9685 field = mono_array_get (fields, gpointer, i);
9686 get_field_name_and_type (field, &fname, &ftype);
9687 *p++ = 0x53; /* FIELD signature */
9688 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
9689 g_free (fname);
9693 g_assert (p - buffer <= buflen);
9694 buflen = p - buffer;
9695 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9696 p = mono_array_addr (result, char, 0);
9697 memcpy (p, buffer, buflen);
9698 g_free (buffer);
9699 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
9700 g_free (sig);
9701 return result;
9705 * mono_reflection_setup_internal_class:
9706 * @tb: a TypeBuilder object
9708 * Creates a MonoClass that represents the TypeBuilder.
9709 * This is a trick that lets us simplify a lot of reflection code
9710 * (and will allow us to support Build and Run assemblies easier).
9712 void
9713 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
9715 MonoError error;
9716 MonoClass *klass, *parent;
9718 MONO_ARCH_SAVE_REGS;
9720 RESOLVE_TYPE (tb->parent);
9722 mono_loader_lock ();
9724 if (tb->parent) {
9725 /* check so we can compile corlib correctly */
9726 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
9727 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
9728 parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
9729 } else {
9730 parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
9732 } else {
9733 parent = NULL;
9736 /* the type has already being created: it means we just have to change the parent */
9737 if (tb->type.type) {
9738 klass = mono_class_from_mono_type (tb->type.type);
9739 klass->parent = NULL;
9740 /* fool mono_class_setup_parent */
9741 klass->supertypes = NULL;
9742 mono_class_setup_parent (klass, parent);
9743 mono_class_setup_mono_type (klass);
9744 mono_loader_unlock ();
9745 return;
9748 klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
9750 klass->image = &tb->module->dynamic_image->image;
9752 klass->inited = 1; /* we lie to the runtime */
9753 klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
9754 if (!mono_error_ok (&error))
9755 goto failure;
9756 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
9757 if (!mono_error_ok (&error))
9758 goto failure;
9759 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
9760 klass->flags = tb->attrs;
9762 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
9764 klass->element_class = klass;
9766 if (mono_class_get_ref_info (klass) == NULL) {
9768 mono_class_set_ref_info (klass, tb);
9770 /* Put into cache so mono_class_get () will find it.
9771 Skip nested types as those should not be available on the global scope. */
9772 if (!tb->nesting_type) {
9773 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
9774 } else {
9775 klass->image->reflection_info_unregister_classes =
9776 g_slist_prepend (klass->image->reflection_info_unregister_classes, klass);
9778 } else {
9779 g_assert (mono_class_get_ref_info (klass) == tb);
9782 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
9783 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
9785 if (parent != NULL) {
9786 mono_class_setup_parent (klass, parent);
9787 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
9788 const char *old_n = klass->name;
9789 /* trick to get relative numbering right when compiling corlib */
9790 klass->name = "BuildingObject";
9791 mono_class_setup_parent (klass, mono_defaults.object_class);
9792 klass->name = old_n;
9795 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
9796 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
9797 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
9798 klass->instance_size = sizeof (MonoObject);
9799 klass->size_inited = 1;
9800 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
9803 mono_class_setup_mono_type (klass);
9805 mono_class_setup_supertypes (klass);
9808 * FIXME: handle interfaces.
9811 tb->type.type = &klass->byval_arg;
9813 if (tb->nesting_type) {
9814 g_assert (tb->nesting_type->type);
9815 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
9818 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
9820 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
9822 mono_loader_unlock ();
9823 return;
9825 failure:
9826 mono_loader_unlock ();
9827 mono_error_raise_exception (&error);
9831 * mono_reflection_setup_generic_class:
9832 * @tb: a TypeBuilder object
9834 * Setup the generic class before adding the first generic parameter.
9836 void
9837 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
9842 * mono_reflection_create_generic_class:
9843 * @tb: a TypeBuilder object
9845 * Creates the generic class after all generic parameters have been added.
9847 void
9848 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
9850 MonoClass *klass;
9851 int count, i;
9853 MONO_ARCH_SAVE_REGS;
9855 klass = mono_class_from_mono_type (tb->type.type);
9857 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
9859 if (klass->generic_container || (count == 0))
9860 return;
9862 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
9864 klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
9866 klass->generic_container->owner.klass = klass;
9867 klass->generic_container->type_argc = count;
9868 klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
9870 klass->is_generic = 1;
9872 for (i = 0; i < count; i++) {
9873 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
9874 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
9875 klass->generic_container->type_params [i] = *param;
9876 /*Make sure we are a diferent type instance */
9877 klass->generic_container->type_params [i].param.owner = klass->generic_container;
9878 klass->generic_container->type_params [i].info.pklass = NULL;
9879 klass->generic_container->type_params [i].info.flags = gparam->attrs;
9881 g_assert (klass->generic_container->type_params [i].param.owner);
9884 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
9888 * mono_reflection_create_internal_class:
9889 * @tb: a TypeBuilder object
9891 * Actually create the MonoClass that is associated with the TypeBuilder.
9893 void
9894 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
9896 MonoClass *klass;
9898 MONO_ARCH_SAVE_REGS;
9900 klass = mono_class_from_mono_type (tb->type.type);
9902 mono_loader_lock ();
9903 if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
9904 MonoReflectionFieldBuilder *fb;
9905 MonoClass *ec;
9906 MonoType *enum_basetype;
9908 g_assert (tb->fields != NULL);
9909 g_assert (mono_array_length (tb->fields) >= 1);
9911 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
9913 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
9914 mono_loader_unlock ();
9915 return;
9918 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9919 klass->element_class = mono_class_from_mono_type (enum_basetype);
9920 if (!klass->element_class)
9921 klass->element_class = mono_class_from_mono_type (enum_basetype);
9924 * get the element_class from the current corlib.
9926 ec = default_class_from_mono_type (enum_basetype);
9927 klass->instance_size = ec->instance_size;
9928 klass->size_inited = 1;
9930 * this is almost safe to do with enums and it's needed to be able
9931 * to create objects of the enum type (for use in SetConstant).
9933 /* FIXME: Does this mean enums can't have method overrides ? */
9934 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
9936 mono_loader_unlock ();
9939 static MonoMarshalSpec*
9940 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
9941 MonoReflectionMarshal *minfo)
9943 MonoMarshalSpec *res;
9945 res = image_g_new0 (image, MonoMarshalSpec, 1);
9946 res->native = minfo->type;
9948 switch (minfo->type) {
9949 case MONO_NATIVE_LPARRAY:
9950 res->data.array_data.elem_type = minfo->eltype;
9951 if (minfo->has_size) {
9952 res->data.array_data.param_num = minfo->param_num;
9953 res->data.array_data.num_elem = minfo->count;
9954 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
9956 else {
9957 res->data.array_data.param_num = -1;
9958 res->data.array_data.num_elem = -1;
9959 res->data.array_data.elem_mult = -1;
9961 break;
9963 case MONO_NATIVE_BYVALTSTR:
9964 case MONO_NATIVE_BYVALARRAY:
9965 res->data.array_data.num_elem = minfo->count;
9966 break;
9968 case MONO_NATIVE_CUSTOM:
9969 if (minfo->marshaltyperef)
9970 res->data.custom_data.custom_name =
9971 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
9972 if (minfo->mcookie)
9973 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
9974 break;
9976 default:
9977 break;
9980 return res;
9982 #endif /* !DISABLE_REFLECTION_EMIT */
9984 MonoReflectionMarshal*
9985 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
9986 MonoMarshalSpec *spec)
9988 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
9989 MonoReflectionMarshal *minfo;
9990 MonoType *mtype;
9992 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
9993 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
9994 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
9995 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
9998 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
9999 minfo->type = spec->native;
10001 switch (minfo->type) {
10002 case MONO_NATIVE_LPARRAY:
10003 minfo->eltype = spec->data.array_data.elem_type;
10004 minfo->count = spec->data.array_data.num_elem;
10005 minfo->param_num = spec->data.array_data.param_num;
10006 break;
10008 case MONO_NATIVE_BYVALTSTR:
10009 case MONO_NATIVE_BYVALARRAY:
10010 minfo->count = spec->data.array_data.num_elem;
10011 break;
10013 case MONO_NATIVE_CUSTOM:
10014 if (spec->data.custom_data.custom_name) {
10015 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
10016 if (mtype)
10017 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
10019 MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
10021 if (spec->data.custom_data.cookie)
10022 MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
10023 break;
10025 default:
10026 break;
10029 return minfo;
10032 #ifndef DISABLE_REFLECTION_EMIT
10033 static MonoMethod*
10034 reflection_methodbuilder_to_mono_method (MonoClass *klass,
10035 ReflectionMethodBuilder *rmb,
10036 MonoMethodSignature *sig)
10038 MonoError error;
10039 MonoMethod *m;
10040 MonoMethodWrapper *wrapperm;
10041 MonoMarshalSpec **specs;
10042 MonoReflectionMethodAux *method_aux;
10043 MonoImage *image;
10044 gboolean dynamic;
10045 int i;
10047 mono_error_init (&error);
10049 * Methods created using a MethodBuilder should have their memory allocated
10050 * inside the image mempool, while dynamic methods should have their memory
10051 * malloc'd.
10053 dynamic = rmb->refs != NULL;
10054 image = dynamic ? NULL : klass->image;
10056 if (!dynamic)
10057 g_assert (!klass->generic_class);
10059 mono_loader_lock ();
10061 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
10062 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
10063 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
10064 else
10065 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
10067 wrapperm = (MonoMethodWrapper*)m;
10069 m->dynamic = dynamic;
10070 m->slot = -1;
10071 m->flags = rmb->attrs;
10072 m->iflags = rmb->iattrs;
10073 m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
10074 m->klass = klass;
10075 m->signature = sig;
10076 m->sre_method = TRUE;
10077 m->skip_visibility = rmb->skip_visibility;
10078 if (rmb->table_idx)
10079 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
10081 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
10082 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
10083 m->string_ctor = 1;
10085 m->signature->pinvoke = 1;
10086 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
10087 m->signature->pinvoke = 1;
10089 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10091 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
10092 g_assert (mono_error_ok (&error));
10093 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
10094 g_assert (mono_error_ok (&error));
10096 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
10098 if (klass->image->dynamic)
10099 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10101 mono_loader_unlock ();
10103 return m;
10104 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
10105 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
10106 MonoMethodHeader *header;
10107 guint32 code_size;
10108 gint32 max_stack, i;
10109 gint32 num_locals = 0;
10110 gint32 num_clauses = 0;
10111 guint8 *code;
10113 if (rmb->ilgen) {
10114 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
10115 code_size = rmb->ilgen->code_len;
10116 max_stack = rmb->ilgen->max_stack;
10117 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
10118 if (rmb->ilgen->ex_handlers)
10119 num_clauses = method_count_clauses (rmb->ilgen);
10120 } else {
10121 if (rmb->code) {
10122 code = mono_array_addr (rmb->code, guint8, 0);
10123 code_size = mono_array_length (rmb->code);
10124 /* we probably need to run a verifier on the code... */
10125 max_stack = 8;
10127 else {
10128 code = NULL;
10129 code_size = 0;
10130 max_stack = 8;
10134 header = image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
10135 header->code_size = code_size;
10136 header->code = image_g_malloc (image, code_size);
10137 memcpy ((char*)header->code, code, code_size);
10138 header->max_stack = max_stack;
10139 header->init_locals = rmb->init_locals;
10140 header->num_locals = num_locals;
10142 for (i = 0; i < num_locals; ++i) {
10143 MonoReflectionLocalBuilder *lb =
10144 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
10146 header->locals [i] = image_g_new0 (image, MonoType, 1);
10147 memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
10150 header->num_clauses = num_clauses;
10151 if (num_clauses) {
10152 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
10153 rmb->ilgen, num_clauses);
10156 wrapperm->header = header;
10159 if (rmb->generic_params) {
10160 int count = mono_array_length (rmb->generic_params);
10161 MonoGenericContainer *container = rmb->generic_container;
10163 g_assert (container);
10165 container->type_argc = count;
10166 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
10167 container->owner.method = m;
10169 m->is_generic = TRUE;
10170 mono_method_set_generic_container (m, container);
10172 for (i = 0; i < count; i++) {
10173 MonoReflectionGenericParam *gp =
10174 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
10175 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
10176 container->type_params [i] = *param;
10180 * The method signature might have pointers to generic parameters that belong to other methods.
10181 * This is a valid SRE case, but the resulting method signature must be encoded using the proper
10182 * generic parameters.
10184 for (i = 0; i < m->signature->param_count; ++i) {
10185 MonoType *t = m->signature->params [i];
10186 if (t->type == MONO_TYPE_MVAR) {
10187 MonoGenericParam *gparam = t->data.generic_param;
10188 if (gparam->num < count) {
10189 m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
10190 m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
10196 if (klass->generic_container) {
10197 container->parent = klass->generic_container;
10198 container->context.class_inst = klass->generic_container->context.class_inst;
10200 container->context.method_inst = mono_get_shared_generic_inst (container);
10203 if (rmb->refs) {
10204 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
10205 int i;
10206 void **data;
10208 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
10210 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
10211 data [0] = GUINT_TO_POINTER (rmb->nrefs);
10212 for (i = 0; i < rmb->nrefs; ++i)
10213 data [i + 1] = rmb->refs [i];
10216 method_aux = NULL;
10218 /* Parameter info */
10219 if (rmb->pinfo) {
10220 if (!method_aux)
10221 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10222 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
10223 for (i = 0; i <= m->signature->param_count; ++i) {
10224 MonoReflectionParamBuilder *pb;
10225 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10226 if ((i > 0) && (pb->attrs)) {
10227 /* Make a copy since it might point to a shared type structure */
10228 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
10229 m->signature->params [i - 1]->attrs = pb->attrs;
10232 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
10233 MonoDynamicImage *assembly;
10234 guint32 idx, def_type, len;
10235 char *p;
10236 const char *p2;
10238 if (!method_aux->param_defaults) {
10239 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
10240 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
10242 assembly = (MonoDynamicImage*)klass->image;
10243 idx = encode_constant (assembly, pb->def_value, &def_type);
10244 /* Copy the data from the blob since it might get realloc-ed */
10245 p = assembly->blob.data + idx;
10246 len = mono_metadata_decode_blob_size (p, &p2);
10247 len += p2 - p;
10248 method_aux->param_defaults [i] = image_g_malloc (image, len);
10249 method_aux->param_default_types [i] = def_type;
10250 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
10253 if (pb->name) {
10254 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
10255 g_assert (mono_error_ok (&error));
10257 if (pb->cattrs) {
10258 if (!method_aux->param_cattr)
10259 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
10260 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
10266 /* Parameter marshalling */
10267 specs = NULL;
10268 if (rmb->pinfo)
10269 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
10270 MonoReflectionParamBuilder *pb;
10271 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10272 if (pb->marshal_info) {
10273 if (specs == NULL)
10274 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
10275 specs [pb->position] =
10276 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
10280 if (specs != NULL) {
10281 if (!method_aux)
10282 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10283 method_aux->param_marshall = specs;
10286 if (klass->image->dynamic && method_aux)
10287 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10289 mono_loader_unlock ();
10291 return m;
10294 static MonoMethod*
10295 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
10297 ReflectionMethodBuilder rmb;
10298 MonoMethodSignature *sig;
10300 mono_loader_lock ();
10301 sig = ctor_builder_to_signature (klass->image, mb);
10302 mono_loader_unlock ();
10304 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
10306 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10307 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10309 /* If we are in a generic class, we might be called multiple times from inflate_method */
10310 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10311 /* ilgen is no longer needed */
10312 mb->ilgen = NULL;
10315 return mb->mhandle;
10318 static MonoMethod*
10319 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
10321 ReflectionMethodBuilder rmb;
10322 MonoMethodSignature *sig;
10324 mono_loader_lock ();
10325 sig = method_builder_to_signature (klass->image, mb);
10326 mono_loader_unlock ();
10328 reflection_methodbuilder_from_method_builder (&rmb, mb);
10330 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10331 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10333 /* If we are in a generic class, we might be called multiple times from inflate_method */
10334 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10335 /* ilgen is no longer needed */
10336 mb->ilgen = NULL;
10338 return mb->mhandle;
10341 static MonoClassField*
10342 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
10344 MonoClassField *field;
10345 MonoType *custom;
10346 MonoError error;
10348 field = g_new0 (MonoClassField, 1);
10350 field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
10351 g_assert (mono_error_ok (&error));
10352 if (fb->attrs || fb->modreq || fb->modopt) {
10353 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10354 field->type->attrs = fb->attrs;
10356 g_assert (klass->image->dynamic);
10357 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
10358 g_free (field->type);
10359 field->type = mono_metadata_type_dup (klass->image, custom);
10360 g_free (custom);
10361 } else {
10362 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10364 if (fb->offset != -1)
10365 field->offset = fb->offset;
10366 field->parent = klass;
10367 mono_save_custom_attrs (klass->image, field, fb->cattrs);
10369 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
10371 return field;
10373 #endif
10375 MonoType*
10376 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
10378 MonoClass *klass;
10379 MonoReflectionTypeBuilder *tb = NULL;
10380 gboolean is_dynamic = FALSE;
10381 MonoDomain *domain;
10382 MonoClass *geninst;
10384 mono_loader_lock ();
10386 domain = mono_object_domain (type);
10388 if (is_sre_type_builder (mono_object_class (type))) {
10389 tb = (MonoReflectionTypeBuilder *) type;
10391 is_dynamic = TRUE;
10392 } else if (is_sre_generic_instance (mono_object_class (type))) {
10393 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
10394 MonoReflectionType *gtd = rgi->generic_type;
10396 if (is_sre_type_builder (mono_object_class (gtd))) {
10397 tb = (MonoReflectionTypeBuilder *)gtd;
10398 is_dynamic = TRUE;
10402 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
10403 if (tb && tb->generic_container)
10404 mono_reflection_create_generic_class (tb);
10406 klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10407 if (!klass->generic_container) {
10408 mono_loader_unlock ();
10409 return NULL;
10412 if (klass->wastypebuilder) {
10413 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
10415 is_dynamic = TRUE;
10418 mono_loader_unlock ();
10420 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
10422 return &geninst->byval_arg;
10425 MonoClass*
10426 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
10428 MonoGenericClass *gclass;
10429 MonoGenericInst *inst;
10431 g_assert (klass->generic_container);
10433 inst = mono_metadata_get_generic_inst (type_argc, types);
10434 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
10436 return mono_generic_class_get_class (gclass);
10439 MonoReflectionMethod*
10440 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
10442 MonoClass *klass;
10443 MonoMethod *method, *inflated;
10444 MonoMethodInflated *imethod;
10445 MonoGenericContext tmp_context;
10446 MonoGenericInst *ginst;
10447 MonoType **type_argv;
10448 int count, i;
10450 MONO_ARCH_SAVE_REGS;
10452 /*FIXME but this no longer should happen*/
10453 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
10454 #ifndef DISABLE_REFLECTION_EMIT
10455 MonoReflectionMethodBuilder *mb = NULL;
10456 MonoReflectionTypeBuilder *tb;
10457 MonoClass *klass;
10459 mb = (MonoReflectionMethodBuilder *) rmethod;
10460 tb = (MonoReflectionTypeBuilder *) mb->type;
10461 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10463 method = methodbuilder_to_mono_method (klass, mb);
10464 #else
10465 g_assert_not_reached ();
10466 method = NULL;
10467 #endif
10468 } else {
10469 method = rmethod->method;
10472 klass = method->klass;
10474 if (method->is_inflated)
10475 method = ((MonoMethodInflated *) method)->declaring;
10477 count = mono_method_signature (method)->generic_param_count;
10478 if (count != mono_array_length (types))
10479 return NULL;
10481 type_argv = g_new0 (MonoType *, count);
10482 for (i = 0; i < count; i++) {
10483 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
10484 type_argv [i] = mono_reflection_type_get_handle (garg);
10486 ginst = mono_metadata_get_generic_inst (count, type_argv);
10487 g_free (type_argv);
10489 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
10490 tmp_context.method_inst = ginst;
10492 inflated = mono_class_inflate_generic_method (method, &tmp_context);
10493 imethod = (MonoMethodInflated *) inflated;
10495 /*FIXME but I think this is no longer necessary*/
10496 if (method->klass->image->dynamic) {
10497 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10499 * This table maps metadata structures representing inflated methods/fields
10500 * to the reflection objects representing their generic definitions.
10502 mono_loader_lock ();
10503 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
10504 mono_loader_unlock ();
10507 if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
10508 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
10510 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
10513 #ifndef DISABLE_REFLECTION_EMIT
10515 static MonoMethod *
10516 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
10518 MonoMethodInflated *imethod;
10519 MonoGenericContext *context;
10520 int i;
10523 * With generic code sharing the klass might not be inflated.
10524 * This can happen because classes inflated with their own
10525 * type arguments are "normalized" to the uninflated class.
10527 if (!klass->generic_class)
10528 return method;
10530 context = mono_class_get_context (klass);
10532 if (klass->method.count && klass->methods) {
10533 /* Find the already created inflated method */
10534 for (i = 0; i < klass->method.count; ++i) {
10535 g_assert (klass->methods [i]->is_inflated);
10536 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
10537 break;
10539 g_assert (i < klass->method.count);
10540 imethod = (MonoMethodInflated*)klass->methods [i];
10541 } else {
10542 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
10545 if (method->is_generic && method->klass->image->dynamic) {
10546 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10548 mono_loader_lock ();
10549 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
10550 mono_loader_unlock ();
10552 return (MonoMethod *) imethod;
10555 static MonoMethod *
10556 inflate_method (MonoReflectionType *type, MonoObject *obj)
10558 MonoMethod *method;
10559 MonoClass *gklass;
10561 MonoClass *type_class = mono_object_class (type);
10563 if (is_sre_generic_instance (type_class)) {
10564 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
10565 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
10566 } else if (is_sre_type_builder (type_class)) {
10567 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10568 } else if (type->type) {
10569 gklass = mono_class_from_mono_type (type->type);
10570 gklass = mono_class_get_generic_type_definition (gklass);
10571 } else {
10572 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
10575 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
10576 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
10577 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
10578 else
10579 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
10580 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
10581 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
10582 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
10583 method = ((MonoReflectionMethod *) obj)->method;
10584 else {
10585 method = NULL; /* prevent compiler warning */
10586 g_error ("can't handle type %s", obj->vtable->klass->name);
10589 return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
10592 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
10593 void
10594 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
10595 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
10596 MonoArray *events)
10598 MonoGenericClass *gclass;
10599 MonoDynamicGenericClass *dgclass;
10600 MonoClass *klass, *gklass;
10601 MonoType *gtype;
10602 int i;
10604 MONO_ARCH_SAVE_REGS;
10606 gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
10607 klass = mono_class_from_mono_type (gtype);
10608 g_assert (gtype->type == MONO_TYPE_GENERICINST);
10609 gclass = gtype->data.generic_class;
10611 if (!gclass->is_dynamic)
10612 return;
10614 dgclass = (MonoDynamicGenericClass *) gclass;
10616 if (dgclass->initialized)
10617 return;
10619 gklass = gclass->container_class;
10620 mono_class_init (gklass);
10622 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
10624 dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
10625 dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
10626 dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
10628 for (i = 0; i < dgclass->count_fields; i++) {
10629 MonoObject *obj = mono_array_get (fields, gpointer, i);
10630 MonoClassField *field, *inflated_field = NULL;
10632 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
10633 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
10634 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
10635 field = ((MonoReflectionField *) obj)->field;
10636 else {
10637 field = NULL; /* prevent compiler warning */
10638 g_assert_not_reached ();
10641 dgclass->fields [i] = *field;
10642 dgclass->fields [i].parent = klass;
10643 dgclass->fields [i].type = mono_class_inflate_generic_type (
10644 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
10645 dgclass->field_generic_types [i] = field->type;
10646 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
10647 dgclass->field_objects [i] = obj;
10649 if (inflated_field) {
10650 g_free (inflated_field);
10651 } else {
10652 dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
10656 dgclass->initialized = TRUE;
10659 void
10660 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
10662 MonoDynamicGenericClass *dgclass;
10663 int i;
10665 g_assert (gclass->is_dynamic);
10667 dgclass = (MonoDynamicGenericClass *)gclass;
10669 for (i = 0; i < dgclass->count_fields; ++i) {
10670 MonoClassField *field = dgclass->fields + i;
10671 mono_metadata_free_type (field->type);
10672 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
10676 static void
10677 fix_partial_generic_class (MonoClass *klass)
10679 MonoClass *gklass = klass->generic_class->container_class;
10680 MonoDynamicGenericClass *dgclass;
10681 int i;
10683 if (klass->wastypebuilder)
10684 return;
10686 dgclass = (MonoDynamicGenericClass *) klass->generic_class;
10687 if (klass->parent != gklass->parent) {
10688 MonoError error;
10689 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
10690 if (mono_error_ok (&error)) {
10691 MonoClass *parent = mono_class_from_mono_type (parent_type);
10692 mono_metadata_free_type (parent_type);
10693 if (parent != klass->parent) {
10694 /*fool mono_class_setup_parent*/
10695 klass->supertypes = NULL;
10696 mono_class_setup_parent (klass, parent);
10698 } else {
10699 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10700 mono_error_cleanup (&error);
10701 if (gklass->wastypebuilder)
10702 klass->wastypebuilder = TRUE;
10703 return;
10707 if (!dgclass->initialized)
10708 return;
10710 if (klass->method.count != gklass->method.count) {
10711 klass->method.count = gklass->method.count;
10712 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
10714 for (i = 0; i < klass->method.count; i++) {
10715 klass->methods [i] = mono_class_inflate_generic_method_full (
10716 gklass->methods [i], klass, mono_class_get_context (klass));
10720 if (klass->interface_count && klass->interface_count != gklass->interface_count) {
10721 klass->interface_count = gklass->interface_count;
10722 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
10723 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10725 for (i = 0; i < gklass->interface_count; ++i) {
10726 MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
10727 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
10728 mono_metadata_free_type (iface_type);
10730 ensure_runtime_vtable (klass->interfaces [i]);
10732 klass->interfaces_inited = 1;
10735 if (klass->field.count != gklass->field.count) {
10736 klass->field.count = gklass->field.count;
10737 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
10739 for (i = 0; i < klass->field.count; i++) {
10740 klass->fields [i] = gklass->fields [i];
10741 klass->fields [i].parent = klass;
10742 klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
10746 /*We can only finish with this klass once it's parent has as well*/
10747 if (gklass->wastypebuilder)
10748 klass->wastypebuilder = TRUE;
10749 return;
10752 static void
10753 ensure_generic_class_runtime_vtable (MonoClass *klass)
10755 MonoClass *gklass = klass->generic_class->container_class;
10757 ensure_runtime_vtable (gklass);
10759 fix_partial_generic_class (klass);
10762 static void
10763 ensure_runtime_vtable (MonoClass *klass)
10765 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10766 int i, num, j;
10768 if (!klass->image->dynamic || (!tb && !klass->generic_class) || klass->wastypebuilder)
10769 return;
10770 if (klass->parent)
10771 ensure_runtime_vtable (klass->parent);
10773 if (tb) {
10774 num = tb->ctors? mono_array_length (tb->ctors): 0;
10775 num += tb->num_methods;
10776 klass->method.count = num;
10777 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
10778 num = tb->ctors? mono_array_length (tb->ctors): 0;
10779 for (i = 0; i < num; ++i)
10780 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
10781 num = tb->num_methods;
10782 j = i;
10783 for (i = 0; i < num; ++i)
10784 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
10786 if (tb->interfaces) {
10787 klass->interface_count = mono_array_length (tb->interfaces);
10788 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
10789 for (i = 0; i < klass->interface_count; ++i) {
10790 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
10791 klass->interfaces [i] = mono_class_from_mono_type (iface);
10792 ensure_runtime_vtable (klass->interfaces [i]);
10794 klass->interfaces_inited = 1;
10796 } else if (klass->generic_class){
10797 ensure_generic_class_runtime_vtable (klass);
10800 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
10801 int slot_num = 0;
10802 for (i = 0; i < klass->method.count; ++i) {
10803 MonoMethod *im = klass->methods [i];
10804 if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
10805 im->slot = slot_num++;
10808 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10809 mono_class_setup_interface_offsets (klass);
10810 mono_class_setup_interface_id (klass);
10814 * The generic vtable is needed even if image->run is not set since some
10815 * runtime code like ves_icall_Type_GetMethodsByName depends on
10816 * method->slot being defined.
10820 * tb->methods could not be freed since it is used for determining
10821 * overrides during dynamic vtable construction.
10825 static MonoMethod*
10826 mono_reflection_method_get_handle (MonoObject *method)
10828 MonoClass *class = mono_object_class (method);
10829 if (is_sr_mono_method (class) || is_sr_mono_generic_method (class)) {
10830 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
10831 return sr_method->method;
10833 if (is_sre_method_builder (class)) {
10834 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
10835 return mb->mhandle;
10837 if (is_sre_method_on_tb_inst (class)) {
10838 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
10839 MonoMethod *result;
10840 /*FIXME move this to a proper method and unify with resolve_object*/
10841 if (m->method_args) {
10842 result = mono_reflection_method_on_tb_inst_get_handle (m);
10843 } else {
10844 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
10845 MonoClass *inflated_klass = mono_class_from_mono_type (type);
10846 MonoMethod *mono_method;
10848 if (is_sre_method_builder (mono_object_class (m->mb)))
10849 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
10850 else if (is_sr_mono_method (mono_object_class (m->mb)))
10851 mono_method = ((MonoReflectionMethod *)m->mb)->method;
10852 else
10853 g_error ("resolve_object:: can't handle a MTBI with base_method of type %s", mono_type_get_full_name (mono_object_class (m->mb)));
10855 result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
10857 return result;
10860 g_error ("Can't handle methods of type %s:%s", class->name_space, class->name);
10861 return NULL;
10864 void
10865 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
10867 MonoReflectionTypeBuilder *tb;
10868 int i, onum;
10870 *overrides = NULL;
10871 *num_overrides = 0;
10873 g_assert (klass->image->dynamic);
10875 if (!mono_class_get_ref_info (klass))
10876 return;
10878 g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
10880 tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
10882 onum = 0;
10883 if (tb->methods) {
10884 for (i = 0; i < tb->num_methods; ++i) {
10885 MonoReflectionMethodBuilder *mb =
10886 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10887 if (mb->override_method)
10888 onum ++;
10892 if (onum) {
10893 *overrides = g_new0 (MonoMethod*, onum * 2);
10895 onum = 0;
10896 for (i = 0; i < tb->num_methods; ++i) {
10897 MonoReflectionMethodBuilder *mb =
10898 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10899 if (mb->override_method) {
10900 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject *)mb->override_method);
10901 (*overrides) [onum * 2 + 1] = mb->mhandle;
10903 g_assert (mb->mhandle);
10905 onum ++;
10910 *num_overrides = onum;
10913 static void
10914 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
10916 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10917 MonoReflectionFieldBuilder *fb;
10918 MonoClassField *field;
10919 MonoImage *image = klass->image;
10920 const char *p, *p2;
10921 int i;
10922 guint32 len, idx, real_size = 0;
10924 klass->field.count = tb->num_fields;
10925 klass->field.first = 0;
10927 mono_error_init (error);
10929 if (tb->class_size) {
10930 g_assert ((tb->packing_size & 0xfffffff0) == 0);
10931 klass->packing_size = tb->packing_size;
10932 real_size = klass->instance_size + tb->class_size;
10935 if (!klass->field.count) {
10936 klass->instance_size = MAX (klass->instance_size, real_size);
10937 return;
10940 klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
10941 mono_class_alloc_ext (klass);
10942 klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
10944 This is, guess what, a hack.
10945 The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
10946 On the static path no field class is resolved, only types are built. This is the right thing to do
10947 but we suck.
10948 Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
10950 klass->size_inited = 1;
10952 for (i = 0; i < klass->field.count; ++i) {
10953 MonoArray *rva_data;
10954 fb = mono_array_get (tb->fields, gpointer, i);
10955 field = &klass->fields [i];
10956 field->name = mono_string_to_utf8_image (image, fb->name, error);
10957 if (!mono_error_ok (error))
10958 return;
10959 if (fb->attrs) {
10960 field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10961 field->type->attrs = fb->attrs;
10962 } else {
10963 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10966 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
10967 char *base = mono_array_addr (rva_data, char, 0);
10968 size_t size = mono_array_length (rva_data);
10969 char *data = mono_image_alloc (klass->image, size);
10970 memcpy (data, base, size);
10971 klass->ext->field_def_values [i].data = data;
10973 if (fb->offset != -1)
10974 field->offset = fb->offset;
10975 field->parent = klass;
10976 fb->handle = field;
10977 mono_save_custom_attrs (klass->image, field, fb->cattrs);
10979 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10980 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
10982 if (fb->def_value) {
10983 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
10984 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
10985 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
10986 /* Copy the data from the blob since it might get realloc-ed */
10987 p = assembly->blob.data + idx;
10988 len = mono_metadata_decode_blob_size (p, &p2);
10989 len += p2 - p;
10990 klass->ext->field_def_values [i].data = mono_image_alloc (image, len);
10991 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
10995 klass->instance_size = MAX (klass->instance_size, real_size);
10996 mono_class_layout_fields (klass);
10999 static void
11000 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
11002 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11003 MonoReflectionPropertyBuilder *pb;
11004 MonoImage *image = klass->image;
11005 MonoProperty *properties;
11006 int i;
11008 mono_error_init (error);
11010 if (!klass->ext)
11011 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11013 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
11014 klass->ext->property.first = 0;
11016 properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
11017 klass->ext->properties = properties;
11018 for (i = 0; i < klass->ext->property.count; ++i) {
11019 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
11020 properties [i].parent = klass;
11021 properties [i].attrs = pb->attrs;
11022 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
11023 if (!mono_error_ok (error))
11024 return;
11025 if (pb->get_method)
11026 properties [i].get = pb->get_method->mhandle;
11027 if (pb->set_method)
11028 properties [i].set = pb->set_method->mhandle;
11030 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
11031 if (pb->def_value) {
11032 guint32 len, idx;
11033 const char *p, *p2;
11034 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11035 if (!klass->ext->prop_def_values)
11036 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
11037 properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
11038 idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
11039 /* Copy the data from the blob since it might get realloc-ed */
11040 p = assembly->blob.data + idx;
11041 len = mono_metadata_decode_blob_size (p, &p2);
11042 len += p2 - p;
11043 klass->ext->prop_def_values [i].data = mono_image_alloc (image, len);
11044 memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
11049 MonoReflectionEvent *
11050 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11052 MonoEvent *event = g_new0 (MonoEvent, 1);
11053 MonoClass *klass;
11055 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11057 event->parent = klass;
11058 event->attrs = eb->attrs;
11059 event->name = mono_string_to_utf8 (eb->name);
11060 if (eb->add_method)
11061 event->add = eb->add_method->mhandle;
11062 if (eb->remove_method)
11063 event->remove = eb->remove_method->mhandle;
11064 if (eb->raise_method)
11065 event->raise = eb->raise_method->mhandle;
11067 #ifndef MONO_SMALL_CONFIG
11068 if (eb->other_methods) {
11069 int j;
11070 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
11071 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11072 MonoReflectionMethodBuilder *mb =
11073 mono_array_get (eb->other_methods,
11074 MonoReflectionMethodBuilder*, j);
11075 event->other [j] = mb->mhandle;
11078 #endif
11080 return mono_event_get_object (mono_object_domain (tb), klass, event);
11083 static void
11084 typebuilder_setup_events (MonoClass *klass, MonoError *error)
11086 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11087 MonoReflectionEventBuilder *eb;
11088 MonoImage *image = klass->image;
11089 MonoEvent *events;
11090 int i;
11092 mono_error_init (error);
11094 if (!klass->ext)
11095 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11097 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
11098 klass->ext->event.first = 0;
11100 events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
11101 klass->ext->events = events;
11102 for (i = 0; i < klass->ext->event.count; ++i) {
11103 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
11104 events [i].parent = klass;
11105 events [i].attrs = eb->attrs;
11106 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
11107 if (!mono_error_ok (error))
11108 return;
11109 if (eb->add_method)
11110 events [i].add = eb->add_method->mhandle;
11111 if (eb->remove_method)
11112 events [i].remove = eb->remove_method->mhandle;
11113 if (eb->raise_method)
11114 events [i].raise = eb->raise_method->mhandle;
11116 #ifndef MONO_SMALL_CONFIG
11117 if (eb->other_methods) {
11118 int j;
11119 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
11120 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11121 MonoReflectionMethodBuilder *mb =
11122 mono_array_get (eb->other_methods,
11123 MonoReflectionMethodBuilder*, j);
11124 events [i].other [j] = mb->mhandle;
11127 #endif
11128 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
11132 static gboolean
11133 remove_instantiations_of_and_ensure_contents (gpointer key,
11134 gpointer value,
11135 gpointer user_data)
11137 MonoType *type = (MonoType*)key;
11138 MonoClass *klass = (MonoClass*)user_data;
11140 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
11141 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
11142 return TRUE;
11143 } else
11144 return FALSE;
11147 static void
11148 check_array_for_usertypes (MonoArray *arr)
11150 int i;
11152 if (!arr)
11153 return;
11155 for (i = 0; i < mono_array_length (arr); ++i)
11156 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i);
11159 MonoReflectionType*
11160 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11162 MonoError error;
11163 MonoClass *klass;
11164 MonoDomain* domain;
11165 MonoReflectionType* res;
11166 int i, j;
11168 MONO_ARCH_SAVE_REGS;
11170 domain = mono_object_domain (tb);
11171 klass = mono_class_from_mono_type (tb->type.type);
11174 * Check for user defined Type subclasses.
11176 RESOLVE_TYPE (tb->parent);
11177 check_array_for_usertypes (tb->interfaces);
11178 if (tb->fields) {
11179 for (i = 0; i < mono_array_length (tb->fields); ++i) {
11180 MonoReflectionFieldBuilder *fb = mono_array_get (tb->fields, gpointer, i);
11181 if (fb) {
11182 RESOLVE_TYPE (fb->type);
11183 check_array_for_usertypes (fb->modreq);
11184 check_array_for_usertypes (fb->modopt);
11185 if (fb->marshal_info && fb->marshal_info->marshaltyperef)
11186 RESOLVE_TYPE (fb->marshal_info->marshaltyperef);
11190 if (tb->methods) {
11191 for (i = 0; i < mono_array_length (tb->methods); ++i) {
11192 MonoReflectionMethodBuilder *mb = mono_array_get (tb->methods, gpointer, i);
11193 if (mb) {
11194 RESOLVE_TYPE (mb->rtype);
11195 check_array_for_usertypes (mb->return_modreq);
11196 check_array_for_usertypes (mb->return_modopt);
11197 check_array_for_usertypes (mb->parameters);
11198 if (mb->param_modreq)
11199 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11200 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11201 if (mb->param_modopt)
11202 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11203 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11207 if (tb->ctors) {
11208 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
11209 MonoReflectionCtorBuilder *mb = mono_array_get (tb->ctors, gpointer, i);
11210 if (mb) {
11211 check_array_for_usertypes (mb->parameters);
11212 if (mb->param_modreq)
11213 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11214 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11215 if (mb->param_modopt)
11216 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11217 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11222 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
11225 * we need to lock the domain because the lock will be taken inside
11226 * So, we need to keep the locking order correct.
11228 mono_loader_lock ();
11229 mono_domain_lock (domain);
11230 if (klass->wastypebuilder) {
11231 mono_domain_unlock (domain);
11232 mono_loader_unlock ();
11233 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11236 * Fields to set in klass:
11237 * the various flags: delegate/unicode/contextbound etc.
11239 klass->flags = tb->attrs;
11240 klass->has_cctor = 1;
11241 klass->has_finalize = 1;
11242 klass->has_finalize_inited = 1;
11244 /* fool mono_class_setup_parent */
11245 klass->supertypes = NULL;
11246 mono_class_setup_parent (klass, klass->parent);
11247 mono_class_setup_mono_type (klass);
11249 #if 0
11250 if (!((MonoDynamicImage*)klass->image)->run) {
11251 if (klass->generic_container) {
11252 /* FIXME: The code below can't handle generic classes */
11253 klass->wastypebuilder = TRUE;
11254 mono_loader_unlock ();
11255 mono_domain_unlock (domain);
11256 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11259 #endif
11261 /* enums are done right away */
11262 if (!klass->enumtype)
11263 ensure_runtime_vtable (klass);
11265 if (tb->subtypes) {
11266 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
11267 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
11268 mono_class_alloc_ext (klass);
11269 klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)subtb)));
11273 klass->nested_classes_inited = TRUE;
11275 /* fields and object layout */
11276 if (klass->parent) {
11277 if (!klass->parent->size_inited)
11278 mono_class_init (klass->parent);
11279 klass->instance_size = klass->parent->instance_size;
11280 klass->sizes.class_size = 0;
11281 klass->min_align = klass->parent->min_align;
11282 /* if the type has no fields we won't call the field_setup
11283 * routine which sets up klass->has_references.
11285 klass->has_references |= klass->parent->has_references;
11286 } else {
11287 klass->instance_size = sizeof (MonoObject);
11288 klass->min_align = 1;
11291 /* FIXME: handle packing_size and instance_size */
11292 typebuilder_setup_fields (klass, &error);
11293 if (!mono_error_ok (&error))
11294 goto failure;
11295 typebuilder_setup_properties (klass, &error);
11296 if (!mono_error_ok (&error))
11297 goto failure;
11299 typebuilder_setup_events (klass, &error);
11300 if (!mono_error_ok (&error))
11301 goto failure;
11303 klass->wastypebuilder = TRUE;
11306 * If we are a generic TypeBuilder, there might be instantiations in the type cache
11307 * which have type System.Reflection.MonoGenericClass, but after the type is created,
11308 * we want to return normal System.MonoType objects, so clear these out from the cache.
11310 * Together with this we must ensure the contents of all instances to match the created type.
11312 if (domain->type_hash && klass->generic_container)
11313 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
11315 mono_domain_unlock (domain);
11316 mono_loader_unlock ();
11318 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
11319 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11320 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
11323 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11324 g_assert (res != (MonoReflectionType*)tb);
11326 return res;
11328 failure:
11329 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11330 klass->wastypebuilder = TRUE;
11331 mono_domain_unlock (domain);
11332 mono_loader_unlock ();
11333 mono_error_raise_exception (&error);
11334 return NULL;
11337 void
11338 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
11340 MonoGenericParamFull *param;
11341 MonoImage *image;
11342 MonoClass *pklass;
11343 MonoError error;
11345 MONO_ARCH_SAVE_REGS;
11347 image = &gparam->tbuilder->module->dynamic_image->image;
11349 param = mono_image_new0 (image, MonoGenericParamFull, 1);
11351 param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
11352 g_assert (mono_error_ok (&error));
11353 param->param.num = gparam->index;
11355 if (gparam->mbuilder) {
11356 if (!gparam->mbuilder->generic_container) {
11357 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
11358 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11359 gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11360 gparam->mbuilder->generic_container->is_method = TRUE;
11362 * Cannot set owner.method, since the MonoMethod is not created yet.
11363 * Set the image field instead, so type_in_image () works.
11365 gparam->mbuilder->generic_container->image = klass->image;
11367 param->param.owner = gparam->mbuilder->generic_container;
11368 } else if (gparam->tbuilder) {
11369 if (!gparam->tbuilder->generic_container) {
11370 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
11371 gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11372 gparam->tbuilder->generic_container->owner.klass = klass;
11374 param->param.owner = gparam->tbuilder->generic_container;
11377 pklass = mono_class_from_generic_parameter ((MonoGenericParam *) param, image, gparam->mbuilder != NULL);
11379 gparam->type.type = &pklass->byval_arg;
11381 mono_class_set_ref_info (pklass, gparam);
11382 mono_image_lock (image);
11383 image->reflection_info_unregister_classes = g_slist_prepend (image->reflection_info_unregister_classes, pklass);
11384 mono_image_unlock (image);
11387 MonoArray *
11388 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
11390 MonoReflectionModuleBuilder *module = sig->module;
11391 MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
11392 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11393 guint32 buflen, i;
11394 MonoArray *result;
11395 SigBuffer buf;
11397 check_array_for_usertypes (sig->arguments);
11399 sigbuffer_init (&buf, 32);
11401 sigbuffer_add_value (&buf, 0x07);
11402 sigbuffer_add_value (&buf, na);
11403 if (assembly != NULL){
11404 for (i = 0; i < na; ++i) {
11405 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11406 encode_reflection_type (assembly, type, &buf);
11410 buflen = buf.p - buf.buf;
11411 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11412 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11413 sigbuffer_free (&buf);
11415 return result;
11418 MonoArray *
11419 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
11421 MonoDynamicImage *assembly = sig->module->dynamic_image;
11422 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11423 guint32 buflen, i;
11424 MonoArray *result;
11425 SigBuffer buf;
11427 check_array_for_usertypes (sig->arguments);
11429 sigbuffer_init (&buf, 32);
11431 sigbuffer_add_value (&buf, 0x06);
11432 for (i = 0; i < na; ++i) {
11433 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11434 encode_reflection_type (assembly, type, &buf);
11437 buflen = buf.p - buf.buf;
11438 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11439 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11440 sigbuffer_free (&buf);
11442 return result;
11445 typedef struct {
11446 MonoMethod *handle;
11447 MonoDomain *domain;
11448 } DynamicMethodReleaseData;
11451 * The runtime automatically clean up those after finalization.
11453 static MonoReferenceQueue *dynamic_method_queue;
11455 static void
11456 free_dynamic_method (void *dynamic_method)
11458 DynamicMethodReleaseData *data = dynamic_method;
11460 mono_runtime_free_method (data->domain, data->handle);
11461 g_free (data);
11464 void
11465 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
11467 MonoReferenceQueue *queue;
11468 MonoMethod *handle;
11469 DynamicMethodReleaseData *release_data;
11470 ReflectionMethodBuilder rmb;
11471 MonoMethodSignature *sig;
11472 MonoClass *klass;
11473 GSList *l;
11474 int i;
11476 if (mono_runtime_is_shutting_down ())
11477 mono_raise_exception (mono_get_exception_invalid_operation (""));
11479 if (!(queue = dynamic_method_queue)) {
11480 mono_loader_lock ();
11481 if (!(queue = dynamic_method_queue))
11482 queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
11483 mono_loader_unlock ();
11486 sig = dynamic_method_to_signature (mb);
11488 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
11491 * Resolve references.
11494 * Every second entry in the refs array is reserved for storing handle_class,
11495 * which is needed by the ldtoken implementation in the JIT.
11497 rmb.nrefs = mb->nrefs;
11498 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
11499 for (i = 0; i < mb->nrefs; i += 2) {
11500 MonoClass *handle_class;
11501 gpointer ref;
11502 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
11504 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11505 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11507 * The referenced DynamicMethod should already be created by the managed
11508 * code, except in the case of circular references. In that case, we store
11509 * method in the refs array, and fix it up later when the referenced
11510 * DynamicMethod is created.
11512 if (method->mhandle) {
11513 ref = method->mhandle;
11514 } else {
11515 /* FIXME: GC object stored in unmanaged memory */
11516 ref = method;
11518 /* FIXME: GC object stored in unmanaged memory */
11519 method->referenced_by = g_slist_append (method->referenced_by, mb);
11521 handle_class = mono_defaults.methodhandle_class;
11522 } else {
11523 MonoException *ex = NULL;
11524 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
11525 if (!ref)
11526 ex = mono_get_exception_type_load (NULL, NULL);
11527 else if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
11528 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
11530 if (ex) {
11531 g_free (rmb.refs);
11532 mono_raise_exception (ex);
11533 return;
11537 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
11538 rmb.refs [i + 1] = handle_class;
11541 klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
11543 mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11544 release_data = g_new (DynamicMethodReleaseData, 1);
11545 release_data->handle = handle;
11546 release_data->domain = mono_object_get_domain ((MonoObject*)mb);
11547 if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
11548 g_free (release_data);
11550 /* Fix up refs entries pointing at us */
11551 for (l = mb->referenced_by; l; l = l->next) {
11552 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
11553 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
11554 gpointer *data;
11556 g_assert (method->mhandle);
11558 data = (gpointer*)wrapper->method_data;
11559 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
11560 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
11561 data [i + 1] = mb->mhandle;
11564 g_slist_free (mb->referenced_by);
11566 g_free (rmb.refs);
11568 /* ilgen is no longer needed */
11569 mb->ilgen = NULL;
11572 #endif /* DISABLE_REFLECTION_EMIT */
11576 * mono_reflection_is_valid_dynamic_token:
11578 * Returns TRUE if token is valid.
11581 gboolean
11582 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
11584 return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
11587 MonoMethodSignature *
11588 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token)
11590 MonoMethodSignature *sig;
11591 g_assert (image->dynamic);
11593 sig = g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
11594 if (sig)
11595 return sig;
11597 return mono_method_signature (method);
11600 #ifndef DISABLE_REFLECTION_EMIT
11603 * mono_reflection_lookup_dynamic_token:
11605 * Finish the Builder object pointed to by TOKEN and return the corresponding
11606 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
11607 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
11608 * mapping table.
11610 * LOCKING: Take the loader lock
11612 gpointer
11613 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
11615 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
11616 MonoObject *obj;
11617 MonoClass *klass;
11619 mono_loader_lock ();
11620 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
11621 mono_loader_unlock ();
11622 if (!obj) {
11623 if (valid_token)
11624 g_error ("Could not find required dynamic token 0x%08x", token);
11625 else
11626 return NULL;
11629 if (!handle_class)
11630 handle_class = &klass;
11631 return resolve_object (image, obj, handle_class, context);
11635 * ensure_complete_type:
11637 * Ensure that KLASS is completed if it is a dynamic type, or references
11638 * dynamic types.
11640 static void
11641 ensure_complete_type (MonoClass *klass)
11643 if (klass->image->dynamic && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
11644 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11646 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11648 // Asserting here could break a lot of code
11649 //g_assert (klass->wastypebuilder);
11652 if (klass->generic_class) {
11653 MonoGenericInst *inst = klass->generic_class->context.class_inst;
11654 int i;
11656 for (i = 0; i < inst->type_argc; ++i) {
11657 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
11662 static gpointer
11663 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
11665 gpointer result = NULL;
11667 if (strcmp (obj->vtable->klass->name, "String") == 0) {
11668 result = mono_string_intern ((MonoString*)obj);
11669 *handle_class = mono_defaults.string_class;
11670 g_assert (result);
11671 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
11672 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11673 MonoClass *mc = mono_class_from_mono_type (type);
11674 if (!mono_class_init (mc))
11675 mono_raise_exception (mono_class_get_exception_for_failure (mc));
11677 if (context) {
11678 MonoType *inflated = mono_class_inflate_generic_type (type, context);
11679 result = mono_class_from_mono_type (inflated);
11680 mono_metadata_free_type (inflated);
11681 } else {
11682 result = mono_class_from_mono_type (type);
11684 *handle_class = mono_defaults.typehandle_class;
11685 g_assert (result);
11686 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
11687 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
11688 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
11689 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
11690 result = ((MonoReflectionMethod*)obj)->method;
11691 if (context)
11692 result = mono_class_inflate_generic_method (result, context);
11693 *handle_class = mono_defaults.methodhandle_class;
11694 g_assert (result);
11695 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
11696 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
11697 result = mb->mhandle;
11698 if (!result) {
11699 /* Type is not yet created */
11700 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
11702 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11705 * Hopefully this has been filled in by calling CreateType() on the
11706 * TypeBuilder.
11709 * TODO: This won't work if the application finishes another
11710 * TypeBuilder instance instead of this one.
11712 result = mb->mhandle;
11714 if (context)
11715 result = mono_class_inflate_generic_method (result, context);
11716 *handle_class = mono_defaults.methodhandle_class;
11717 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
11718 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
11720 result = cb->mhandle;
11721 if (!result) {
11722 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
11724 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11725 result = cb->mhandle;
11727 if (context)
11728 result = mono_class_inflate_generic_method (result, context);
11729 *handle_class = mono_defaults.methodhandle_class;
11730 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
11731 MonoClassField *field = ((MonoReflectionField*)obj)->field;
11733 ensure_complete_type (field->parent);
11734 if (context) {
11735 MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
11736 MonoClass *class = mono_class_from_mono_type (inflated);
11737 MonoClassField *inflated_field;
11738 gpointer iter = NULL;
11739 mono_metadata_free_type (inflated);
11740 while ((inflated_field = mono_class_get_fields (class, &iter))) {
11741 if (!strcmp (field->name, inflated_field->name))
11742 break;
11744 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
11745 result = inflated_field;
11746 } else {
11747 result = field;
11749 *handle_class = mono_defaults.fieldhandle_class;
11750 g_assert (result);
11751 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
11752 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
11753 result = fb->handle;
11755 if (!result) {
11756 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
11758 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11759 result = fb->handle;
11762 if (fb->handle && fb->handle->parent->generic_container) {
11763 MonoClass *klass = fb->handle->parent;
11764 MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
11765 MonoClass *inflated = mono_class_from_mono_type (type);
11767 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
11768 g_assert (result);
11769 mono_metadata_free_type (type);
11771 *handle_class = mono_defaults.fieldhandle_class;
11772 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
11773 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
11774 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
11775 MonoClass *klass;
11777 klass = type->data.klass;
11778 if (klass->wastypebuilder) {
11779 /* Already created */
11780 result = klass;
11782 else {
11783 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11784 result = type->data.klass;
11785 g_assert (result);
11787 *handle_class = mono_defaults.typehandle_class;
11788 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
11789 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
11790 MonoMethodSignature *sig;
11791 int nargs, i;
11793 if (helper->arguments)
11794 nargs = mono_array_length (helper->arguments);
11795 else
11796 nargs = 0;
11798 sig = mono_metadata_signature_alloc (image, nargs);
11799 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
11800 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
11802 if (helper->unmanaged_call_conv) { /* unmanaged */
11803 sig->call_convention = helper->unmanaged_call_conv - 1;
11804 sig->pinvoke = TRUE;
11805 } else if (helper->call_conv & 0x02) {
11806 sig->call_convention = MONO_CALL_VARARG;
11807 } else {
11808 sig->call_convention = MONO_CALL_DEFAULT;
11811 sig->param_count = nargs;
11812 /* TODO: Copy type ? */
11813 sig->ret = helper->return_type->type;
11814 for (i = 0; i < nargs; ++i)
11815 sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
11817 result = sig;
11818 *handle_class = NULL;
11819 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11820 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11821 /* Already created by the managed code */
11822 g_assert (method->mhandle);
11823 result = method->mhandle;
11824 *handle_class = mono_defaults.methodhandle_class;
11825 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
11826 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11827 type = mono_class_inflate_generic_type (type, context);
11828 result = mono_class_from_mono_type (type);
11829 *handle_class = mono_defaults.typehandle_class;
11830 g_assert (result);
11831 mono_metadata_free_type (type);
11832 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
11833 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11834 type = mono_class_inflate_generic_type (type, context);
11835 result = mono_class_from_mono_type (type);
11836 *handle_class = mono_defaults.typehandle_class;
11837 g_assert (result);
11838 mono_metadata_free_type (type);
11839 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
11840 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
11841 MonoClass *inflated;
11842 MonoType *type;
11843 MonoClassField *field;
11845 if (is_sre_field_builder (mono_object_class (f->fb)))
11846 field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
11847 else if (is_sr_mono_field (mono_object_class (f->fb)))
11848 field = ((MonoReflectionField*)f->fb)->field;
11849 else
11850 g_error ("resolve_object:: can't handle a FTBI with base_method of type %s", mono_type_get_full_name (mono_object_class (f->fb)));
11852 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
11853 inflated = mono_class_from_mono_type (type);
11855 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
11856 ensure_complete_type (field->parent);
11857 g_assert (result);
11858 mono_metadata_free_type (type);
11859 *handle_class = mono_defaults.fieldhandle_class;
11860 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
11861 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
11862 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
11863 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11864 MonoMethod *method;
11866 if (is_sre_ctor_builder (mono_object_class (c->cb)))
11867 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
11868 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
11869 method = ((MonoReflectionMethod *)c->cb)->method;
11870 else
11871 g_error ("resolve_object:: can't handle a CTBI with base_method of type %s", mono_type_get_full_name (mono_object_class (c->cb)));
11873 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
11874 *handle_class = mono_defaults.methodhandle_class;
11875 mono_metadata_free_type (type);
11876 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
11877 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
11878 if (m->method_args) {
11879 result = mono_reflection_method_on_tb_inst_get_handle (m);
11880 if (context)
11881 result = mono_class_inflate_generic_method (result, context);
11882 } else {
11883 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
11884 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11885 MonoMethod *method;
11887 if (is_sre_method_builder (mono_object_class (m->mb)))
11888 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
11889 else if (is_sr_mono_method (mono_object_class (m->mb)))
11890 method = ((MonoReflectionMethod *)m->mb)->method;
11891 else
11892 g_error ("resolve_object:: can't handle a MTBI with base_method of type %s", mono_type_get_full_name (mono_object_class (m->mb)));
11894 result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
11895 mono_metadata_free_type (type);
11897 *handle_class = mono_defaults.methodhandle_class;
11898 } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
11899 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
11900 MonoType *mtype;
11901 MonoClass *klass;
11902 MonoMethod *method;
11903 gpointer iter;
11904 char *name;
11906 mtype = mono_reflection_type_get_handle (m->parent);
11907 klass = mono_class_from_mono_type (mtype);
11909 /* Find the method */
11911 name = mono_string_to_utf8 (m->name);
11912 iter = NULL;
11913 while ((method = mono_class_get_methods (klass, &iter))) {
11914 if (!strcmp (method->name, name))
11915 break;
11917 g_free (name);
11919 // FIXME:
11920 g_assert (method);
11921 // FIXME: Check parameters/return value etc. match
11923 result = method;
11924 *handle_class = mono_defaults.methodhandle_class;
11925 } else if (is_sre_array (mono_object_get_class(obj)) ||
11926 is_sre_byref (mono_object_get_class(obj)) ||
11927 is_sre_pointer (mono_object_get_class(obj))) {
11928 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
11929 MonoType *type = mono_reflection_type_get_handle (ref_type);
11930 result = mono_class_from_mono_type (type);
11931 *handle_class = mono_defaults.typehandle_class;
11932 } else {
11933 g_print ("%s\n", obj->vtable->klass->name);
11934 g_assert_not_reached ();
11936 return result;
11939 #else /* DISABLE_REFLECTION_EMIT */
11941 MonoArray*
11942 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
11944 g_assert_not_reached ();
11945 return NULL;
11948 void
11949 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
11951 g_assert_not_reached ();
11954 void
11955 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11957 g_assert_not_reached ();
11960 void
11961 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
11963 g_assert_not_reached ();
11966 void
11967 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11969 g_assert_not_reached ();
11972 void
11973 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
11975 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
11978 void
11979 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
11981 g_assert_not_reached ();
11984 void
11985 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
11987 g_assert_not_reached ();
11990 MonoReflectionModule *
11991 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
11993 g_assert_not_reached ();
11994 return NULL;
11997 guint32
11998 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
12000 g_assert_not_reached ();
12001 return 0;
12004 guint32
12005 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
12007 g_assert_not_reached ();
12008 return 0;
12011 guint32
12012 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
12013 gboolean create_open_instance, gboolean register_token)
12015 g_assert_not_reached ();
12016 return 0;
12019 void
12020 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
12024 void
12025 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
12026 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
12027 MonoArray *events)
12029 g_assert_not_reached ();
12032 void
12033 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12035 *overrides = NULL;
12036 *num_overrides = 0;
12039 MonoReflectionEvent *
12040 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12042 g_assert_not_reached ();
12043 return NULL;
12046 MonoReflectionType*
12047 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12049 g_assert_not_reached ();
12050 return NULL;
12053 void
12054 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12056 g_assert_not_reached ();
12059 MonoArray *
12060 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12062 g_assert_not_reached ();
12063 return NULL;
12066 MonoArray *
12067 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12069 g_assert_not_reached ();
12070 return NULL;
12073 void
12074 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12078 gpointer
12079 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12081 return NULL;
12084 MonoType*
12085 mono_reflection_type_get_handle (MonoReflectionType* ref)
12087 if (!ref)
12088 return NULL;
12089 return ref->type;
12092 void
12093 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12095 g_assert_not_reached ();
12098 #endif /* DISABLE_REFLECTION_EMIT */
12100 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
12101 const static guint32 declsec_flags_map[] = {
12102 0x00000000, /* empty */
12103 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
12104 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
12105 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
12106 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
12107 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
12108 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
12109 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
12110 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
12111 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
12112 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
12113 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
12114 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
12115 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
12116 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
12117 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
12118 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
12119 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
12120 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
12124 * Returns flags that includes all available security action associated to the handle.
12125 * @token: metadata token (either for a class or a method)
12126 * @image: image where resides the metadata.
12128 static guint32
12129 mono_declsec_get_flags (MonoImage *image, guint32 token)
12131 int index = mono_metadata_declsec_from_index (image, token);
12132 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
12133 guint32 result = 0;
12134 guint32 action;
12135 int i;
12137 /* HasSecurity can be present for other, not specially encoded, attributes,
12138 e.g. SuppressUnmanagedCodeSecurityAttribute */
12139 if (index < 0)
12140 return 0;
12142 for (i = index; i < t->rows; i++) {
12143 guint32 cols [MONO_DECL_SECURITY_SIZE];
12145 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12146 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12147 break;
12149 action = cols [MONO_DECL_SECURITY_ACTION];
12150 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
12151 result |= declsec_flags_map [action];
12152 } else {
12153 g_assert_not_reached ();
12156 return result;
12160 * Get the security actions (in the form of flags) associated with the specified method.
12162 * @method: The method for which we want the declarative security flags.
12163 * Return the declarative security flags for the method (only).
12165 * Note: To keep MonoMethod size down we do not cache the declarative security flags
12166 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
12168 guint32
12169 mono_declsec_flags_from_method (MonoMethod *method)
12171 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12172 /* FIXME: No cache (for the moment) */
12173 guint32 idx = mono_method_get_index (method);
12174 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12175 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12176 return mono_declsec_get_flags (method->klass->image, idx);
12178 return 0;
12182 * Get the security actions (in the form of flags) associated with the specified class.
12184 * @klass: The class for which we want the declarative security flags.
12185 * Return the declarative security flags for the class.
12187 * Note: We cache the flags inside the MonoClass structure as this will get
12188 * called very often (at least for each method).
12190 guint32
12191 mono_declsec_flags_from_class (MonoClass *klass)
12193 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
12194 if (!klass->ext || !klass->ext->declsec_flags) {
12195 guint32 idx;
12197 idx = mono_metadata_token_index (klass->type_token);
12198 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12199 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12200 mono_loader_lock ();
12201 mono_class_alloc_ext (klass);
12202 mono_loader_unlock ();
12203 /* we cache the flags on classes */
12204 klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
12206 return klass->ext->declsec_flags;
12208 return 0;
12212 * Get the security actions (in the form of flags) associated with the specified assembly.
12214 * @assembly: The assembly for which we want the declarative security flags.
12215 * Return the declarative security flags for the assembly.
12217 guint32
12218 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
12220 guint32 idx = 1; /* there is only one assembly */
12221 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12222 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12223 return mono_declsec_get_flags (assembly->image, idx);
12228 * Fill actions for the specific index (which may either be an encoded class token or
12229 * an encoded method token) from the metadata image.
12230 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
12232 static MonoBoolean
12233 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
12234 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12236 MonoBoolean result = FALSE;
12237 MonoTableInfo *t;
12238 guint32 cols [MONO_DECL_SECURITY_SIZE];
12239 int index = mono_metadata_declsec_from_index (image, token);
12240 int i;
12242 t = &image->tables [MONO_TABLE_DECLSECURITY];
12243 for (i = index; i < t->rows; i++) {
12244 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12246 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12247 return result;
12249 /* if present only replace (class) permissions with method permissions */
12250 /* if empty accept either class or method permissions */
12251 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
12252 if (!actions->demand.blob) {
12253 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12254 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12255 actions->demand.blob = (char*) (blob + 2);
12256 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
12257 result = TRUE;
12259 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
12260 if (!actions->noncasdemand.blob) {
12261 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12262 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12263 actions->noncasdemand.blob = (char*) (blob + 2);
12264 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
12265 result = TRUE;
12267 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
12268 if (!actions->demandchoice.blob) {
12269 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12270 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12271 actions->demandchoice.blob = (char*) (blob + 2);
12272 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
12273 result = TRUE;
12278 return result;
12281 static MonoBoolean
12282 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
12283 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12285 guint32 idx = mono_metadata_token_index (klass->type_token);
12286 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12287 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12288 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
12291 static MonoBoolean
12292 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
12293 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12295 guint32 idx = mono_method_get_index (method);
12296 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12297 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12298 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
12302 * Collect all actions (that requires to generate code in mini) assigned for
12303 * the specified method.
12304 * Note: Don't use the content of actions if the function return FALSE.
12306 MonoBoolean
12307 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
12309 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
12310 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
12311 MonoBoolean result = FALSE;
12312 guint32 flags;
12314 /* quick exit if no declarative security is present in the metadata */
12315 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12316 return FALSE;
12318 /* we want the original as the wrapper is "free" of the security informations */
12319 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12320 method = mono_marshal_method_from_wrapper (method);
12321 if (!method)
12322 return FALSE;
12325 /* First we look for method-level attributes */
12326 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12327 mono_class_init (method->klass);
12328 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12330 result = mono_declsec_get_method_demands_params (method, demands,
12331 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12334 /* Here we use (or create) the class declarative cache to look for demands */
12335 flags = mono_declsec_flags_from_class (method->klass);
12336 if (flags & mask) {
12337 if (!result) {
12338 mono_class_init (method->klass);
12339 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12341 result |= mono_declsec_get_class_demands_params (method->klass, demands,
12342 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12345 /* The boolean return value is used as a shortcut in case nothing needs to
12346 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
12347 return result;
12352 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
12354 * Note: Don't use the content of actions if the function return FALSE.
12356 MonoBoolean
12357 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
12359 MonoBoolean result = FALSE;
12360 guint32 flags;
12362 /* quick exit if no declarative security is present in the metadata */
12363 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12364 return FALSE;
12366 /* we want the original as the wrapper is "free" of the security informations */
12367 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12368 method = mono_marshal_method_from_wrapper (method);
12369 if (!method)
12370 return FALSE;
12373 /* results are independant - zeroize both */
12374 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
12375 memset (klass, 0, sizeof (MonoDeclSecurityActions));
12377 /* First we look for method-level attributes */
12378 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12379 mono_class_init (method->klass);
12381 result = mono_declsec_get_method_demands_params (method, cmethod,
12382 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12385 /* Here we use (or create) the class declarative cache to look for demands */
12386 flags = mono_declsec_flags_from_class (method->klass);
12387 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
12388 mono_class_init (method->klass);
12390 result |= mono_declsec_get_class_demands_params (method->klass, klass,
12391 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12394 return result;
12398 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12400 * @klass The inherited class - this is the class that provides the security check (attributes)
12401 * @demans
12402 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
12404 * Note: Don't use the content of actions if the function return FALSE.
12406 MonoBoolean
12407 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
12409 MonoBoolean result = FALSE;
12410 guint32 flags;
12412 /* quick exit if no declarative security is present in the metadata */
12413 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12414 return FALSE;
12416 /* Here we use (or create) the class declarative cache to look for demands */
12417 flags = mono_declsec_flags_from_class (klass);
12418 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
12419 mono_class_init (klass);
12420 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12422 result |= mono_declsec_get_class_demands_params (klass, demands,
12423 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12426 return result;
12430 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12432 * Note: Don't use the content of actions if the function return FALSE.
12434 MonoBoolean
12435 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
12437 /* quick exit if no declarative security is present in the metadata */
12438 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12439 return FALSE;
12441 /* we want the original as the wrapper is "free" of the security informations */
12442 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12443 method = mono_marshal_method_from_wrapper (method);
12444 if (!method)
12445 return FALSE;
12448 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12449 mono_class_init (method->klass);
12450 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12452 return mono_declsec_get_method_demands_params (method, demands,
12453 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12455 return FALSE;
12459 static MonoBoolean
12460 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
12462 guint32 cols [MONO_DECL_SECURITY_SIZE];
12463 MonoTableInfo *t;
12464 int i;
12466 int index = mono_metadata_declsec_from_index (image, token);
12467 if (index == -1)
12468 return FALSE;
12470 t = &image->tables [MONO_TABLE_DECLSECURITY];
12471 for (i = index; i < t->rows; i++) {
12472 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12474 /* shortcut - index are ordered */
12475 if (token != cols [MONO_DECL_SECURITY_PARENT])
12476 return FALSE;
12478 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
12479 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12480 entry->blob = (char*) (metadata + 2);
12481 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
12482 return TRUE;
12486 return FALSE;
12489 MonoBoolean
12490 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
12492 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12493 guint32 idx = mono_method_get_index (method);
12494 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12495 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12496 return get_declsec_action (method->klass->image, idx, action, entry);
12498 return FALSE;
12501 MonoBoolean
12502 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
12504 /* use cache */
12505 guint32 flags = mono_declsec_flags_from_class (klass);
12506 if (declsec_flags_map [action] & flags) {
12507 guint32 idx = mono_metadata_token_index (klass->type_token);
12508 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12509 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12510 return get_declsec_action (klass->image, idx, action, entry);
12512 return FALSE;
12515 MonoBoolean
12516 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
12518 guint32 idx = 1; /* there is only one assembly */
12519 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12520 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12522 return get_declsec_action (assembly->image, idx, action, entry);
12525 gboolean
12526 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
12528 MonoObject *res, *exc;
12529 void *params [1];
12530 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
12531 static MonoMethod *method = NULL;
12533 if (!System_Reflection_Emit_TypeBuilder) {
12534 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
12535 g_assert (System_Reflection_Emit_TypeBuilder);
12537 if (method == NULL) {
12538 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
12539 g_assert (method);
12543 * The result of mono_type_get_object () might be a System.MonoType but we
12544 * need a TypeBuilder so use mono_class_get_ref_info (klass).
12546 g_assert (mono_class_get_ref_info (klass));
12547 g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
12549 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
12551 res = mono_runtime_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc);
12552 if (exc)
12553 return FALSE;
12554 else
12555 return *(MonoBoolean*)mono_object_unbox (res);
12559 * mono_reflection_type_get_type:
12560 * @reftype: the System.Type object
12562 * Returns the MonoType* associated with the C# System.Type object @reftype.
12564 MonoType*
12565 mono_reflection_type_get_type (MonoReflectionType *reftype)
12567 g_assert (reftype);
12569 return mono_reflection_type_get_handle (reftype);