2010-05-14 Rodrigo Kumpera <rkumpera@novell.com>
[mono-project.git] / mono / metadata / reflection.c
blob7f2ff72f67a7ef5517b0f26fa2aa994ef3820952
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)
11 #include <config.h>
12 #include "mono/utils/mono-digest.h"
13 #include "mono/utils/mono-membar.h"
14 #include "mono/metadata/reflection.h"
15 #include "mono/metadata/tabledefs.h"
16 #include "mono/metadata/metadata-internals.h"
17 #include <mono/metadata/profiler-private.h>
18 #include "mono/metadata/class-internals.h"
19 #include "mono/metadata/gc-internal.h"
20 #include "mono/metadata/tokentype.h"
21 #include "mono/metadata/domain-internals.h"
22 #include "mono/metadata/opcodes.h"
23 #include "mono/metadata/assembly.h"
24 #include "mono/metadata/object-internals.h"
25 #include <mono/metadata/exception.h>
26 #include <mono/metadata/marshal.h>
27 #include <mono/metadata/security-manager.h>
28 #include <stdio.h>
29 #include <glib.h>
30 #include <errno.h>
31 #include <time.h>
32 #include <string.h>
33 #include <ctype.h>
34 #include "image.h"
35 #include "cil-coff.h"
36 #include "mono-endian.h"
37 #include <mono/metadata/gc-internal.h>
38 #include <mono/metadata/mempool-internals.h>
39 #include <mono/metadata/security-core-clr.h>
40 #include <mono/metadata/debug-helpers.h>
41 #include <mono/metadata/verify-internals.h>
42 #include <mono/metadata/mono-ptr-array.h>
43 #include <mono/utils/mono-string.h>
44 #include <mono/utils/mono-error-internals.h>
47 #if HAVE_SGEN_GC
48 static void* reflection_info_desc = NULL;
49 #define MOVING_GC_REGISTER(addr) do { \
50 if (!reflection_info_desc) { \
51 gsize bmap = 1; \
52 reflection_info_desc = mono_gc_make_descr_from_bitmap (&bmap, 1); \
53 } \
54 mono_gc_register_root ((char*)(addr), sizeof (gpointer), reflection_info_desc); \
55 } while (0)
56 #else
57 #define MOVING_GC_REGISTER(addr)
58 #endif
60 static gboolean is_usertype (MonoReflectionType *ref);
61 static MonoReflectionType *mono_reflection_type_resolve_user_types (MonoReflectionType *type);
63 typedef struct {
64 char *p;
65 char *buf;
66 char *end;
67 } SigBuffer;
69 #define TEXT_OFFSET 512
70 #define CLI_H_SIZE 136
71 #define FILE_ALIGN 512
72 #define VIRT_ALIGN 8192
73 #define START_TEXT_RVA 0x00002000
75 typedef struct {
76 MonoReflectionILGen *ilgen;
77 MonoReflectionType *rtype;
78 MonoArray *parameters;
79 MonoArray *generic_params;
80 MonoGenericContainer *generic_container;
81 MonoArray *pinfo;
82 MonoArray *opt_types;
83 guint32 attrs;
84 guint32 iattrs;
85 guint32 call_conv;
86 guint32 *table_idx; /* note: it's a pointer */
87 MonoArray *code;
88 MonoObject *type;
89 MonoString *name;
90 MonoBoolean init_locals;
91 MonoBoolean skip_visibility;
92 MonoArray *return_modreq;
93 MonoArray *return_modopt;
94 MonoArray *param_modreq;
95 MonoArray *param_modopt;
96 MonoArray *permissions;
97 MonoMethod *mhandle;
98 guint32 nrefs;
99 gpointer *refs;
100 /* for PInvoke */
101 int charset, extra_flags, native_cc;
102 MonoString *dll, *dllentry;
103 } ReflectionMethodBuilder;
105 typedef struct {
106 guint32 owner;
107 MonoReflectionGenericParam *gparam;
108 } GenericParamTableEntry;
110 const unsigned char table_sizes [MONO_TABLE_NUM] = {
111 MONO_MODULE_SIZE,
112 MONO_TYPEREF_SIZE,
113 MONO_TYPEDEF_SIZE,
115 MONO_FIELD_SIZE,
117 MONO_METHOD_SIZE,
119 MONO_PARAM_SIZE,
120 MONO_INTERFACEIMPL_SIZE,
121 MONO_MEMBERREF_SIZE, /* 0x0A */
122 MONO_CONSTANT_SIZE,
123 MONO_CUSTOM_ATTR_SIZE,
124 MONO_FIELD_MARSHAL_SIZE,
125 MONO_DECL_SECURITY_SIZE,
126 MONO_CLASS_LAYOUT_SIZE,
127 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
128 MONO_STAND_ALONE_SIGNATURE_SIZE,
129 MONO_EVENT_MAP_SIZE,
131 MONO_EVENT_SIZE,
132 MONO_PROPERTY_MAP_SIZE,
134 MONO_PROPERTY_SIZE,
135 MONO_METHOD_SEMA_SIZE,
136 MONO_METHODIMPL_SIZE,
137 MONO_MODULEREF_SIZE, /* 0x1A */
138 MONO_TYPESPEC_SIZE,
139 MONO_IMPLMAP_SIZE,
140 MONO_FIELD_RVA_SIZE,
143 MONO_ASSEMBLY_SIZE, /* 0x20 */
144 MONO_ASSEMBLY_PROCESSOR_SIZE,
145 MONO_ASSEMBLYOS_SIZE,
146 MONO_ASSEMBLYREF_SIZE,
147 MONO_ASSEMBLYREFPROC_SIZE,
148 MONO_ASSEMBLYREFOS_SIZE,
149 MONO_FILE_SIZE,
150 MONO_EXP_TYPE_SIZE,
151 MONO_MANIFEST_SIZE,
152 MONO_NESTED_CLASS_SIZE,
154 MONO_GENERICPARAM_SIZE, /* 0x2A */
155 MONO_METHODSPEC_SIZE,
156 MONO_GENPARCONSTRAINT_SIZE
160 #ifndef DISABLE_REFLECTION_EMIT
161 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
162 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec);
163 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
164 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
165 static void ensure_runtime_vtable (MonoClass *klass);
166 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
167 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method);
168 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
169 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
170 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
171 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
172 static guint32 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb);
173 #endif
175 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
176 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
177 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
178 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
179 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
180 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
181 static void encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
182 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
183 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t);
184 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
185 static MonoReflectionType* mono_reflection_type_resolve_user_types (MonoReflectionType *type);
186 static gboolean is_sre_array (MonoClass *class);
187 static gboolean is_sre_byref (MonoClass *class);
188 static gboolean is_sre_pointer (MonoClass *class);
189 static gboolean is_sre_type_builder (MonoClass *class);
190 static gboolean is_sre_method_builder (MonoClass *class);
191 static gboolean is_sre_ctor_builder (MonoClass *class);
192 static gboolean is_sre_field_builder (MonoClass *class);
193 static gboolean is_sr_mono_method (MonoClass *class);
194 static gboolean is_sr_mono_cmethod (MonoClass *class);
195 static gboolean is_sr_mono_generic_method (MonoClass *class);
196 static gboolean is_sr_mono_generic_cmethod (MonoClass *class);
197 static gboolean is_sr_mono_field (MonoClass *class);
198 static gboolean is_sr_mono_property (MonoClass *class);
199 static gboolean is_sre_method_on_tb_inst (MonoClass *class);
200 static gboolean is_sre_ctor_on_tb_inst (MonoClass *class);
202 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
203 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
204 static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj);
206 #define RESOLVE_TYPE(type) do { type = (void*)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type); } while (0)
207 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index) do { \
208 MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index); \
209 __type = mono_reflection_type_resolve_user_types (__type); \
210 mono_array_set (arr, MonoReflectionType*, index, __type); \
211 } while (0)
213 #define mono_type_array_get_and_resolve(array, index) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index))
215 void
216 mono_reflection_init (void)
220 static void
221 sigbuffer_init (SigBuffer *buf, int size)
223 buf->buf = g_malloc (size);
224 buf->p = buf->buf;
225 buf->end = buf->buf + size;
228 static void
229 sigbuffer_make_room (SigBuffer *buf, int size)
231 if (buf->end - buf->p < size) {
232 int new_size = buf->end - buf->buf + size + 32;
233 char *p = g_realloc (buf->buf, new_size);
234 size = buf->p - buf->buf;
235 buf->buf = p;
236 buf->p = p + size;
237 buf->end = buf->buf + new_size;
241 static void
242 sigbuffer_add_value (SigBuffer *buf, guint32 val)
244 sigbuffer_make_room (buf, 6);
245 mono_metadata_encode_value (val, buf->p, &buf->p);
248 static void
249 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
251 sigbuffer_make_room (buf, 1);
252 buf->p [0] = val;
253 buf->p++;
256 static void
257 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
259 sigbuffer_make_room (buf, size);
260 memcpy (buf->p, p, size);
261 buf->p += size;
264 static void
265 sigbuffer_free (SigBuffer *buf)
267 g_free (buf->buf);
270 #ifndef DISABLE_REFLECTION_EMIT
272 * mp_g_alloc:
274 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
275 * from the C heap.
277 static gpointer
278 image_g_malloc (MonoImage *image, guint size)
280 if (image)
281 return mono_image_alloc (image, size);
282 else
283 return g_malloc (size);
285 #endif /* !DISABLE_REFLECTION_EMIT */
288 * image_g_alloc0:
290 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
291 * from the C heap.
293 static gpointer
294 image_g_malloc0 (MonoImage *image, guint size)
296 if (image)
297 return mono_image_alloc0 (image, size);
298 else
299 return g_malloc0 (size);
302 #ifndef DISABLE_REFLECTION_EMIT
303 static char*
304 image_strdup (MonoImage *image, const char *s)
306 if (image)
307 return mono_image_strdup (image, s);
308 else
309 return g_strdup (s);
311 #endif
313 #define image_g_new(image,struct_type, n_structs) \
314 ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
316 #define image_g_new0(image,struct_type, n_structs) \
317 ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
320 static void
321 alloc_table (MonoDynamicTable *table, guint nrows)
323 table->rows = nrows;
324 g_assert (table->columns);
325 if (nrows + 1 >= table->alloc_rows) {
326 while (nrows + 1 >= table->alloc_rows) {
327 if (table->alloc_rows == 0)
328 table->alloc_rows = 16;
329 else
330 table->alloc_rows *= 2;
333 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
337 static void
338 make_room_in_stream (MonoDynamicStream *stream, int size)
340 if (size <= stream->alloc_size)
341 return;
343 while (stream->alloc_size <= size) {
344 if (stream->alloc_size < 4096)
345 stream->alloc_size = 4096;
346 else
347 stream->alloc_size *= 2;
350 stream->data = g_realloc (stream->data, stream->alloc_size);
353 static guint32
354 string_heap_insert (MonoDynamicStream *sh, const char *str)
356 guint32 idx;
357 guint32 len;
358 gpointer oldkey, oldval;
360 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
361 return GPOINTER_TO_UINT (oldval);
363 len = strlen (str) + 1;
364 idx = sh->index;
366 make_room_in_stream (sh, idx + len);
369 * We strdup the string even if we already copy them in sh->data
370 * so that the string pointers in the hash remain valid even if
371 * we need to realloc sh->data. We may want to avoid that later.
373 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
374 memcpy (sh->data + idx, str, len);
375 sh->index += len;
376 return idx;
379 static guint32
380 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
382 char *name = mono_string_to_utf8 (str);
383 guint32 idx;
384 idx = string_heap_insert (sh, name);
385 g_free (name);
386 return idx;
389 #ifndef DISABLE_REFLECTION_EMIT
390 static void
391 string_heap_init (MonoDynamicStream *sh)
393 sh->index = 0;
394 sh->alloc_size = 4096;
395 sh->data = g_malloc (4096);
396 sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
397 string_heap_insert (sh, "");
399 #endif
401 static guint32
402 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
404 guint32 idx;
406 make_room_in_stream (stream, stream->index + len);
407 memcpy (stream->data + stream->index, data, len);
408 idx = stream->index;
409 stream->index += len;
411 * align index? Not without adding an additional param that controls it since
412 * we may store a blob value in pieces.
414 return idx;
417 static guint32
418 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
420 guint32 idx;
422 make_room_in_stream (stream, stream->index + len);
423 memset (stream->data + stream->index, 0, len);
424 idx = stream->index;
425 stream->index += len;
426 return idx;
429 static void
430 stream_data_align (MonoDynamicStream *stream)
432 char buf [4] = {0};
433 guint32 count = stream->index % 4;
435 /* we assume the stream data will be aligned */
436 if (count)
437 mono_image_add_stream_data (stream, buf, 4 - count);
440 #ifndef DISABLE_REFLECTION_EMIT
441 static int
442 mono_blob_entry_hash (const char* str)
444 guint len, h;
445 const char *end;
446 len = mono_metadata_decode_blob_size (str, &str);
447 if (len > 0) {
448 end = str + len;
449 h = *str;
450 for (str += 1; str < end; str++)
451 h = (h << 5) - h + *str;
452 return h;
453 } else {
454 return 0;
458 static gboolean
459 mono_blob_entry_equal (const char *str1, const char *str2) {
460 int len, len2;
461 const char *end1;
462 const char *end2;
463 len = mono_metadata_decode_blob_size (str1, &end1);
464 len2 = mono_metadata_decode_blob_size (str2, &end2);
465 if (len != len2)
466 return 0;
467 return memcmp (end1, end2, len) == 0;
469 #endif
470 static guint32
471 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
473 guint32 idx;
474 char *copy;
475 gpointer oldkey, oldval;
477 copy = g_malloc (s1+s2);
478 memcpy (copy, b1, s1);
479 memcpy (copy + s1, b2, s2);
480 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
481 g_free (copy);
482 idx = GPOINTER_TO_UINT (oldval);
483 } else {
484 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
485 mono_image_add_stream_data (&assembly->blob, b2, s2);
486 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
488 return idx;
491 static guint32
492 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
494 char blob_size [8];
495 char *b = blob_size;
496 guint32 size = buf->p - buf->buf;
497 /* store length */
498 g_assert (size <= (buf->end - buf->buf));
499 mono_metadata_encode_value (size, b, &b);
500 return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
504 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
505 * dest may be misaligned.
507 static void
508 swap_with_size (char *dest, const char* val, int len, int nelem) {
509 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
510 int elem;
512 for (elem = 0; elem < nelem; ++elem) {
513 switch (len) {
514 case 1:
515 *dest = *val;
516 break;
517 case 2:
518 dest [0] = val [1];
519 dest [1] = val [0];
520 break;
521 case 4:
522 dest [0] = val [3];
523 dest [1] = val [2];
524 dest [2] = val [1];
525 dest [3] = val [0];
526 break;
527 case 8:
528 dest [0] = val [7];
529 dest [1] = val [6];
530 dest [2] = val [5];
531 dest [3] = val [4];
532 dest [4] = val [3];
533 dest [5] = val [2];
534 dest [6] = val [1];
535 dest [7] = val [0];
536 break;
537 default:
538 g_assert_not_reached ();
540 dest += len;
541 val += len;
543 #else
544 memcpy (dest, val, len * nelem);
545 #endif
548 static guint32
549 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
551 char blob_size [64];
552 char *b = blob_size;
553 guint32 idx = 0, len;
555 len = str->length * 2;
556 mono_metadata_encode_value (len, b, &b);
557 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
559 char *swapped = g_malloc (2 * mono_string_length (str));
560 const char *p = (const char*)mono_string_chars (str);
562 swap_with_size (swapped, p, 2, mono_string_length (str));
563 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
564 g_free (swapped);
566 #else
567 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
568 #endif
569 return idx;
572 #ifndef DISABLE_REFLECTION_EMIT
573 static MonoClass *
574 default_class_from_mono_type (MonoType *type)
576 switch (type->type) {
577 case MONO_TYPE_OBJECT:
578 return mono_defaults.object_class;
579 case MONO_TYPE_VOID:
580 return mono_defaults.void_class;
581 case MONO_TYPE_BOOLEAN:
582 return mono_defaults.boolean_class;
583 case MONO_TYPE_CHAR:
584 return mono_defaults.char_class;
585 case MONO_TYPE_I1:
586 return mono_defaults.sbyte_class;
587 case MONO_TYPE_U1:
588 return mono_defaults.byte_class;
589 case MONO_TYPE_I2:
590 return mono_defaults.int16_class;
591 case MONO_TYPE_U2:
592 return mono_defaults.uint16_class;
593 case MONO_TYPE_I4:
594 return mono_defaults.int32_class;
595 case MONO_TYPE_U4:
596 return mono_defaults.uint32_class;
597 case MONO_TYPE_I:
598 return mono_defaults.int_class;
599 case MONO_TYPE_U:
600 return mono_defaults.uint_class;
601 case MONO_TYPE_I8:
602 return mono_defaults.int64_class;
603 case MONO_TYPE_U8:
604 return mono_defaults.uint64_class;
605 case MONO_TYPE_R4:
606 return mono_defaults.single_class;
607 case MONO_TYPE_R8:
608 return mono_defaults.double_class;
609 case MONO_TYPE_STRING:
610 return mono_defaults.string_class;
611 default:
612 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
613 g_assert_not_reached ();
616 return NULL;
618 #endif
621 * mono_class_get_ref_info:
623 * Return the type builder/generic param builder corresponding to KLASS, if it exists.
625 gpointer
626 mono_class_get_ref_info (MonoClass *klass)
628 if (klass->ref_info_handle == 0)
629 return NULL;
630 else
631 return mono_gchandle_get_target (klass->ref_info_handle);
634 void
635 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
637 klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
638 g_assert (klass->ref_info_handle != 0);
641 void
642 mono_class_free_ref_info (MonoClass *klass)
644 if (klass->ref_info_handle) {
645 mono_gchandle_free (klass->ref_info_handle);
646 klass->ref_info_handle = 0;
650 static void
651 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
653 int i;
654 MonoGenericInst *class_inst;
655 MonoClass *klass;
657 g_assert (gclass);
659 class_inst = gclass->context.class_inst;
661 sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
662 klass = gclass->container_class;
663 sigbuffer_add_value (buf, klass->byval_arg.type);
664 sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
666 sigbuffer_add_value (buf, class_inst->type_argc);
667 for (i = 0; i < class_inst->type_argc; ++i)
668 encode_type (assembly, class_inst->type_argv [i], buf);
672 static void
673 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
675 if (!type) {
676 g_assert_not_reached ();
677 return;
680 if (type->byref)
681 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
683 switch (type->type){
684 case MONO_TYPE_VOID:
685 case MONO_TYPE_BOOLEAN:
686 case MONO_TYPE_CHAR:
687 case MONO_TYPE_I1:
688 case MONO_TYPE_U1:
689 case MONO_TYPE_I2:
690 case MONO_TYPE_U2:
691 case MONO_TYPE_I4:
692 case MONO_TYPE_U4:
693 case MONO_TYPE_I8:
694 case MONO_TYPE_U8:
695 case MONO_TYPE_R4:
696 case MONO_TYPE_R8:
697 case MONO_TYPE_I:
698 case MONO_TYPE_U:
699 case MONO_TYPE_STRING:
700 case MONO_TYPE_OBJECT:
701 case MONO_TYPE_TYPEDBYREF:
702 sigbuffer_add_value (buf, type->type);
703 break;
704 case MONO_TYPE_PTR:
705 sigbuffer_add_value (buf, type->type);
706 encode_type (assembly, type->data.type, buf);
707 break;
708 case MONO_TYPE_SZARRAY:
709 sigbuffer_add_value (buf, type->type);
710 encode_type (assembly, &type->data.klass->byval_arg, buf);
711 break;
712 case MONO_TYPE_VALUETYPE:
713 case MONO_TYPE_CLASS: {
714 MonoClass *k = mono_class_from_mono_type (type);
716 if (k->generic_container) {
717 MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
718 encode_generic_class (assembly, gclass, buf);
719 } else {
721 * Make sure we use the correct type.
723 sigbuffer_add_value (buf, k->byval_arg.type);
725 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
726 * otherwise two typerefs could point to the same type, leading to
727 * verification errors.
729 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
731 break;
733 case MONO_TYPE_ARRAY:
734 sigbuffer_add_value (buf, type->type);
735 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
736 sigbuffer_add_value (buf, type->data.array->rank);
737 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
738 sigbuffer_add_value (buf, 0);
739 break;
740 case MONO_TYPE_GENERICINST:
741 encode_generic_class (assembly, type->data.generic_class, buf);
742 break;
743 case MONO_TYPE_VAR:
744 case MONO_TYPE_MVAR:
745 sigbuffer_add_value (buf, type->type);
746 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
747 break;
748 default:
749 g_error ("need to encode type %x", type->type);
753 static void
754 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
756 if (!type) {
757 sigbuffer_add_value (buf, MONO_TYPE_VOID);
758 return;
761 encode_type (assembly, mono_reflection_type_get_handle (type), buf);
764 static void
765 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
767 int i;
769 if (modreq) {
770 for (i = 0; i < mono_array_length (modreq); ++i) {
771 MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
772 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
773 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
776 if (modopt) {
777 for (i = 0; i < mono_array_length (modopt); ++i) {
778 MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
779 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
780 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
785 #ifndef DISABLE_REFLECTION_EMIT
786 static guint32
787 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
789 SigBuffer buf;
790 int i;
791 guint32 nparams = sig->param_count;
792 guint32 idx;
794 if (!assembly->save)
795 return 0;
797 sigbuffer_init (&buf, 32);
799 * FIXME: vararg, explicit_this, differenc call_conv values...
801 idx = sig->call_convention;
802 if (sig->hasthis)
803 idx |= 0x20; /* hasthis */
804 if (sig->generic_param_count)
805 idx |= 0x10; /* generic */
806 sigbuffer_add_byte (&buf, idx);
807 if (sig->generic_param_count)
808 sigbuffer_add_value (&buf, sig->generic_param_count);
809 sigbuffer_add_value (&buf, nparams);
810 encode_type (assembly, sig->ret, &buf);
811 for (i = 0; i < nparams; ++i) {
812 if (i == sig->sentinelpos)
813 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
814 encode_type (assembly, sig->params [i], &buf);
816 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
817 sigbuffer_free (&buf);
818 return idx;
820 #endif
822 static guint32
823 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
826 * FIXME: reuse code from method_encode_signature().
828 SigBuffer buf;
829 int i;
830 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
831 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
832 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
833 guint32 idx;
835 sigbuffer_init (&buf, 32);
836 /* LAMESPEC: all the call conv spec is foobared */
837 idx = mb->call_conv & 0x60; /* has-this, explicit-this */
838 if (mb->call_conv & 2)
839 idx |= 0x5; /* vararg */
840 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
841 idx |= 0x20; /* hasthis */
842 if (ngparams)
843 idx |= 0x10; /* generic */
844 sigbuffer_add_byte (&buf, idx);
845 if (ngparams)
846 sigbuffer_add_value (&buf, ngparams);
847 sigbuffer_add_value (&buf, nparams + notypes);
848 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
849 encode_reflection_type (assembly, mb->rtype, &buf);
850 for (i = 0; i < nparams; ++i) {
851 MonoArray *modreq = NULL;
852 MonoArray *modopt = NULL;
853 MonoReflectionType *pt;
855 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
856 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
857 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
858 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
859 encode_custom_modifiers (assembly, modreq, modopt, &buf);
860 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
861 encode_reflection_type (assembly, pt, &buf);
863 if (notypes)
864 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
865 for (i = 0; i < notypes; ++i) {
866 MonoReflectionType *pt;
868 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
869 encode_reflection_type (assembly, pt, &buf);
872 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
873 sigbuffer_free (&buf);
874 return idx;
877 static guint32
878 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
880 MonoDynamicTable *table;
881 guint32 *values;
882 guint32 idx, sig_idx;
883 guint nl = mono_array_length (ilgen->locals);
884 SigBuffer buf;
885 int i;
887 sigbuffer_init (&buf, 32);
888 sigbuffer_add_value (&buf, 0x07);
889 sigbuffer_add_value (&buf, nl);
890 for (i = 0; i < nl; ++i) {
891 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
893 if (lb->is_pinned)
894 sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
896 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf);
898 sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
899 sigbuffer_free (&buf);
901 if (assembly->standalonesig_cache == NULL)
902 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
903 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
904 if (idx)
905 return idx;
907 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
908 idx = table->next_idx ++;
909 table->rows ++;
910 alloc_table (table, table->rows);
911 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
913 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
915 g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
917 return idx;
920 static guint32
921 method_count_clauses (MonoReflectionILGen *ilgen)
923 guint32 num_clauses = 0;
924 int i;
926 MonoILExceptionInfo *ex_info;
927 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
928 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
929 if (ex_info->handlers)
930 num_clauses += mono_array_length (ex_info->handlers);
931 else
932 num_clauses++;
935 return num_clauses;
938 #ifndef DISABLE_REFLECTION_EMIT
939 static MonoExceptionClause*
940 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
942 MonoExceptionClause *clauses;
943 MonoExceptionClause *clause;
944 MonoILExceptionInfo *ex_info;
945 MonoILExceptionBlock *ex_block;
946 guint32 finally_start;
947 int i, j, clause_index;;
949 clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
951 clause_index = 0;
952 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
953 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
954 finally_start = ex_info->start + ex_info->len;
955 if (!ex_info->handlers)
956 continue;
957 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
958 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
959 clause = &(clauses [clause_index]);
961 clause->flags = ex_block->type;
962 clause->try_offset = ex_info->start;
964 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
965 clause->try_len = finally_start - ex_info->start;
966 else
967 clause->try_len = ex_info->len;
968 clause->handler_offset = ex_block->start;
969 clause->handler_len = ex_block->len;
970 if (ex_block->extype) {
971 clause->data.catch_class = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype));
972 } else {
973 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
974 clause->data.filter_offset = ex_block->filter_offset;
975 else
976 clause->data.filter_offset = 0;
978 finally_start = ex_block->start + ex_block->len;
980 clause_index ++;
984 return clauses;
986 #endif /* !DISABLE_REFLECTION_EMIT */
988 static guint32
989 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
991 char flags = 0;
992 guint32 idx;
993 guint32 code_size;
994 gint32 max_stack, i;
995 gint32 num_locals = 0;
996 gint32 num_exception = 0;
997 gint maybe_small;
998 guint32 fat_flags;
999 char fat_header [12];
1000 guint32 int_value;
1001 guint16 short_value;
1002 guint32 local_sig = 0;
1003 guint32 header_size = 12;
1004 MonoArray *code;
1006 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
1007 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
1008 return 0;
1010 /*if (mb->name)
1011 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1012 if (mb->ilgen) {
1013 code = mb->ilgen->code;
1014 code_size = mb->ilgen->code_len;
1015 max_stack = mb->ilgen->max_stack;
1016 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1017 if (mb->ilgen->ex_handlers)
1018 num_exception = method_count_clauses (mb->ilgen);
1019 } else {
1020 code = mb->code;
1021 if (code == NULL){
1022 char *name = mono_string_to_utf8 (mb->name);
1023 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1024 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
1025 g_free (str);
1026 g_free (name);
1027 mono_raise_exception (exception);
1030 code_size = mono_array_length (code);
1031 max_stack = 8; /* we probably need to run a verifier on the code... */
1034 stream_data_align (&assembly->code);
1036 /* check for exceptions, maxstack, locals */
1037 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1038 if (maybe_small) {
1039 if (code_size < 64 && !(code_size & 1)) {
1040 flags = (code_size << 2) | 0x2;
1041 } else if (code_size < 32 && (code_size & 1)) {
1042 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1043 } else {
1044 goto fat_header;
1046 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1047 /* add to the fixup todo list */
1048 if (mb->ilgen && mb->ilgen->num_token_fixups)
1049 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1050 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1051 return assembly->text_rva + idx;
1053 fat_header:
1054 if (num_locals)
1055 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
1057 * FIXME: need to set also the header size in fat_flags.
1058 * (and more sects and init locals flags)
1060 fat_flags = 0x03;
1061 if (num_exception)
1062 fat_flags |= METHOD_HEADER_MORE_SECTS;
1063 if (mb->init_locals)
1064 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1065 fat_header [0] = fat_flags;
1066 fat_header [1] = (header_size / 4 ) << 4;
1067 short_value = GUINT16_TO_LE (max_stack);
1068 memcpy (fat_header + 2, &short_value, 2);
1069 int_value = GUINT32_TO_LE (code_size);
1070 memcpy (fat_header + 4, &int_value, 4);
1071 int_value = GUINT32_TO_LE (local_sig);
1072 memcpy (fat_header + 8, &int_value, 4);
1073 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1074 /* add to the fixup todo list */
1075 if (mb->ilgen && mb->ilgen->num_token_fixups)
1076 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1078 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1079 if (num_exception) {
1080 unsigned char sheader [4];
1081 MonoILExceptionInfo * ex_info;
1082 MonoILExceptionBlock * ex_block;
1083 int j;
1085 stream_data_align (&assembly->code);
1086 /* always use fat format for now */
1087 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1088 num_exception *= 6 * sizeof (guint32);
1089 num_exception += 4; /* include the size of the header */
1090 sheader [1] = num_exception & 0xff;
1091 sheader [2] = (num_exception >> 8) & 0xff;
1092 sheader [3] = (num_exception >> 16) & 0xff;
1093 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1094 /* fat header, so we are already aligned */
1095 /* reverse order */
1096 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1097 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1098 if (ex_info->handlers) {
1099 int finally_start = ex_info->start + ex_info->len;
1100 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1101 guint32 val;
1102 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1103 /* the flags */
1104 val = GUINT32_TO_LE (ex_block->type);
1105 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1106 /* try offset */
1107 val = GUINT32_TO_LE (ex_info->start);
1108 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1109 /* need fault, too, probably */
1110 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1111 val = GUINT32_TO_LE (finally_start - ex_info->start);
1112 else
1113 val = GUINT32_TO_LE (ex_info->len);
1114 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1115 /* handler offset */
1116 val = GUINT32_TO_LE (ex_block->start);
1117 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1118 /* handler len */
1119 val = GUINT32_TO_LE (ex_block->len);
1120 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1121 finally_start = ex_block->start + ex_block->len;
1122 if (ex_block->extype) {
1123 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype)));
1124 } else {
1125 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1126 val = ex_block->filter_offset;
1127 else
1128 val = 0;
1130 val = GUINT32_TO_LE (val);
1131 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1132 /*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",
1133 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);*/
1135 } else {
1136 g_error ("No clauses for ex info block %d", i);
1140 return assembly->text_rva + idx;
1143 static guint32
1144 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1146 int i;
1147 MonoDynamicTable *table;
1148 guint32 *values;
1150 table = &assembly->tables [table_idx];
1152 g_assert (col < table->columns);
1154 values = table->values + table->columns;
1155 for (i = 1; i <= table->rows; ++i) {
1156 if (values [col] == token)
1157 return i;
1158 values += table->columns;
1160 return 0;
1164 * LOCKING: Acquires the loader lock.
1166 static MonoCustomAttrInfo*
1167 lookup_custom_attr (MonoImage *image, gpointer member)
1169 MonoCustomAttrInfo* res;
1171 res = mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1173 if (!res)
1174 return NULL;
1176 return g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1179 static gboolean
1180 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1182 /* FIXME: Need to do more checks */
1183 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1184 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1186 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1187 return FALSE;
1190 return TRUE;
1193 static MonoCustomAttrInfo*
1194 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1196 int i, index, count, not_visible;
1197 MonoCustomAttrInfo *ainfo;
1198 MonoReflectionCustomAttr *cattr;
1200 if (!cattrs)
1201 return NULL;
1202 /* FIXME: check in assembly the Run flag is set */
1204 count = mono_array_length (cattrs);
1206 /* Skip nonpublic attributes since MS.NET seems to do the same */
1207 /* FIXME: This needs to be done more globally */
1208 not_visible = 0;
1209 for (i = 0; i < count; ++i) {
1210 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1211 if (!custom_attr_visible (image, cattr))
1212 not_visible ++;
1214 count -= not_visible;
1216 ainfo = image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1218 ainfo->image = image;
1219 ainfo->num_attrs = count;
1220 ainfo->cached = alloc_img != NULL;
1221 index = 0;
1222 for (i = 0; i < count; ++i) {
1223 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1224 if (custom_attr_visible (image, cattr)) {
1225 unsigned char *saved = mono_image_alloc (image, mono_array_length (cattr->data));
1226 memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1227 ainfo->attrs [index].ctor = cattr->ctor->method;
1228 ainfo->attrs [index].data = saved;
1229 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1230 index ++;
1234 return ainfo;
1237 #ifndef DISABLE_REFLECTION_EMIT
1239 * LOCKING: Acquires the loader lock.
1241 static void
1242 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1244 MonoCustomAttrInfo *ainfo, *tmp;
1246 if (!cattrs || !mono_array_length (cattrs))
1247 return;
1249 ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1251 mono_loader_lock ();
1252 tmp = mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1253 if (tmp)
1254 mono_custom_attrs_free (tmp);
1255 mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1256 mono_loader_unlock ();
1259 #endif
1261 void
1262 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1264 if (!ainfo->cached)
1265 g_free (ainfo);
1269 * idx is the table index of the object
1270 * type is one of MONO_CUSTOM_ATTR_*
1272 static void
1273 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1275 MonoDynamicTable *table;
1276 MonoReflectionCustomAttr *cattr;
1277 guint32 *values;
1278 guint32 count, i, token;
1279 char blob_size [6];
1280 char *p = blob_size;
1282 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1283 if (!cattrs)
1284 return;
1285 count = mono_array_length (cattrs);
1286 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1287 table->rows += count;
1288 alloc_table (table, table->rows);
1289 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1290 idx <<= MONO_CUSTOM_ATTR_BITS;
1291 idx |= type;
1292 for (i = 0; i < count; ++i) {
1293 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1294 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1295 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE);
1296 type = mono_metadata_token_index (token);
1297 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1298 switch (mono_metadata_token_table (token)) {
1299 case MONO_TABLE_METHOD:
1300 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1301 break;
1302 case MONO_TABLE_MEMBERREF:
1303 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1304 break;
1305 default:
1306 g_warning ("got wrong token in custom attr");
1307 continue;
1309 values [MONO_CUSTOM_ATTR_TYPE] = type;
1310 p = blob_size;
1311 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1312 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1313 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1314 values += MONO_CUSTOM_ATTR_SIZE;
1315 ++table->next_idx;
1319 static void
1320 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1322 MonoDynamicTable *table;
1323 guint32 *values;
1324 guint32 count, i, idx;
1325 MonoReflectionPermissionSet *perm;
1327 if (!permissions)
1328 return;
1330 count = mono_array_length (permissions);
1331 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1332 table->rows += count;
1333 alloc_table (table, table->rows);
1335 for (i = 0; i < mono_array_length (permissions); ++i) {
1336 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1338 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1340 idx = mono_metadata_token_index (parent_token);
1341 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1342 switch (mono_metadata_token_table (parent_token)) {
1343 case MONO_TABLE_TYPEDEF:
1344 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1345 break;
1346 case MONO_TABLE_METHOD:
1347 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1348 break;
1349 case MONO_TABLE_ASSEMBLY:
1350 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1351 break;
1352 default:
1353 g_assert_not_reached ();
1356 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1357 values [MONO_DECL_SECURITY_PARENT] = idx;
1358 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1360 ++table->next_idx;
1365 * Fill in the MethodDef and ParamDef tables for a method.
1366 * This is used for both normal methods and constructors.
1368 static void
1369 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1371 MonoDynamicTable *table;
1372 guint32 *values;
1373 guint i, count;
1375 /* room in this table is already allocated */
1376 table = &assembly->tables [MONO_TABLE_METHOD];
1377 *mb->table_idx = table->next_idx ++;
1378 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1379 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1380 values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1381 values [MONO_METHOD_FLAGS] = mb->attrs;
1382 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1383 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1384 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1386 table = &assembly->tables [MONO_TABLE_PARAM];
1387 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1389 mono_image_add_decl_security (assembly,
1390 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1392 if (mb->pinfo) {
1393 MonoDynamicTable *mtable;
1394 guint32 *mvalues;
1396 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1397 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1399 count = 0;
1400 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1401 if (mono_array_get (mb->pinfo, gpointer, i))
1402 count++;
1404 table->rows += count;
1405 alloc_table (table, table->rows);
1406 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1407 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1408 MonoReflectionParamBuilder *pb;
1409 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1410 values [MONO_PARAM_FLAGS] = pb->attrs;
1411 values [MONO_PARAM_SEQUENCE] = i;
1412 if (pb->name != NULL) {
1413 values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1414 } else {
1415 values [MONO_PARAM_NAME] = 0;
1417 values += MONO_PARAM_SIZE;
1418 if (pb->marshal_info) {
1419 mtable->rows++;
1420 alloc_table (mtable, mtable->rows);
1421 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1422 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1423 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1425 pb->table_idx = table->next_idx++;
1426 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1427 guint32 field_type = 0;
1428 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1429 mtable->rows ++;
1430 alloc_table (mtable, mtable->rows);
1431 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1432 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1433 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1434 mvalues [MONO_CONSTANT_TYPE] = field_type;
1435 mvalues [MONO_CONSTANT_PADDING] = 0;
1442 #ifndef DISABLE_REFLECTION_EMIT
1443 static void
1444 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1446 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1448 rmb->ilgen = mb->ilgen;
1449 rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype);
1450 rmb->parameters = mb->parameters;
1451 rmb->generic_params = mb->generic_params;
1452 rmb->generic_container = mb->generic_container;
1453 rmb->opt_types = NULL;
1454 rmb->pinfo = mb->pinfo;
1455 rmb->attrs = mb->attrs;
1456 rmb->iattrs = mb->iattrs;
1457 rmb->call_conv = mb->call_conv;
1458 rmb->code = mb->code;
1459 rmb->type = mb->type;
1460 rmb->name = mb->name;
1461 rmb->table_idx = &mb->table_idx;
1462 rmb->init_locals = mb->init_locals;
1463 rmb->skip_visibility = FALSE;
1464 rmb->return_modreq = mb->return_modreq;
1465 rmb->return_modopt = mb->return_modopt;
1466 rmb->param_modreq = mb->param_modreq;
1467 rmb->param_modopt = mb->param_modopt;
1468 rmb->permissions = mb->permissions;
1469 rmb->mhandle = mb->mhandle;
1470 rmb->nrefs = 0;
1471 rmb->refs = NULL;
1473 if (mb->dll) {
1474 rmb->charset = mb->charset;
1475 rmb->extra_flags = mb->extra_flags;
1476 rmb->native_cc = mb->native_cc;
1477 rmb->dllentry = mb->dllentry;
1478 rmb->dll = mb->dll;
1482 static void
1483 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1485 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1487 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1489 rmb->ilgen = mb->ilgen;
1490 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1491 rmb->parameters = mb->parameters;
1492 rmb->generic_params = NULL;
1493 rmb->generic_container = NULL;
1494 rmb->opt_types = NULL;
1495 rmb->pinfo = mb->pinfo;
1496 rmb->attrs = mb->attrs;
1497 rmb->iattrs = mb->iattrs;
1498 rmb->call_conv = mb->call_conv;
1499 rmb->code = NULL;
1500 rmb->type = mb->type;
1501 rmb->name = mono_string_new (mono_domain_get (), name);
1502 rmb->table_idx = &mb->table_idx;
1503 rmb->init_locals = mb->init_locals;
1504 rmb->skip_visibility = FALSE;
1505 rmb->return_modreq = NULL;
1506 rmb->return_modopt = NULL;
1507 rmb->param_modreq = mb->param_modreq;
1508 rmb->param_modopt = mb->param_modopt;
1509 rmb->permissions = mb->permissions;
1510 rmb->mhandle = mb->mhandle;
1511 rmb->nrefs = 0;
1512 rmb->refs = NULL;
1515 static void
1516 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1518 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1520 rmb->ilgen = mb->ilgen;
1521 rmb->rtype = mb->rtype;
1522 rmb->parameters = mb->parameters;
1523 rmb->generic_params = NULL;
1524 rmb->generic_container = NULL;
1525 rmb->opt_types = NULL;
1526 rmb->pinfo = NULL;
1527 rmb->attrs = mb->attrs;
1528 rmb->iattrs = 0;
1529 rmb->call_conv = mb->call_conv;
1530 rmb->code = NULL;
1531 rmb->type = (MonoObject *) mb->owner;
1532 rmb->name = mb->name;
1533 rmb->table_idx = NULL;
1534 rmb->init_locals = mb->init_locals;
1535 rmb->skip_visibility = mb->skip_visibility;
1536 rmb->return_modreq = NULL;
1537 rmb->return_modopt = NULL;
1538 rmb->param_modreq = NULL;
1539 rmb->param_modopt = NULL;
1540 rmb->permissions = NULL;
1541 rmb->mhandle = mb->mhandle;
1542 rmb->nrefs = 0;
1543 rmb->refs = NULL;
1545 #endif
1547 static void
1548 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1550 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1551 MonoDynamicTable *table;
1552 guint32 *values;
1553 guint32 tok;
1555 if (!mb->override_method)
1556 return;
1558 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1559 table->rows ++;
1560 alloc_table (table, table->rows);
1561 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1562 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1563 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1565 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE, FALSE);
1566 switch (mono_metadata_token_table (tok)) {
1567 case MONO_TABLE_MEMBERREF:
1568 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1569 break;
1570 case MONO_TABLE_METHOD:
1571 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1572 break;
1573 default:
1574 g_assert_not_reached ();
1576 values [MONO_METHODIMPL_DECLARATION] = tok;
1579 #ifndef DISABLE_REFLECTION_EMIT
1580 static void
1581 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1583 MonoDynamicTable *table;
1584 guint32 *values;
1585 ReflectionMethodBuilder rmb;
1586 int i;
1588 reflection_methodbuilder_from_method_builder (&rmb, mb);
1590 mono_image_basic_method (&rmb, assembly);
1591 mb->table_idx = *rmb.table_idx;
1593 if (mb->dll) { /* It's a P/Invoke method */
1594 guint32 moduleref;
1595 /* map CharSet values to on-disk values */
1596 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1597 int extra_flags = mb->extra_flags;
1598 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1599 table->rows ++;
1600 alloc_table (table, table->rows);
1601 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1603 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1604 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1605 if (mb->dllentry)
1606 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1607 else
1608 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1609 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1610 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1611 table = &assembly->tables [MONO_TABLE_MODULEREF];
1612 table->rows ++;
1613 alloc_table (table, table->rows);
1614 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1615 values [MONO_IMPLMAP_SCOPE] = table->rows;
1619 if (mb->generic_params) {
1620 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1621 table->rows += mono_array_length (mb->generic_params);
1622 alloc_table (table, table->rows);
1623 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1624 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1626 mono_image_get_generic_param_info (
1627 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1633 static void
1634 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1636 ReflectionMethodBuilder rmb;
1638 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1640 mono_image_basic_method (&rmb, assembly);
1641 mb->table_idx = *rmb.table_idx;
1643 #endif
1645 static char*
1646 type_get_fully_qualified_name (MonoType *type)
1648 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1651 static char*
1652 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1653 MonoClass *klass;
1654 MonoAssembly *ta;
1656 klass = mono_class_from_mono_type (type);
1657 if (!klass)
1658 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1659 ta = klass->image->assembly;
1660 if (ta->dynamic || (ta == ass)) {
1661 if (klass->generic_class || klass->generic_container)
1662 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1663 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1664 else
1665 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1668 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1671 #ifndef DISABLE_REFLECTION_EMIT
1672 /*field_image is the image to which the eventual custom mods have been encoded against*/
1673 static guint32
1674 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
1676 SigBuffer buf;
1677 guint32 idx, i, token;
1679 if (!assembly->save)
1680 return 0;
1682 sigbuffer_init (&buf, 32);
1684 sigbuffer_add_value (&buf, 0x06);
1685 /* encode custom attributes before the type */
1686 if (type->num_mods) {
1687 for (i = 0; i < type->num_mods; ++i) {
1688 if (field_image) {
1689 MonoClass *class = mono_class_get (field_image, type->modifiers [i].token);
1690 g_assert (class);
1691 token = mono_image_typedef_or_ref (assembly, &class->byval_arg);
1692 } else {
1693 token = type->modifiers [i].token;
1696 if (type->modifiers [i].required)
1697 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1698 else
1699 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1701 sigbuffer_add_value (&buf, token);
1704 encode_type (assembly, type, &buf);
1705 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1706 sigbuffer_free (&buf);
1707 return idx;
1709 #endif
1711 static guint32
1712 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1714 SigBuffer buf;
1715 guint32 idx;
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 */
1722 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
1723 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1724 sigbuffer_free (&buf);
1725 return idx;
1728 static guint32
1729 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1730 char blob_size [64];
1731 char *b = blob_size;
1732 char *p, *box_val;
1733 char* buf;
1734 guint32 idx = 0, len = 0, dummy = 0;
1735 #ifdef ARM_FPU_FPA
1736 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1737 guint32 fpa_double [2];
1738 guint32 *fpa_p;
1739 #endif
1740 #endif
1742 p = buf = g_malloc (64);
1743 if (!val) {
1744 *ret_type = MONO_TYPE_CLASS;
1745 len = 4;
1746 box_val = (char*)&dummy;
1747 } else {
1748 box_val = ((char*)val) + sizeof (MonoObject);
1749 *ret_type = val->vtable->klass->byval_arg.type;
1751 handle_enum:
1752 switch (*ret_type) {
1753 case MONO_TYPE_BOOLEAN:
1754 case MONO_TYPE_U1:
1755 case MONO_TYPE_I1:
1756 len = 1;
1757 break;
1758 case MONO_TYPE_CHAR:
1759 case MONO_TYPE_U2:
1760 case MONO_TYPE_I2:
1761 len = 2;
1762 break;
1763 case MONO_TYPE_U4:
1764 case MONO_TYPE_I4:
1765 case MONO_TYPE_R4:
1766 len = 4;
1767 break;
1768 case MONO_TYPE_U8:
1769 case MONO_TYPE_I8:
1770 len = 8;
1771 break;
1772 case MONO_TYPE_R8:
1773 len = 8;
1774 #ifdef ARM_FPU_FPA
1775 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1776 fpa_p = (guint32*)box_val;
1777 fpa_double [0] = fpa_p [1];
1778 fpa_double [1] = fpa_p [0];
1779 box_val = (char*)fpa_double;
1780 #endif
1781 #endif
1782 break;
1783 case MONO_TYPE_VALUETYPE:
1784 if (val->vtable->klass->enumtype) {
1785 *ret_type = mono_class_enum_basetype (val->vtable->klass)->type;
1786 goto handle_enum;
1787 } else
1788 g_error ("we can't encode valuetypes");
1789 case MONO_TYPE_CLASS:
1790 break;
1791 case MONO_TYPE_STRING: {
1792 MonoString *str = (MonoString*)val;
1793 /* there is no signature */
1794 len = str->length * 2;
1795 mono_metadata_encode_value (len, b, &b);
1796 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1798 char *swapped = g_malloc (2 * mono_string_length (str));
1799 const char *p = (const char*)mono_string_chars (str);
1801 swap_with_size (swapped, p, 2, mono_string_length (str));
1802 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1803 g_free (swapped);
1805 #else
1806 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1807 #endif
1809 g_free (buf);
1810 return idx;
1812 case MONO_TYPE_GENERICINST:
1813 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
1814 goto handle_enum;
1815 default:
1816 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1819 /* there is no signature */
1820 mono_metadata_encode_value (len, b, &b);
1821 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1822 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1823 swap_with_size (blob_size, box_val, len, 1);
1824 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1825 #else
1826 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1827 #endif
1829 g_free (buf);
1830 return idx;
1833 static guint32
1834 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1835 char *str;
1836 SigBuffer buf;
1837 guint32 idx, len;
1839 sigbuffer_init (&buf, 32);
1841 sigbuffer_add_value (&buf, minfo->type);
1843 switch (minfo->type) {
1844 case MONO_NATIVE_BYVALTSTR:
1845 case MONO_NATIVE_BYVALARRAY:
1846 sigbuffer_add_value (&buf, minfo->count);
1847 break;
1848 case MONO_NATIVE_LPARRAY:
1849 if (minfo->eltype || minfo->has_size) {
1850 sigbuffer_add_value (&buf, minfo->eltype);
1851 if (minfo->has_size) {
1852 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
1853 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
1855 /* LAMESPEC: ElemMult is undocumented */
1856 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1859 break;
1860 case MONO_NATIVE_SAFEARRAY:
1861 if (minfo->eltype)
1862 sigbuffer_add_value (&buf, minfo->eltype);
1863 break;
1864 case MONO_NATIVE_CUSTOM:
1865 if (minfo->guid) {
1866 str = mono_string_to_utf8 (minfo->guid);
1867 len = strlen (str);
1868 sigbuffer_add_value (&buf, len);
1869 sigbuffer_add_mem (&buf, str, len);
1870 g_free (str);
1871 } else {
1872 sigbuffer_add_value (&buf, 0);
1874 /* native type name */
1875 sigbuffer_add_value (&buf, 0);
1876 /* custom marshaler type name */
1877 if (minfo->marshaltype || minfo->marshaltyperef) {
1878 if (minfo->marshaltyperef)
1879 str = type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
1880 else
1881 str = mono_string_to_utf8 (minfo->marshaltype);
1882 len = strlen (str);
1883 sigbuffer_add_value (&buf, len);
1884 sigbuffer_add_mem (&buf, str, len);
1885 g_free (str);
1886 } else {
1887 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
1888 sigbuffer_add_value (&buf, 0);
1890 if (minfo->mcookie) {
1891 str = mono_string_to_utf8 (minfo->mcookie);
1892 len = strlen (str);
1893 sigbuffer_add_value (&buf, len);
1894 sigbuffer_add_mem (&buf, str, len);
1895 g_free (str);
1896 } else {
1897 sigbuffer_add_value (&buf, 0);
1899 break;
1900 default:
1901 break;
1903 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1904 sigbuffer_free (&buf);
1905 return idx;
1908 static void
1909 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1911 MonoDynamicTable *table;
1912 guint32 *values;
1914 /* maybe this fixup should be done in the C# code */
1915 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1916 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1917 table = &assembly->tables [MONO_TABLE_FIELD];
1918 fb->table_idx = table->next_idx ++;
1919 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1920 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1921 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
1922 values [MONO_FIELD_FLAGS] = fb->attrs;
1923 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1925 if (fb->offset != -1) {
1926 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1927 table->rows ++;
1928 alloc_table (table, table->rows);
1929 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1930 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1931 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1933 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1934 guint32 field_type = 0;
1935 table = &assembly->tables [MONO_TABLE_CONSTANT];
1936 table->rows ++;
1937 alloc_table (table, table->rows);
1938 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1939 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1940 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1941 values [MONO_CONSTANT_TYPE] = field_type;
1942 values [MONO_CONSTANT_PADDING] = 0;
1944 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1945 guint32 rva_idx;
1946 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1947 table->rows ++;
1948 alloc_table (table, table->rows);
1949 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1950 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1952 * We store it in the code section because it's simpler for now.
1954 if (fb->rva_data) {
1955 if (mono_array_length (fb->rva_data) >= 10)
1956 stream_data_align (&assembly->code);
1957 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1958 } else
1959 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1960 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1962 if (fb->marshal_info) {
1963 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1964 table->rows ++;
1965 alloc_table (table, table->rows);
1966 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1967 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1968 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1972 static guint32
1973 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1975 SigBuffer buf;
1976 guint32 nparams = 0;
1977 MonoReflectionMethodBuilder *mb = fb->get_method;
1978 MonoReflectionMethodBuilder *smb = fb->set_method;
1979 guint32 idx, i;
1981 if (mb && mb->parameters)
1982 nparams = mono_array_length (mb->parameters);
1983 if (!mb && smb && smb->parameters)
1984 nparams = mono_array_length (smb->parameters) - 1;
1985 sigbuffer_init (&buf, 32);
1986 sigbuffer_add_byte (&buf, 0x08);
1987 sigbuffer_add_value (&buf, nparams);
1988 if (mb) {
1989 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf);
1990 for (i = 0; i < nparams; ++i) {
1991 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1992 encode_reflection_type (assembly, pt, &buf);
1994 } else if (smb && smb->parameters) {
1995 /* the property type is the last param */
1996 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
1997 for (i = 0; i < nparams; ++i) {
1998 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1999 encode_reflection_type (assembly, pt, &buf);
2001 } else {
2002 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
2005 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2006 sigbuffer_free (&buf);
2007 return idx;
2010 static void
2011 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
2013 MonoDynamicTable *table;
2014 guint32 *values;
2015 guint num_methods = 0;
2016 guint32 semaidx;
2019 * we need to set things in the following tables:
2020 * PROPERTYMAP (info already filled in _get_type_info ())
2021 * PROPERTY (rows already preallocated in _get_type_info ())
2022 * METHOD (method info already done with the generic method code)
2023 * METHODSEMANTICS
2024 * CONSTANT
2026 table = &assembly->tables [MONO_TABLE_PROPERTY];
2027 pb->table_idx = table->next_idx ++;
2028 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2029 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2030 values [MONO_PROPERTY_FLAGS] = pb->attrs;
2031 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
2033 /* FIXME: we still don't handle 'other' methods */
2034 if (pb->get_method) num_methods ++;
2035 if (pb->set_method) num_methods ++;
2037 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2038 table->rows += num_methods;
2039 alloc_table (table, table->rows);
2041 if (pb->get_method) {
2042 semaidx = table->next_idx ++;
2043 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2044 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2045 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2046 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2048 if (pb->set_method) {
2049 semaidx = table->next_idx ++;
2050 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2051 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2052 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2053 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2055 if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2056 guint32 field_type = 0;
2057 table = &assembly->tables [MONO_TABLE_CONSTANT];
2058 table->rows ++;
2059 alloc_table (table, table->rows);
2060 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2061 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2062 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2063 values [MONO_CONSTANT_TYPE] = field_type;
2064 values [MONO_CONSTANT_PADDING] = 0;
2068 static void
2069 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
2071 MonoDynamicTable *table;
2072 guint32 *values;
2073 guint num_methods = 0;
2074 guint32 semaidx;
2077 * we need to set things in the following tables:
2078 * EVENTMAP (info already filled in _get_type_info ())
2079 * EVENT (rows already preallocated in _get_type_info ())
2080 * METHOD (method info already done with the generic method code)
2081 * METHODSEMANTICS
2083 table = &assembly->tables [MONO_TABLE_EVENT];
2084 eb->table_idx = table->next_idx ++;
2085 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2086 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2087 values [MONO_EVENT_FLAGS] = eb->attrs;
2088 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (eb->type));
2091 * FIXME: we still don't handle 'other' methods
2093 if (eb->add_method) num_methods ++;
2094 if (eb->remove_method) num_methods ++;
2095 if (eb->raise_method) num_methods ++;
2097 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2098 table->rows += num_methods;
2099 alloc_table (table, table->rows);
2101 if (eb->add_method) {
2102 semaidx = table->next_idx ++;
2103 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2104 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2105 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2106 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2108 if (eb->remove_method) {
2109 semaidx = table->next_idx ++;
2110 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2111 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2112 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2113 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2115 if (eb->raise_method) {
2116 semaidx = table->next_idx ++;
2117 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2118 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2119 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2120 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2124 static void
2125 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2127 MonoDynamicTable *table;
2128 guint32 num_constraints, i;
2129 guint32 *values;
2130 guint32 table_idx;
2132 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2133 num_constraints = gparam->iface_constraints ?
2134 mono_array_length (gparam->iface_constraints) : 0;
2135 table->rows += num_constraints;
2136 if (gparam->base_type)
2137 table->rows++;
2138 alloc_table (table, table->rows);
2140 if (gparam->base_type) {
2141 table_idx = table->next_idx ++;
2142 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2144 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2145 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2146 assembly, mono_reflection_type_get_handle (gparam->base_type));
2149 for (i = 0; i < num_constraints; i++) {
2150 MonoReflectionType *constraint = mono_array_get (
2151 gparam->iface_constraints, gpointer, i);
2153 table_idx = table->next_idx ++;
2154 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2156 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2157 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2158 assembly, mono_reflection_type_get_handle (constraint));
2162 static void
2163 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2165 GenericParamTableEntry *entry;
2168 * The GenericParam table must be sorted according to the `owner' field.
2169 * We need to do this sorting prior to writing the GenericParamConstraint
2170 * table, since we have to use the final GenericParam table indices there
2171 * and they must also be sorted.
2174 entry = g_new0 (GenericParamTableEntry, 1);
2175 entry->owner = owner;
2176 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2177 MOVING_GC_REGISTER (&entry->gparam);
2178 entry->gparam = gparam;
2180 g_ptr_array_add (assembly->gen_params, entry);
2183 static void
2184 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2186 MonoDynamicTable *table;
2187 MonoGenericParam *param;
2188 guint32 *values;
2189 guint32 table_idx;
2191 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2192 table_idx = table->next_idx ++;
2193 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2195 param = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam)->data.generic_param;
2197 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2198 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2199 values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2200 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2202 mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2204 encode_constraints (entry->gparam, table_idx, assembly);
2207 static guint32
2208 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2210 MonoDynamicTable *table;
2211 guint32 token;
2212 guint32 *values;
2213 guint32 cols [MONO_ASSEMBLY_SIZE];
2214 const char *pubkey;
2215 guint32 publen;
2217 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2218 return token;
2220 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2221 table = &assembly->tables [MONO_TABLE_MODULEREF];
2222 token = table->next_idx ++;
2223 table->rows ++;
2224 alloc_table (table, table->rows);
2225 values = table->values + token * MONO_MODULEREF_SIZE;
2226 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2228 token <<= MONO_RESOLTION_SCOPE_BITS;
2229 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2230 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2232 return token;
2235 if (image->assembly->dynamic)
2236 /* FIXME: */
2237 memset (cols, 0, sizeof (cols));
2238 else {
2239 /* image->assembly->image is the manifest module */
2240 image = image->assembly->image;
2241 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2244 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2245 token = table->next_idx ++;
2246 table->rows ++;
2247 alloc_table (table, table->rows);
2248 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2249 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2250 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2251 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2252 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2253 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2254 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2255 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2256 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2258 if (strcmp ("", image->assembly->aname.culture)) {
2259 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2260 image->assembly->aname.culture);
2263 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2264 guchar pubtoken [9];
2265 pubtoken [0] = 8;
2266 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2267 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2268 } else {
2269 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2271 token <<= MONO_RESOLTION_SCOPE_BITS;
2272 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2273 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2274 return token;
2277 static guint32
2278 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2280 MonoDynamicTable *table;
2281 guint32 *values;
2282 guint32 token;
2283 SigBuffer buf;
2285 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2286 return token;
2288 sigbuffer_init (&buf, 32);
2289 switch (type->type) {
2290 case MONO_TYPE_FNPTR:
2291 case MONO_TYPE_PTR:
2292 case MONO_TYPE_SZARRAY:
2293 case MONO_TYPE_ARRAY:
2294 case MONO_TYPE_VAR:
2295 case MONO_TYPE_MVAR:
2296 case MONO_TYPE_GENERICINST:
2297 encode_type (assembly, type, &buf);
2298 break;
2299 case MONO_TYPE_CLASS:
2300 case MONO_TYPE_VALUETYPE: {
2301 MonoClass *k = mono_class_from_mono_type (type);
2302 if (!k || !k->generic_container) {
2303 sigbuffer_free (&buf);
2304 return 0;
2306 encode_type (assembly, type, &buf);
2307 break;
2309 default:
2310 sigbuffer_free (&buf);
2311 return 0;
2314 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2315 if (assembly->save) {
2316 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2317 alloc_table (table, table->rows + 1);
2318 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2319 values [MONO_TYPESPEC_SIGNATURE] = token;
2321 sigbuffer_free (&buf);
2323 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2324 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2325 table->next_idx ++;
2326 return token;
2329 static guint32
2330 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2332 MonoDynamicTable *table;
2333 guint32 *values;
2334 guint32 token, scope, enclosing;
2335 MonoClass *klass;
2337 /* if the type requires a typespec, we must try that first*/
2338 if (try_typespec && (token = create_typespec (assembly, type)))
2339 return token;
2340 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2341 if (token)
2342 return token;
2343 klass = mono_class_from_mono_type (type);
2344 if (!klass)
2345 klass = mono_class_from_mono_type (type);
2348 * If it's in the same module and not a generic type parameter:
2350 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2351 (type->type != MONO_TYPE_MVAR)) {
2352 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
2353 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2354 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), mono_class_get_ref_info (klass));
2355 return token;
2358 if (klass->nested_in) {
2359 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2360 /* get the typeref idx of the enclosing type */
2361 enclosing >>= MONO_TYPEDEFORREF_BITS;
2362 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2363 } else {
2364 scope = resolution_scope_from_image (assembly, klass->image);
2366 table = &assembly->tables [MONO_TABLE_TYPEREF];
2367 if (assembly->save) {
2368 alloc_table (table, table->rows + 1);
2369 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2370 values [MONO_TYPEREF_SCOPE] = scope;
2371 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2372 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2374 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2375 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2376 table->next_idx ++;
2377 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), mono_class_get_ref_info (klass));
2378 return token;
2382 * Despite the name, we handle also TypeSpec (with the above helper).
2384 static guint32
2385 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2387 return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2390 #ifndef DISABLE_REFLECTION_EMIT
2391 static guint32
2392 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2394 MonoDynamicTable *table;
2395 guint32 *values;
2396 guint32 token, pclass;
2398 switch (parent & MONO_TYPEDEFORREF_MASK) {
2399 case MONO_TYPEDEFORREF_TYPEREF:
2400 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2401 break;
2402 case MONO_TYPEDEFORREF_TYPESPEC:
2403 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2404 break;
2405 case MONO_TYPEDEFORREF_TYPEDEF:
2406 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2407 break;
2408 default:
2409 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2410 return 0;
2412 /* extract the index */
2413 parent >>= MONO_TYPEDEFORREF_BITS;
2415 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2417 if (assembly->save) {
2418 alloc_table (table, table->rows + 1);
2419 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2420 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2421 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2422 values [MONO_MEMBERREF_SIGNATURE] = sig;
2425 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2426 table->next_idx ++;
2428 return token;
2432 * Insert a memberef row into the metadata: the token that point to the memberref
2433 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2434 * mono_image_get_fieldref_token()).
2435 * The sig param is an index to an already built signature.
2437 static guint32
2438 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2440 guint32 parent = mono_image_typedef_or_ref (assembly, type);
2441 return mono_image_add_memberef_row (assembly, parent, name, sig);
2445 static guint32
2446 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2448 guint32 token;
2449 MonoMethodSignature *sig;
2451 create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2453 if (create_typespec) {
2454 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2455 if (token)
2456 return token;
2459 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2460 if (token && !create_typespec)
2461 return token;
2463 g_assert (!method->is_inflated);
2464 if (!token) {
2466 * A methodref signature can't contain an unmanaged calling convention.
2468 sig = mono_metadata_signature_dup (mono_method_signature (method));
2469 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2470 sig->call_convention = MONO_CALL_DEFAULT;
2471 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2472 method->name, method_encode_signature (assembly, sig));
2473 g_free (sig);
2474 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2477 if (create_typespec) {
2478 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2479 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2480 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2482 if (assembly->save) {
2483 guint32 *values;
2485 alloc_table (table, table->rows + 1);
2486 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2487 values [MONO_METHODSPEC_METHOD] = token;
2488 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2491 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2492 table->next_idx ++;
2493 /*methodspec and memberef tokens are diferent, */
2494 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2495 return token;
2497 return token;
2500 static guint32
2501 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2503 guint32 token, parent, sig;
2504 ReflectionMethodBuilder rmb;
2505 char *name;
2506 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2508 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2509 if (token)
2510 return token;
2512 name = mono_string_to_utf8 (method->name);
2513 reflection_methodbuilder_from_method_builder (&rmb, method);
2516 * A methodref signature can't contain an unmanaged calling convention.
2517 * Since some flags are encoded as part of call_conv, we need to check against it.
2519 if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2520 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2522 sig = method_builder_encode_signature (assembly, &rmb);
2524 if (tb->generic_params)
2525 parent = create_generic_typespec (assembly, tb);
2526 else
2527 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type));
2529 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2531 g_free (name);
2532 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2533 return token;
2536 static guint32
2537 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2538 const gchar *name, guint32 sig)
2540 MonoDynamicTable *table;
2541 guint32 token;
2542 guint32 *values;
2544 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2546 if (assembly->save) {
2547 alloc_table (table, table->rows + 1);
2548 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2549 values [MONO_MEMBERREF_CLASS] = original;
2550 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2551 values [MONO_MEMBERREF_SIGNATURE] = sig;
2554 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2555 table->next_idx ++;
2557 return token;
2560 static guint32
2561 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2563 SigBuffer buf;
2564 int i;
2565 guint32 nparams = mono_array_length (mb->generic_params);
2566 guint32 idx;
2568 if (!assembly->save)
2569 return 0;
2571 sigbuffer_init (&buf, 32);
2573 sigbuffer_add_value (&buf, 0xa);
2574 sigbuffer_add_value (&buf, nparams);
2576 for (i = 0; i < nparams; i++) {
2577 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2578 sigbuffer_add_value (&buf, i);
2581 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2582 sigbuffer_free (&buf);
2583 return idx;
2586 static guint32
2587 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2589 MonoDynamicTable *table;
2590 guint32 *values;
2591 guint32 token, mtoken = 0;
2593 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2594 if (token)
2595 return token;
2597 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2599 mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2600 switch (mono_metadata_token_table (mtoken)) {
2601 case MONO_TABLE_MEMBERREF:
2602 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2603 break;
2604 case MONO_TABLE_METHOD:
2605 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2606 break;
2607 default:
2608 g_assert_not_reached ();
2611 if (assembly->save) {
2612 alloc_table (table, table->rows + 1);
2613 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2614 values [MONO_METHODSPEC_METHOD] = mtoken;
2615 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2618 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2619 table->next_idx ++;
2621 mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2622 return token;
2625 static guint32
2626 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2628 guint32 token;
2630 if (mb->generic_params && create_methodspec)
2631 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2633 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2634 if (token)
2635 return token;
2637 token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2638 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2639 return token;
2642 static guint32
2643 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2645 guint32 token, parent, sig;
2646 ReflectionMethodBuilder rmb;
2647 char *name;
2648 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
2650 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2651 if (token)
2652 return token;
2654 g_assert (tb->generic_params);
2656 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2658 parent = create_generic_typespec (assembly, tb);
2659 name = mono_string_to_utf8 (rmb.name);
2660 sig = method_builder_encode_signature (assembly, &rmb);
2662 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2664 g_free (name);
2665 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2666 return token;
2668 #endif
2670 static gboolean
2671 is_field_on_inst (MonoClassField *field)
2673 return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2677 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2679 static MonoType*
2680 get_field_on_inst_generic_type (MonoClassField *field)
2682 MonoClass *class, *gtd;
2683 MonoDynamicGenericClass *dgclass;
2684 int field_index;
2686 g_assert (is_field_on_inst (field));
2688 dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2690 if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
2691 field_index = field - dgclass->fields;
2692 return dgclass->field_generic_types [field_index];
2695 class = field->parent;
2696 gtd = class->generic_class->container_class;
2698 if (field >= class->fields && field - class->fields < class->field.count) {
2699 field_index = field - class->fields;
2700 return gtd->fields [field_index].type;
2703 g_assert_not_reached ();
2704 return 0;
2707 #ifndef DISABLE_REFLECTION_EMIT
2708 static guint32
2709 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2711 MonoType *type;
2712 guint32 token;
2713 MonoClassField *field;
2715 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2716 if (token)
2717 return token;
2718 g_assert (f->field->parent);
2720 field = f->field;
2721 if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2722 int index = field - field->parent->fields;
2723 type = field->parent->generic_class->container_class->fields [index].type;
2724 } else {
2725 if (is_field_on_inst (f->field))
2726 type = get_field_on_inst_generic_type (f->field);
2727 else
2728 type = f->field->type;
2730 token = mono_image_get_memberref_token (assembly, &f->field->parent->byval_arg,
2731 mono_field_get_name (f->field),
2732 fieldref_encode_signature (assembly, field->parent->image, type));
2733 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
2734 return token;
2737 static guint32
2738 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
2740 guint32 token;
2741 MonoClass *klass;
2742 MonoGenericClass *gclass;
2743 MonoDynamicGenericClass *dgclass;
2744 MonoType *type;
2745 char *name;
2747 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2748 if (token)
2749 return token;
2750 if (is_sre_field_builder (mono_object_class (f->fb))) {
2751 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
2752 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2753 klass = mono_class_from_mono_type (type);
2754 gclass = type->data.generic_class;
2755 g_assert (gclass->is_dynamic);
2756 dgclass = (MonoDynamicGenericClass *) gclass;
2758 name = mono_string_to_utf8 (fb->name);
2759 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name,
2760 field_encode_signature (assembly, fb));
2761 g_free (name);
2762 } else if (is_sr_mono_field (mono_object_class (f->fb))) {
2763 guint32 sig;
2764 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
2766 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2767 klass = mono_class_from_mono_type (type);
2769 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
2770 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
2771 } else {
2772 char *name = mono_type_get_full_name (mono_object_class (f->fb));
2773 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
2776 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
2777 return token;
2780 static guint32
2781 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
2783 guint32 sig, token;
2784 MonoClass *klass;
2785 MonoGenericClass *gclass;
2786 MonoType *type;
2788 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
2790 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
2791 if (token)
2792 return token;
2794 if (is_sre_ctor_builder (mono_object_class (c->cb))) {
2795 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
2796 MonoDynamicGenericClass *dgclass;
2797 ReflectionMethodBuilder rmb;
2798 char *name;
2800 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2801 klass = mono_class_from_mono_type (type);
2803 gclass = type->data.generic_class;
2804 g_assert (gclass->is_dynamic);
2805 dgclass = (MonoDynamicGenericClass *) gclass;
2807 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
2809 name = mono_string_to_utf8 (rmb.name);
2811 sig = method_builder_encode_signature (assembly, &rmb);
2813 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2814 g_free (name);
2815 } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
2816 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
2818 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2819 klass = mono_class_from_mono_type (type);
2821 sig = method_encode_signature (assembly, mono_method_signature (mm));
2822 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2823 } else {
2824 char *name = mono_type_get_full_name (mono_object_class (c->cb));
2825 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2829 mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
2830 return token;
2833 static MonoMethod*
2834 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m)
2836 MonoClass *klass;
2837 MonoGenericContext tmp_context;
2838 MonoType **type_argv;
2839 MonoGenericInst *ginst;
2840 MonoMethod *method, *inflated;
2841 int count, i;
2843 method = inflate_method (m->inst, (MonoObject*)m->mb);
2845 klass = method->klass;
2847 if (m->method_args == NULL)
2848 return method;
2850 if (method->is_inflated)
2851 method = ((MonoMethodInflated *) method)->declaring;
2853 count = mono_array_length (m->method_args);
2855 type_argv = g_new0 (MonoType *, count);
2856 for (i = 0; i < count; i++) {
2857 MonoReflectionType *garg = mono_array_get (m->method_args, gpointer, i);
2858 type_argv [i] = mono_reflection_type_get_handle (garg);
2860 ginst = mono_metadata_get_generic_inst (count, type_argv);
2861 g_free (type_argv);
2863 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
2864 tmp_context.method_inst = ginst;
2866 inflated = mono_class_inflate_generic_method (method, &tmp_context);
2867 return inflated;
2870 static guint32
2871 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
2873 guint32 sig, token = 0;
2874 MonoType *type;
2875 MonoClass *klass;
2877 if (m->method_args) {
2878 MonoMethod *inflated;
2880 inflated = mono_reflection_method_on_tb_inst_get_handle (m);
2881 if (create_methodspec)
2882 token = mono_image_get_methodspec_token (assembly, inflated);
2883 else
2884 token = mono_image_get_inflated_method_token (assembly, inflated);
2885 return token;
2888 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
2889 if (token)
2890 return token;
2892 if (is_sre_method_builder (mono_object_class (m->mb))) {
2893 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
2894 MonoGenericClass *gclass;
2895 ReflectionMethodBuilder rmb;
2896 char *name;
2898 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2899 klass = mono_class_from_mono_type (type);
2900 gclass = type->data.generic_class;
2901 g_assert (gclass->is_dynamic);
2903 reflection_methodbuilder_from_method_builder (&rmb, mb);
2905 name = mono_string_to_utf8 (rmb.name);
2907 sig = method_builder_encode_signature (assembly, &rmb);
2909 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2910 g_free (name);
2911 } else if (is_sr_mono_method (mono_object_class (m->mb))) {
2912 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
2914 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2915 klass = mono_class_from_mono_type (type);
2917 sig = method_encode_signature (assembly, mono_method_signature (mm));
2918 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2919 } else {
2920 char *name = mono_type_get_full_name (mono_object_class (m->mb));
2921 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2924 mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
2925 return token;
2928 static guint32
2929 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
2931 SigBuffer buf;
2932 int i;
2933 guint32 nparams = context->method_inst->type_argc;
2934 guint32 idx;
2936 if (!assembly->save)
2937 return 0;
2939 sigbuffer_init (&buf, 32);
2941 * FIXME: vararg, explicit_this, differenc call_conv values...
2943 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
2944 sigbuffer_add_value (&buf, nparams);
2946 for (i = 0; i < nparams; i++)
2947 encode_type (assembly, context->method_inst->type_argv [i], &buf);
2949 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2950 sigbuffer_free (&buf);
2951 return idx;
2954 static guint32
2955 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2957 MonoDynamicTable *table;
2958 guint32 *values;
2959 guint32 token, mtoken = 0, sig;
2960 MonoMethodInflated *imethod;
2961 MonoMethod *declaring;
2963 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2965 g_assert (method->is_inflated);
2966 imethod = (MonoMethodInflated *) method;
2967 declaring = imethod->declaring;
2969 sig = method_encode_signature (assembly, mono_method_signature (declaring));
2970 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2972 if (!mono_method_signature (declaring)->generic_param_count)
2973 return mtoken;
2975 switch (mono_metadata_token_table (mtoken)) {
2976 case MONO_TABLE_MEMBERREF:
2977 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2978 break;
2979 case MONO_TABLE_METHOD:
2980 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2981 break;
2982 default:
2983 g_assert_not_reached ();
2986 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
2988 if (assembly->save) {
2989 alloc_table (table, table->rows + 1);
2990 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2991 values [MONO_METHODSPEC_METHOD] = mtoken;
2992 values [MONO_METHODSPEC_SIGNATURE] = sig;
2995 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2996 table->next_idx ++;
2998 return token;
3001 static guint32
3002 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3004 MonoMethodInflated *imethod;
3005 guint32 token;
3007 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3008 if (token)
3009 return token;
3011 g_assert (method->is_inflated);
3012 imethod = (MonoMethodInflated *) method;
3014 if (mono_method_signature (imethod->declaring)->generic_param_count) {
3015 token = method_encode_methodspec (assembly, method);
3016 } else {
3017 guint32 sig = method_encode_signature (
3018 assembly, mono_method_signature (imethod->declaring));
3019 token = mono_image_get_memberref_token (
3020 assembly, &method->klass->byval_arg, method->name, sig);
3023 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3024 return token;
3027 static guint32
3028 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3030 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3031 guint32 sig, token;
3033 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3034 token = mono_image_get_memberref_token (
3035 assembly, &m->klass->byval_arg, m->name, sig);
3037 return token;
3040 static guint32
3041 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
3043 MonoDynamicTable *table;
3044 MonoClass *klass;
3045 MonoType *type;
3046 guint32 *values;
3047 guint32 token;
3048 SigBuffer buf;
3049 int count, i;
3052 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3053 * ie. what we'd normally use as the generic type in a TypeSpec signature.
3054 * Because of this, we must not insert it into the `typeref' hash table.
3056 type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
3057 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3058 if (token)
3059 return token;
3061 sigbuffer_init (&buf, 32);
3063 g_assert (tb->generic_params);
3064 klass = mono_class_from_mono_type (type);
3066 if (tb->generic_container)
3067 mono_reflection_create_generic_class (tb);
3069 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3070 g_assert (klass->generic_container);
3071 sigbuffer_add_value (&buf, klass->byval_arg.type);
3072 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3074 count = mono_array_length (tb->generic_params);
3075 sigbuffer_add_value (&buf, count);
3076 for (i = 0; i < count; i++) {
3077 MonoReflectionGenericParam *gparam;
3079 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3081 encode_type (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)gparam), &buf);
3084 table = &assembly->tables [MONO_TABLE_TYPESPEC];
3086 if (assembly->save) {
3087 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3088 alloc_table (table, table->rows + 1);
3089 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3090 values [MONO_TYPESPEC_SIGNATURE] = token;
3092 sigbuffer_free (&buf);
3094 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3095 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3096 table->next_idx ++;
3097 return token;
3101 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3103 static MonoType*
3104 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
3106 int i, count, len, pos;
3107 MonoType *t;
3109 count = 0;
3110 if (modreq)
3111 count += mono_array_length (modreq);
3112 if (modopt)
3113 count += mono_array_length (modopt);
3115 if (count == 0)
3116 return mono_metadata_type_dup (NULL, type);
3118 len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3119 t = g_malloc (len);
3120 memcpy (t, type, MONO_SIZEOF_TYPE);
3122 t->num_mods = count;
3123 pos = 0;
3124 if (modreq) {
3125 for (i = 0; i < mono_array_length (modreq); ++i) {
3126 MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
3127 t->modifiers [pos].required = 1;
3128 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3129 pos ++;
3132 if (modopt) {
3133 for (i = 0; i < mono_array_length (modopt); ++i) {
3134 MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
3135 t->modifiers [pos].required = 0;
3136 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3137 pos ++;
3141 return t;
3144 static guint32
3145 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3147 MonoDynamicTable *table;
3148 MonoClass *klass;
3149 MonoType *custom = NULL;
3150 guint32 *values;
3151 guint32 token, pclass, parent, sig;
3152 gchar *name;
3154 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3155 if (token)
3156 return token;
3158 klass = mono_class_from_mono_type (mono_reflection_type_get_handle (fb->typeb));
3159 name = mono_string_to_utf8 (fb->name);
3161 /* fb->type does not include the custom modifiers */
3162 /* FIXME: We should do this in one place when a fieldbuilder is created */
3163 if (fb->modreq || fb->modopt) {
3164 custom = add_custom_modifiers (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type), fb->modreq, fb->modopt);
3165 sig = fieldref_encode_signature (assembly, NULL, custom);
3166 g_free (custom);
3167 } else {
3168 sig = fieldref_encode_signature (assembly, NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
3171 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3172 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3174 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3175 parent >>= MONO_TYPEDEFORREF_BITS;
3177 table = &assembly->tables [MONO_TABLE_MEMBERREF];
3179 if (assembly->save) {
3180 alloc_table (table, table->rows + 1);
3181 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3182 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3183 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3184 values [MONO_MEMBERREF_SIGNATURE] = sig;
3187 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3188 table->next_idx ++;
3189 mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3190 g_free (name);
3191 return token;
3194 static guint32
3195 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3197 SigBuffer buf;
3198 guint32 nargs;
3199 guint32 size;
3200 guint32 i, idx;
3202 if (!assembly->save)
3203 return 0;
3205 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3206 g_assert (helper->type == 2);
3208 if (helper->arguments)
3209 nargs = mono_array_length (helper->arguments);
3210 else
3211 nargs = 0;
3213 size = 10 + (nargs * 10);
3215 sigbuffer_init (&buf, 32);
3217 /* Encode calling convention */
3218 /* Change Any to Standard */
3219 if ((helper->call_conv & 0x03) == 0x03)
3220 helper->call_conv = 0x01;
3221 /* explicit_this implies has_this */
3222 if (helper->call_conv & 0x40)
3223 helper->call_conv &= 0x20;
3225 if (helper->call_conv == 0) { /* Unmanaged */
3226 idx = helper->unmanaged_call_conv - 1;
3227 } else {
3228 /* Managed */
3229 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3230 if (helper->call_conv & 0x02) /* varargs */
3231 idx += 0x05;
3234 sigbuffer_add_byte (&buf, idx);
3235 sigbuffer_add_value (&buf, nargs);
3236 encode_reflection_type (assembly, helper->return_type, &buf);
3237 for (i = 0; i < nargs; ++i) {
3238 MonoArray *modreqs = NULL;
3239 MonoArray *modopts = NULL;
3240 MonoReflectionType *pt;
3242 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3243 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3244 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3245 modopts = mono_array_get (helper->modopts, MonoArray*, i);
3247 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3248 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3249 encode_reflection_type (assembly, pt, &buf);
3251 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3252 sigbuffer_free (&buf);
3254 return idx;
3257 static guint32
3258 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3260 guint32 idx;
3261 MonoDynamicTable *table;
3262 guint32 *values;
3264 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3265 idx = table->next_idx ++;
3266 table->rows ++;
3267 alloc_table (table, table->rows);
3268 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3270 values [MONO_STAND_ALONE_SIGNATURE] =
3271 mono_reflection_encode_sighelper (assembly, helper);
3273 return idx;
3276 static int
3277 reflection_cc_to_file (int call_conv) {
3278 switch (call_conv & 0x3) {
3279 case 0:
3280 case 1: return MONO_CALL_DEFAULT;
3281 case 2: return MONO_CALL_VARARG;
3282 default:
3283 g_assert_not_reached ();
3285 return 0;
3287 #endif /* !DISABLE_REFLECTION_EMIT */
3289 typedef struct {
3290 MonoType *parent;
3291 MonoMethodSignature *sig;
3292 char *name;
3293 guint32 token;
3294 } ArrayMethod;
3296 #ifndef DISABLE_REFLECTION_EMIT
3297 static guint32
3298 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3300 guint32 nparams, i;
3301 GList *tmp;
3302 char *name;
3303 MonoMethodSignature *sig;
3304 ArrayMethod *am;
3305 MonoType *mtype;
3307 name = mono_string_to_utf8 (m->name);
3308 nparams = mono_array_length (m->parameters);
3309 sig = g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3310 sig->hasthis = 1;
3311 sig->sentinelpos = -1;
3312 sig->call_convention = reflection_cc_to_file (m->call_conv);
3313 sig->param_count = nparams;
3314 sig->ret = m->ret ? mono_reflection_type_get_handle (m->ret): &mono_defaults.void_class->byval_arg;
3315 mtype = mono_reflection_type_get_handle (m->parent);
3316 for (i = 0; i < nparams; ++i)
3317 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i);
3319 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3320 am = tmp->data;
3321 if (strcmp (name, am->name) == 0 &&
3322 mono_metadata_type_equal (am->parent, mtype) &&
3323 mono_metadata_signature_equal (am->sig, sig)) {
3324 g_free (name);
3325 g_free (sig);
3326 m->table_idx = am->token & 0xffffff;
3327 return am->token;
3330 am = g_new0 (ArrayMethod, 1);
3331 am->name = name;
3332 am->sig = sig;
3333 am->parent = mtype;
3334 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3335 method_encode_signature (assembly, sig));
3336 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3337 m->table_idx = am->token & 0xffffff;
3338 return am->token;
3342 * Insert into the metadata tables all the info about the TypeBuilder tb.
3343 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3345 static void
3346 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3348 MonoDynamicTable *table;
3349 guint *values;
3350 int i, is_object = 0, is_system = 0;
3351 char *n;
3353 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3354 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3355 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3356 n = mono_string_to_utf8 (tb->name);
3357 if (strcmp (n, "Object") == 0)
3358 is_object++;
3359 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3360 g_free (n);
3361 n = mono_string_to_utf8 (tb->nspace);
3362 if (strcmp (n, "System") == 0)
3363 is_system++;
3364 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3365 g_free (n);
3366 if (tb->parent && !(is_system && is_object) &&
3367 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3368 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
3369 } else {
3370 values [MONO_TYPEDEF_EXTENDS] = 0;
3372 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3373 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3376 * if we have explicitlayout or sequentiallayouts, output data in the
3377 * ClassLayout table.
3379 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3380 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3381 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3382 table->rows++;
3383 alloc_table (table, table->rows);
3384 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3385 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3386 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3387 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3390 /* handle interfaces */
3391 if (tb->interfaces) {
3392 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3393 i = table->rows;
3394 table->rows += mono_array_length (tb->interfaces);
3395 alloc_table (table, table->rows);
3396 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3397 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3398 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3399 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3400 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (iface));
3401 values += MONO_INTERFACEIMPL_SIZE;
3405 /* handle fields */
3406 if (tb->fields) {
3407 table = &assembly->tables [MONO_TABLE_FIELD];
3408 table->rows += tb->num_fields;
3409 alloc_table (table, table->rows);
3410 for (i = 0; i < tb->num_fields; ++i)
3411 mono_image_get_field_info (
3412 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3415 /* handle constructors */
3416 if (tb->ctors) {
3417 table = &assembly->tables [MONO_TABLE_METHOD];
3418 table->rows += mono_array_length (tb->ctors);
3419 alloc_table (table, table->rows);
3420 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3421 mono_image_get_ctor_info (domain,
3422 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3425 /* handle methods */
3426 if (tb->methods) {
3427 table = &assembly->tables [MONO_TABLE_METHOD];
3428 table->rows += tb->num_methods;
3429 alloc_table (table, table->rows);
3430 for (i = 0; i < tb->num_methods; ++i)
3431 mono_image_get_method_info (
3432 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3435 /* Do the same with properties etc.. */
3436 if (tb->events && mono_array_length (tb->events)) {
3437 table = &assembly->tables [MONO_TABLE_EVENT];
3438 table->rows += mono_array_length (tb->events);
3439 alloc_table (table, table->rows);
3440 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3441 table->rows ++;
3442 alloc_table (table, table->rows);
3443 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3444 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3445 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3446 for (i = 0; i < mono_array_length (tb->events); ++i)
3447 mono_image_get_event_info (
3448 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3450 if (tb->properties && mono_array_length (tb->properties)) {
3451 table = &assembly->tables [MONO_TABLE_PROPERTY];
3452 table->rows += mono_array_length (tb->properties);
3453 alloc_table (table, table->rows);
3454 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3455 table->rows ++;
3456 alloc_table (table, table->rows);
3457 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3458 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3459 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3460 for (i = 0; i < mono_array_length (tb->properties); ++i)
3461 mono_image_get_property_info (
3462 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3465 /* handle generic parameters */
3466 if (tb->generic_params) {
3467 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3468 table->rows += mono_array_length (tb->generic_params);
3469 alloc_table (table, table->rows);
3470 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3471 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3473 mono_image_get_generic_param_info (
3474 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3478 mono_image_add_decl_security (assembly,
3479 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3481 if (tb->subtypes) {
3482 MonoDynamicTable *ntable;
3484 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3485 ntable->rows += mono_array_length (tb->subtypes);
3486 alloc_table (ntable, ntable->rows);
3487 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3489 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3490 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3492 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3493 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3494 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3495 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3496 mono_string_to_utf8 (tb->name), tb->table_idx,
3497 ntable->next_idx, ntable->rows);*/
3498 values += MONO_NESTED_CLASS_SIZE;
3499 ntable->next_idx++;
3503 #endif
3505 static void
3506 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
3508 int i;
3510 mono_ptr_array_append (*types, type);
3512 if (!type->subtypes)
3513 return;
3515 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3516 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3517 collect_types (types, subtype);
3521 static gint
3522 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3524 if ((*type1)->table_idx < (*type2)->table_idx)
3525 return -1;
3526 else
3527 if ((*type1)->table_idx > (*type2)->table_idx)
3528 return 1;
3529 else
3530 return 0;
3533 static void
3534 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3535 int i;
3537 if (!pinfo)
3538 return;
3539 for (i = 0; i < mono_array_length (pinfo); ++i) {
3540 MonoReflectionParamBuilder *pb;
3541 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3542 if (!pb)
3543 continue;
3544 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3548 static void
3549 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3550 int i;
3552 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3553 if (tb->fields) {
3554 for (i = 0; i < tb->num_fields; ++i) {
3555 MonoReflectionFieldBuilder* fb;
3556 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3557 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3560 if (tb->events) {
3561 for (i = 0; i < mono_array_length (tb->events); ++i) {
3562 MonoReflectionEventBuilder* eb;
3563 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3564 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3567 if (tb->properties) {
3568 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3569 MonoReflectionPropertyBuilder* pb;
3570 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3571 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3574 if (tb->ctors) {
3575 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3576 MonoReflectionCtorBuilder* cb;
3577 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3578 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3579 params_add_cattrs (assembly, cb->pinfo);
3583 if (tb->methods) {
3584 for (i = 0; i < tb->num_methods; ++i) {
3585 MonoReflectionMethodBuilder* mb;
3586 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3587 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3588 params_add_cattrs (assembly, mb->pinfo);
3592 if (tb->subtypes) {
3593 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3594 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3598 static void
3599 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3601 int i;
3603 mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3605 if (moduleb->global_methods) {
3606 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3607 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3608 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3609 params_add_cattrs (assembly, mb->pinfo);
3613 if (moduleb->global_fields) {
3614 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3615 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3616 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3620 if (moduleb->types) {
3621 for (i = 0; i < moduleb->num_types; ++i)
3622 type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3626 static void
3627 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3629 MonoDynamicTable *table;
3630 guint32 *values;
3631 char blob_size [6];
3632 guchar hash [20];
3633 char *b = blob_size;
3634 char *dir, *path;
3636 table = &assembly->tables [MONO_TABLE_FILE];
3637 table->rows++;
3638 alloc_table (table, table->rows);
3639 values = table->values + table->next_idx * MONO_FILE_SIZE;
3640 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3641 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3642 if (module->image->dynamic) {
3643 /* This depends on the fact that the main module is emitted last */
3644 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3645 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3646 } else {
3647 dir = NULL;
3648 path = g_strdup (module->image->name);
3650 mono_sha1_get_digest_from_file (path, hash);
3651 g_free (dir);
3652 g_free (path);
3653 mono_metadata_encode_value (20, b, &b);
3654 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3655 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3656 table->next_idx ++;
3659 static void
3660 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3662 MonoDynamicTable *table;
3663 int i;
3665 table = &assembly->tables [MONO_TABLE_MODULE];
3666 mb->table_idx = table->next_idx ++;
3667 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3668 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3669 i /= 16;
3670 ++i;
3671 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3672 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3673 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3674 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3677 static guint32
3678 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3679 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3681 MonoDynamicTable *table;
3682 guint32 *values;
3683 guint32 visib, res;
3685 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3686 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3687 return 0;
3689 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3690 table->rows++;
3691 alloc_table (table, table->rows);
3692 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3694 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3695 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3696 if (klass->nested_in)
3697 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3698 else
3699 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3700 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3701 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3703 res = table->next_idx;
3705 table->next_idx ++;
3707 /* Emit nested types */
3708 if (klass->ext && klass->ext->nested_classes) {
3709 GList *tmp;
3711 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
3712 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3715 return res;
3718 static void
3719 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3720 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3722 MonoClass *klass;
3723 guint32 idx, i;
3725 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
3727 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3729 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3730 parent_index, assembly);
3733 * Emit nested types
3734 * We need to do this ourselves since klass->nested_classes is not set up.
3736 if (tb->subtypes) {
3737 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3738 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3742 static void
3743 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3744 guint32 module_index, MonoDynamicImage *assembly)
3746 MonoImage *image = module->image;
3747 MonoTableInfo *t;
3748 guint32 i;
3750 t = &image->tables [MONO_TABLE_TYPEDEF];
3752 for (i = 0; i < t->rows; ++i) {
3753 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3755 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3756 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3760 static void
3761 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
3763 MonoDynamicTable *table;
3764 guint32 *values;
3765 guint32 scope, scope_idx, impl, current_idx;
3766 gboolean forwarder = TRUE;
3767 gpointer iter = NULL;
3768 MonoClass *nested;
3770 if (klass->nested_in) {
3771 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3772 forwarder = FALSE;
3773 } else {
3774 scope = resolution_scope_from_image (assembly, klass->image);
3775 g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3776 scope_idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3777 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3780 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3782 table->rows++;
3783 alloc_table (table, table->rows);
3784 current_idx = table->next_idx;
3785 values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
3787 values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
3788 values [MONO_EXP_TYPE_TYPEDEF] = 0;
3789 values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
3790 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3791 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3793 table->next_idx++;
3795 while ((nested = mono_class_get_nested_types (klass, &iter)))
3796 add_exported_type (assemblyb, assembly, nested, current_idx);
3799 static void
3800 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3802 MonoClass *klass;
3803 int i;
3805 if (!assemblyb->type_forwarders)
3806 return;
3808 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3809 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
3810 MonoType *type;
3811 if (!t)
3812 continue;
3814 type = mono_reflection_type_get_handle (t);
3815 g_assert (type);
3817 klass = mono_class_from_mono_type (type);
3819 add_exported_type (assemblyb, assembly, klass, 0);
3823 #define align_pointer(base,p)\
3824 do {\
3825 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3826 if (__diff & 3)\
3827 (p) += 4 - (__diff & 3);\
3828 } while (0)
3830 static int
3831 compare_constants (const void *a, const void *b)
3833 const guint32 *a_values = a;
3834 const guint32 *b_values = b;
3835 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3838 static int
3839 compare_semantics (const void *a, const void *b)
3841 const guint32 *a_values = a;
3842 const guint32 *b_values = b;
3843 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3844 if (assoc)
3845 return assoc;
3846 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3849 static int
3850 compare_custom_attrs (const void *a, const void *b)
3852 const guint32 *a_values = a;
3853 const guint32 *b_values = b;
3855 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3858 static int
3859 compare_field_marshal (const void *a, const void *b)
3861 const guint32 *a_values = a;
3862 const guint32 *b_values = b;
3864 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3867 static int
3868 compare_nested (const void *a, const void *b)
3870 const guint32 *a_values = a;
3871 const guint32 *b_values = b;
3873 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3876 static int
3877 compare_genericparam (const void *a, const void *b)
3879 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3880 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3882 if ((*b_entry)->owner == (*a_entry)->owner)
3883 return
3884 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam)) -
3885 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam));
3886 else
3887 return (*a_entry)->owner - (*b_entry)->owner;
3890 static int
3891 compare_declsecurity_attrs (const void *a, const void *b)
3893 const guint32 *a_values = a;
3894 const guint32 *b_values = b;
3896 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3899 static int
3900 compare_interface_impl (const void *a, const void *b)
3902 const guint32 *a_values = a;
3903 const guint32 *b_values = b;
3905 int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
3906 if (klass)
3907 return klass;
3909 return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
3912 static void
3913 pad_heap (MonoDynamicStream *sh)
3915 if (sh->index & 3) {
3916 int sz = 4 - (sh->index & 3);
3917 memset (sh->data + sh->index, 0, sz);
3918 sh->index += sz;
3922 struct StreamDesc {
3923 const char *name;
3924 MonoDynamicStream *stream;
3928 * build_compressed_metadata() fills in the blob of data that represents the
3929 * raw metadata as it will be saved in the PE file. The five streams are output
3930 * and the metadata tables are comnpressed from the guint32 array representation,
3931 * to the compressed on-disk format.
3933 static void
3934 build_compressed_metadata (MonoDynamicImage *assembly)
3936 MonoDynamicTable *table;
3937 int i;
3938 guint64 valid_mask = 0;
3939 guint64 sorted_mask;
3940 guint32 heapt_size = 0;
3941 guint32 meta_size = 256; /* allow for header and other stuff */
3942 guint32 table_offset;
3943 guint32 ntables = 0;
3944 guint64 *int64val;
3945 guint32 *int32val;
3946 guint16 *int16val;
3947 MonoImage *meta;
3948 unsigned char *p;
3949 struct StreamDesc stream_desc [5];
3951 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3952 for (i = 0; i < assembly->gen_params->len; i++){
3953 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3954 write_generic_param_entry (assembly, entry);
3957 stream_desc [0].name = "#~";
3958 stream_desc [0].stream = &assembly->tstream;
3959 stream_desc [1].name = "#Strings";
3960 stream_desc [1].stream = &assembly->sheap;
3961 stream_desc [2].name = "#US";
3962 stream_desc [2].stream = &assembly->us;
3963 stream_desc [3].name = "#Blob";
3964 stream_desc [3].stream = &assembly->blob;
3965 stream_desc [4].name = "#GUID";
3966 stream_desc [4].stream = &assembly->guid;
3968 /* tables that are sorted */
3969 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3970 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3971 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3972 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3973 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3974 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
3975 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
3977 /* Compute table sizes */
3978 /* the MonoImage has already been created in mono_image_basic_init() */
3979 meta = &assembly->image;
3981 /* sizes should be multiple of 4 */
3982 pad_heap (&assembly->blob);
3983 pad_heap (&assembly->guid);
3984 pad_heap (&assembly->sheap);
3985 pad_heap (&assembly->us);
3987 /* Setup the info used by compute_sizes () */
3988 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3989 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3990 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3992 meta_size += assembly->blob.index;
3993 meta_size += assembly->guid.index;
3994 meta_size += assembly->sheap.index;
3995 meta_size += assembly->us.index;
3997 for (i=0; i < MONO_TABLE_NUM; ++i)
3998 meta->tables [i].rows = assembly->tables [i].rows;
4000 for (i = 0; i < MONO_TABLE_NUM; i++){
4001 if (meta->tables [i].rows == 0)
4002 continue;
4003 valid_mask |= (guint64)1 << i;
4004 ntables ++;
4005 meta->tables [i].row_size = mono_metadata_compute_size (
4006 meta, i, &meta->tables [i].size_bitfield);
4007 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4009 heapt_size += 24; /* #~ header size */
4010 heapt_size += ntables * 4;
4011 /* make multiple of 4 */
4012 heapt_size += 3;
4013 heapt_size &= ~3;
4014 meta_size += heapt_size;
4015 meta->raw_metadata = g_malloc0 (meta_size);
4016 p = (unsigned char*)meta->raw_metadata;
4017 /* the metadata signature */
4018 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4019 /* version numbers and 4 bytes reserved */
4020 int16val = (guint16*)p;
4021 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4022 *int16val = GUINT16_TO_LE (meta->md_version_minor);
4023 p += 8;
4024 /* version string */
4025 int32val = (guint32*)p;
4026 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4027 p += 4;
4028 memcpy (p, meta->version, strlen (meta->version));
4029 p += GUINT32_FROM_LE (*int32val);
4030 align_pointer (meta->raw_metadata, p);
4031 int16val = (guint16*)p;
4032 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4033 *int16val = GUINT16_TO_LE (5); /* number of streams */
4034 p += 4;
4037 * write the stream info.
4039 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4040 table_offset += 3; table_offset &= ~3;
4042 assembly->tstream.index = heapt_size;
4043 for (i = 0; i < 5; ++i) {
4044 int32val = (guint32*)p;
4045 stream_desc [i].stream->offset = table_offset;
4046 *int32val++ = GUINT32_TO_LE (table_offset);
4047 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4048 table_offset += GUINT32_FROM_LE (*int32val);
4049 table_offset += 3; table_offset &= ~3;
4050 p += 8;
4051 strcpy ((char*)p, stream_desc [i].name);
4052 p += strlen (stream_desc [i].name) + 1;
4053 align_pointer (meta->raw_metadata, p);
4056 * now copy the data, the table stream header and contents goes first.
4058 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4059 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4060 int32val = (guint32*)p;
4061 *int32val = GUINT32_TO_LE (0); /* reserved */
4062 p += 4;
4064 *p++ = 2; /* version */
4065 *p++ = 0;
4067 if (meta->idx_string_wide)
4068 *p |= 0x01;
4069 if (meta->idx_guid_wide)
4070 *p |= 0x02;
4071 if (meta->idx_blob_wide)
4072 *p |= 0x04;
4073 ++p;
4074 *p++ = 1; /* reserved */
4075 int64val = (guint64*)p;
4076 *int64val++ = GUINT64_TO_LE (valid_mask);
4077 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
4078 p += 16;
4079 int32val = (guint32*)p;
4080 for (i = 0; i < MONO_TABLE_NUM; i++){
4081 if (meta->tables [i].rows == 0)
4082 continue;
4083 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4085 p = (unsigned char*)int32val;
4087 /* sort the tables that still need sorting */
4088 table = &assembly->tables [MONO_TABLE_CONSTANT];
4089 if (table->rows)
4090 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4091 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4092 if (table->rows)
4093 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4094 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4095 if (table->rows)
4096 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4097 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4098 if (table->rows)
4099 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4100 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4101 if (table->rows)
4102 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4103 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4104 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4105 if (table->rows)
4106 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4107 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4108 if (table->rows)
4109 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4111 /* compress the tables */
4112 for (i = 0; i < MONO_TABLE_NUM; i++){
4113 int row, col;
4114 guint32 *values;
4115 guint32 bitfield = meta->tables [i].size_bitfield;
4116 if (!meta->tables [i].rows)
4117 continue;
4118 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4119 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4120 meta->tables [i].base = (char*)p;
4121 for (row = 1; row <= meta->tables [i].rows; ++row) {
4122 values = assembly->tables [i].values + row * assembly->tables [i].columns;
4123 for (col = 0; col < assembly->tables [i].columns; ++col) {
4124 switch (mono_metadata_table_size (bitfield, col)) {
4125 case 1:
4126 *p++ = values [col];
4127 break;
4128 case 2:
4129 *p++ = values [col] & 0xff;
4130 *p++ = (values [col] >> 8) & 0xff;
4131 break;
4132 case 4:
4133 *p++ = values [col] & 0xff;
4134 *p++ = (values [col] >> 8) & 0xff;
4135 *p++ = (values [col] >> 16) & 0xff;
4136 *p++ = (values [col] >> 24) & 0xff;
4137 break;
4138 default:
4139 g_assert_not_reached ();
4143 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4146 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4147 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4148 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4149 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4150 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4152 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4156 * Some tables in metadata need to be sorted according to some criteria, but
4157 * when methods and fields are first created with reflection, they may be assigned a token
4158 * that doesn't correspond to the final token they will get assigned after the sorting.
4159 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4160 * with the reflection objects that represent them. Once all the tables are set up, the
4161 * reflection objects will contains the correct table index. fixup_method() will fixup the
4162 * tokens for the method with ILGenerator @ilgen.
4164 static void
4165 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4167 guint32 code_idx = GPOINTER_TO_UINT (value);
4168 MonoReflectionILTokenInfo *iltoken;
4169 MonoReflectionFieldBuilder *field;
4170 MonoReflectionCtorBuilder *ctor;
4171 MonoReflectionMethodBuilder *method;
4172 MonoReflectionTypeBuilder *tb;
4173 MonoReflectionArrayMethod *am;
4174 guint32 i, idx = 0;
4175 unsigned char *target;
4177 for (i = 0; i < ilgen->num_token_fixups; ++i) {
4178 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4179 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4180 switch (target [3]) {
4181 case MONO_TABLE_FIELD:
4182 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4183 field = (MonoReflectionFieldBuilder *)iltoken->member;
4184 idx = field->table_idx;
4185 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4186 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4187 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4188 } else {
4189 g_assert_not_reached ();
4191 break;
4192 case MONO_TABLE_METHOD:
4193 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4194 method = (MonoReflectionMethodBuilder *)iltoken->member;
4195 idx = method->table_idx;
4196 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4197 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4198 idx = ctor->table_idx;
4199 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4200 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4201 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4202 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4203 } else {
4204 g_assert_not_reached ();
4206 break;
4207 case MONO_TABLE_TYPEDEF:
4208 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4209 g_assert_not_reached ();
4210 tb = (MonoReflectionTypeBuilder *)iltoken->member;
4211 idx = tb->table_idx;
4212 break;
4213 case MONO_TABLE_MEMBERREF:
4214 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4215 am = (MonoReflectionArrayMethod*)iltoken->member;
4216 idx = am->table_idx;
4217 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4218 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4219 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4220 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4221 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4222 g_assert (m->klass->generic_class || m->klass->generic_container);
4223 continue;
4224 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4225 continue;
4226 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4227 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4228 g_assert (is_field_on_inst (f));
4229 continue;
4230 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4231 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4232 continue;
4233 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4234 continue;
4235 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4236 continue;
4237 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4238 continue;
4239 } else {
4240 g_assert_not_reached ();
4242 break;
4243 case MONO_TABLE_METHODSPEC:
4244 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4245 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4246 g_assert (mono_method_signature (m)->generic_param_count);
4247 continue;
4248 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4249 continue;
4250 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4251 continue;
4252 } else {
4253 g_assert_not_reached ();
4255 break;
4256 default:
4257 g_error ("got unexpected table 0x%02x in fixup", target [3]);
4259 target [0] = idx & 0xff;
4260 target [1] = (idx >> 8) & 0xff;
4261 target [2] = (idx >> 16) & 0xff;
4266 * fixup_cattrs:
4268 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4269 * value is not known when the table is emitted.
4271 static void
4272 fixup_cattrs (MonoDynamicImage *assembly)
4274 MonoDynamicTable *table;
4275 guint32 *values;
4276 guint32 type, i, idx, token;
4277 MonoObject *ctor;
4279 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4281 for (i = 0; i < table->rows; ++i) {
4282 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4284 type = values [MONO_CUSTOM_ATTR_TYPE];
4285 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4286 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4287 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4288 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4289 g_assert (ctor);
4291 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4292 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4293 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4294 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4300 static void
4301 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4303 MonoDynamicTable *table;
4304 guint32 *values;
4306 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4307 table->rows++;
4308 alloc_table (table, table->rows);
4309 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4310 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4311 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4312 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4313 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4314 table->next_idx++;
4317 static void
4318 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4320 MonoDynamicTable *table;
4321 guint32 *values;
4322 char blob_size [6];
4323 guchar hash [20];
4324 char *b = blob_size;
4325 char *name, *sname;
4326 guint32 idx, offset;
4328 if (rsrc->filename) {
4329 name = mono_string_to_utf8 (rsrc->filename);
4330 sname = g_path_get_basename (name);
4332 table = &assembly->tables [MONO_TABLE_FILE];
4333 table->rows++;
4334 alloc_table (table, table->rows);
4335 values = table->values + table->next_idx * MONO_FILE_SIZE;
4336 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4337 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4338 g_free (sname);
4340 mono_sha1_get_digest_from_file (name, hash);
4341 mono_metadata_encode_value (20, b, &b);
4342 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4343 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4344 g_free (name);
4345 idx = table->next_idx++;
4346 rsrc->offset = 0;
4347 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4348 } else {
4349 char sizebuf [4];
4350 char *data;
4351 guint len;
4352 if (rsrc->data) {
4353 data = mono_array_addr (rsrc->data, char, 0);
4354 len = mono_array_length (rsrc->data);
4355 } else {
4356 data = NULL;
4357 len = 0;
4359 offset = len;
4360 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4361 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4362 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4363 mono_image_add_stream_data (&assembly->resources, data, len);
4365 if (!mb->is_main)
4367 * The entry should be emitted into the MANIFESTRESOURCE table of
4368 * the main module, but that needs to reference the FILE table
4369 * which isn't emitted yet.
4371 return;
4372 else
4373 idx = 0;
4376 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4379 static void
4380 set_version_from_string (MonoString *version, guint32 *values)
4382 gchar *ver, *p, *str;
4383 guint32 i;
4385 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4386 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4387 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4388 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4389 if (!version)
4390 return;
4391 ver = str = mono_string_to_utf8 (version);
4392 for (i = 0; i < 4; ++i) {
4393 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4394 switch (*p) {
4395 case '.':
4396 p++;
4397 break;
4398 case '*':
4399 /* handle Revision and Build */
4400 p++;
4401 break;
4403 ver = p;
4405 g_free (str);
4408 static guint32
4409 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4410 gsize len;
4411 guint32 token = 0;
4412 char blob_size [6];
4413 char *b = blob_size;
4415 if (!pkey)
4416 return token;
4418 len = mono_array_length (pkey);
4419 mono_metadata_encode_value (len, b, &b);
4420 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4421 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4423 assembly->public_key = g_malloc (len);
4424 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4425 assembly->public_key_len = len;
4427 /* Special case: check for ECMA key (16 bytes) */
4428 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4429 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4430 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4431 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4432 /* minimum key size (in 2.0) is 384 bits */
4433 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4434 } else {
4435 /* FIXME - verifier */
4436 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4437 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4439 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
4441 return token;
4444 static void
4445 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4447 MonoDynamicTable *table;
4448 MonoDynamicImage *assembly;
4449 MonoReflectionAssemblyBuilder *assemblyb;
4450 MonoDomain *domain;
4451 guint32 *values;
4452 int i;
4453 guint32 module_index;
4455 assemblyb = moduleb->assemblyb;
4456 assembly = moduleb->dynamic_image;
4457 domain = mono_object_domain (assemblyb);
4459 /* Emit ASSEMBLY table */
4460 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4461 alloc_table (table, 1);
4462 values = table->values + MONO_ASSEMBLY_SIZE;
4463 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4464 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4465 if (assemblyb->culture) {
4466 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4467 } else {
4468 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4470 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4471 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4472 set_version_from_string (assemblyb->version, values);
4474 /* Emit FILE + EXPORTED_TYPE table */
4475 module_index = 0;
4476 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4477 int j;
4478 MonoReflectionModuleBuilder *file_module =
4479 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4480 if (file_module != moduleb) {
4481 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4482 module_index ++;
4483 if (file_module->types) {
4484 for (j = 0; j < file_module->num_types; ++j) {
4485 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4486 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4491 if (assemblyb->loaded_modules) {
4492 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4493 MonoReflectionModule *file_module =
4494 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4495 mono_image_fill_file_table (domain, file_module, assembly);
4496 module_index ++;
4497 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4500 if (assemblyb->type_forwarders)
4501 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4503 /* Emit MANIFESTRESOURCE table */
4504 module_index = 0;
4505 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4506 int j;
4507 MonoReflectionModuleBuilder *file_module =
4508 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4509 /* The table for the main module is emitted later */
4510 if (file_module != moduleb) {
4511 module_index ++;
4512 if (file_module->resources) {
4513 int len = mono_array_length (file_module->resources);
4514 for (j = 0; j < len; ++j) {
4515 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4516 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4523 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4526 * mono_image_build_metadata() will fill the info in all the needed metadata tables
4527 * for the modulebuilder @moduleb.
4528 * At the end of the process, method and field tokens are fixed up and the
4529 * on-disk compressed metadata representation is created.
4531 void
4532 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4534 MonoDynamicTable *table;
4535 MonoDynamicImage *assembly;
4536 MonoReflectionAssemblyBuilder *assemblyb;
4537 MonoDomain *domain;
4538 MonoPtrArray types;
4539 guint32 *values;
4540 int i, j;
4542 assemblyb = moduleb->assemblyb;
4543 assembly = moduleb->dynamic_image;
4544 domain = mono_object_domain (assemblyb);
4546 if (assembly->text_rva)
4547 return;
4549 assembly->text_rva = START_TEXT_RVA;
4551 if (moduleb->is_main) {
4552 mono_image_emit_manifest (moduleb);
4555 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4556 table->rows = 1; /* .<Module> */
4557 table->next_idx++;
4558 alloc_table (table, table->rows);
4560 * Set the first entry.
4562 values = table->values + table->columns;
4563 values [MONO_TYPEDEF_FLAGS] = 0;
4564 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4565 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4566 values [MONO_TYPEDEF_EXTENDS] = 0;
4567 values [MONO_TYPEDEF_FIELD_LIST] = 1;
4568 values [MONO_TYPEDEF_METHOD_LIST] = 1;
4571 * handle global methods
4572 * FIXME: test what to do when global methods are defined in multiple modules.
4574 if (moduleb->global_methods) {
4575 table = &assembly->tables [MONO_TABLE_METHOD];
4576 table->rows += mono_array_length (moduleb->global_methods);
4577 alloc_table (table, table->rows);
4578 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4579 mono_image_get_method_info (
4580 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4582 if (moduleb->global_fields) {
4583 table = &assembly->tables [MONO_TABLE_FIELD];
4584 table->rows += mono_array_length (moduleb->global_fields);
4585 alloc_table (table, table->rows);
4586 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4587 mono_image_get_field_info (
4588 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4591 table = &assembly->tables [MONO_TABLE_MODULE];
4592 alloc_table (table, 1);
4593 mono_image_fill_module_table (domain, moduleb, assembly);
4595 /* Collect all types into a list sorted by their table_idx */
4596 mono_ptr_array_init (types, moduleb->num_types);
4598 if (moduleb->types)
4599 for (i = 0; i < moduleb->num_types; ++i) {
4600 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4601 collect_types (&types, type);
4604 mono_ptr_array_sort (types, (gpointer)compare_types_by_table_idx);
4605 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4606 table->rows += mono_ptr_array_size (types);
4607 alloc_table (table, table->rows);
4610 * Emit type names + namespaces at one place inside the string heap,
4611 * so load_class_names () needs to touch fewer pages.
4613 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4614 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4615 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4617 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4618 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4619 string_heap_insert_mstring (&assembly->sheap, tb->name);
4622 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4623 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4624 mono_image_get_type_info (domain, type, assembly);
4628 * table->rows is already set above and in mono_image_fill_module_table.
4630 /* add all the custom attributes at the end, once all the indexes are stable */
4631 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4633 /* CAS assembly permissions */
4634 if (assemblyb->permissions_minimum)
4635 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4636 if (assemblyb->permissions_optional)
4637 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4638 if (assemblyb->permissions_refused)
4639 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4641 module_add_cattrs (assembly, moduleb);
4643 /* fixup tokens */
4644 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4646 /* Create the MethodImpl table. We do this after emitting all methods so we already know
4647 * the final tokens and don't need another fixup pass. */
4649 if (moduleb->global_methods) {
4650 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4651 MonoReflectionMethodBuilder *mb = mono_array_get (
4652 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4653 mono_image_add_methodimpl (assembly, mb);
4657 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4658 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4659 if (type->methods) {
4660 for (j = 0; j < type->num_methods; ++j) {
4661 MonoReflectionMethodBuilder *mb = mono_array_get (
4662 type->methods, MonoReflectionMethodBuilder*, j);
4664 mono_image_add_methodimpl (assembly, mb);
4669 mono_ptr_array_destroy (types);
4671 fixup_cattrs (assembly);
4674 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4676 void
4677 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4679 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4682 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4685 typedef struct {
4686 guint32 import_lookup_table;
4687 guint32 timestamp;
4688 guint32 forwarder;
4689 guint32 name_rva;
4690 guint32 import_address_table_rva;
4691 } MonoIDT;
4693 typedef struct {
4694 guint32 name_rva;
4695 guint32 flags;
4696 } MonoILT;
4698 #ifndef DISABLE_REFLECTION_EMIT
4701 * mono_image_insert_string:
4702 * @module: module builder object
4703 * @str: a string
4705 * Insert @str into the user string stream of @module.
4707 guint32
4708 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4710 MonoDynamicImage *assembly;
4711 guint32 idx;
4712 char buf [16];
4713 char *b = buf;
4715 MONO_ARCH_SAVE_REGS;
4717 if (!module->dynamic_image)
4718 mono_image_module_basic_init (module);
4720 assembly = module->dynamic_image;
4722 if (assembly->save) {
4723 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4724 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4725 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4727 char *swapped = g_malloc (2 * mono_string_length (str));
4728 const char *p = (const char*)mono_string_chars (str);
4730 swap_with_size (swapped, p, 2, mono_string_length (str));
4731 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4732 g_free (swapped);
4734 #else
4735 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4736 #endif
4737 mono_image_add_stream_data (&assembly->us, "", 1);
4738 } else {
4739 idx = assembly->us.index ++;
4742 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4744 return MONO_TOKEN_STRING | idx;
4747 guint32
4748 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4750 MonoClass *klass;
4751 guint32 token = 0;
4753 klass = obj->vtable->klass;
4754 if (strcmp (klass->name, "MonoMethod") == 0) {
4755 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4756 MonoMethodSignature *sig, *old;
4757 guint32 sig_token, parent;
4758 int nargs, i;
4760 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4762 nargs = mono_array_length (opt_param_types);
4763 old = mono_method_signature (method);
4764 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4766 sig->hasthis = old->hasthis;
4767 sig->explicit_this = old->explicit_this;
4768 sig->call_convention = old->call_convention;
4769 sig->generic_param_count = old->generic_param_count;
4770 sig->param_count = old->param_count + nargs;
4771 sig->sentinelpos = old->param_count;
4772 sig->ret = old->ret;
4774 for (i = 0; i < old->param_count; i++)
4775 sig->params [i] = old->params [i];
4777 for (i = 0; i < nargs; i++) {
4778 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4779 sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt);
4782 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4783 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4784 parent >>= MONO_TYPEDEFORREF_BITS;
4786 parent <<= MONO_MEMBERREF_PARENT_BITS;
4787 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4789 sig_token = method_encode_signature (assembly, sig);
4790 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4791 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4792 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4793 ReflectionMethodBuilder rmb;
4794 guint32 parent, sig;
4795 char *name;
4797 reflection_methodbuilder_from_method_builder (&rmb, mb);
4798 rmb.opt_types = opt_param_types;
4800 sig = method_builder_encode_signature (assembly, &rmb);
4802 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
4803 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4805 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4806 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4808 name = mono_string_to_utf8 (rmb.name);
4809 token = mono_image_get_varargs_method_token (
4810 assembly, parent, name, sig);
4811 g_free (name);
4812 } else {
4813 g_error ("requested method token for %s\n", klass->name);
4816 return token;
4820 * mono_image_create_token:
4821 * @assembly: a dynamic assembly
4822 * @obj:
4823 * @register_token: Whenever to register the token in the assembly->tokens hash.
4825 * Get a token to insert in the IL code stream for the given MemberInfo.
4826 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
4827 * the table_idx-es were recomputed, so registering the token would overwrite an existing
4828 * entry.
4830 guint32
4831 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
4832 gboolean create_methodspec, gboolean register_token)
4834 MonoClass *klass;
4835 guint32 token = 0;
4837 klass = obj->vtable->klass;
4839 /* Check for user defined reflection objects */
4840 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
4841 if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0))
4842 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported")); \
4844 if (strcmp (klass->name, "MethodBuilder") == 0) {
4845 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4846 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4848 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
4849 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4850 else
4851 token = mono_image_get_methodbuilder_token (assembly, mb, create_methodspec);
4852 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4853 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4854 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4855 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4857 if (tb->module->dynamic_image == assembly && !tb->generic_params)
4858 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4859 else
4860 token = mono_image_get_ctorbuilder_token (assembly, mb);
4861 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4862 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4863 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4864 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4865 if (tb->generic_params) {
4866 token = mono_image_get_generic_field_token (assembly, fb);
4867 } else {
4868 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4870 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4871 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4872 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4873 } else if (strcmp (klass->name, "MonoType") == 0) {
4874 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4875 MonoClass *mc = mono_class_from_mono_type (type);
4876 if (!mono_class_init (mc))
4877 mono_raise_exception (mono_class_get_exception_for_failure (mc));
4879 token = mono_metadata_token_from_dor (
4880 mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL));
4881 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4882 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4883 token = mono_metadata_token_from_dor (
4884 mono_image_typedef_or_ref (assembly, type));
4885 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4886 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4887 token = mono_metadata_token_from_dor (
4888 mono_image_typedef_or_ref (assembly, type));
4889 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4890 strcmp (klass->name, "MonoMethod") == 0 ||
4891 strcmp (klass->name, "MonoGenericMethod") == 0 ||
4892 strcmp (klass->name, "MonoGenericCMethod") == 0) {
4893 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4894 if (m->method->is_inflated) {
4895 if (create_methodspec)
4896 token = mono_image_get_methodspec_token (assembly, m->method);
4897 else
4898 token = mono_image_get_inflated_method_token (assembly, m->method);
4899 } else if ((m->method->klass->image == &assembly->image) &&
4900 !m->method->klass->generic_class) {
4901 static guint32 method_table_idx = 0xffffff;
4902 if (m->method->klass->wastypebuilder) {
4903 /* we use the same token as the one that was assigned
4904 * to the Methodbuilder.
4905 * FIXME: do the equivalent for Fields.
4907 token = m->method->token;
4908 } else {
4910 * Each token should have a unique index, but the indexes are
4911 * assigned by managed code, so we don't know about them. An
4912 * easy solution is to count backwards...
4914 method_table_idx --;
4915 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4917 } else {
4918 token = mono_image_get_methodref_token (assembly, m->method, create_methodspec);
4920 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4921 } else if (strcmp (klass->name, "MonoField") == 0) {
4922 MonoReflectionField *f = (MonoReflectionField *)obj;
4923 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
4924 static guint32 field_table_idx = 0xffffff;
4925 field_table_idx --;
4926 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4927 } else {
4928 token = mono_image_get_fieldref_token (assembly, f);
4930 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4931 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4932 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4933 token = mono_image_get_array_token (assembly, m);
4934 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4935 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4936 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4937 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
4938 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4939 token = mono_metadata_token_from_dor (
4940 mono_image_typedef_or_ref (assembly, type));
4941 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
4942 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
4943 token = mono_image_get_field_on_inst_token (assembly, f);
4944 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
4945 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
4946 token = mono_image_get_ctor_on_inst_token (assembly, c, create_methodspec);
4947 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
4948 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
4949 token = mono_image_get_method_on_inst_token (assembly, m, create_methodspec);
4950 } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
4951 MonoReflectionType *type = (MonoReflectionType *)obj;
4952 token = mono_metadata_token_from_dor (
4953 mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (type)));
4954 } else {
4955 g_error ("requested token for %s\n", klass->name);
4958 if (register_token)
4959 mono_image_register_token (assembly, token, obj);
4961 return token;
4965 * mono_image_register_token:
4967 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
4968 * the Module.ResolveXXXToken () methods to work.
4970 void
4971 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
4973 MonoObject *prev = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4974 if (prev) {
4975 /* There could be multiple MethodInfo objects with the same token */
4976 //g_assert (prev == obj);
4977 } else {
4978 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4982 static MonoDynamicImage*
4983 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4985 static const guchar entrycode [16] = {0xff, 0x25, 0};
4986 MonoDynamicImage *image;
4987 int i;
4989 const char *version;
4991 if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
4992 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
4993 else
4994 version = mono_get_runtime_info ()->runtime_version;
4996 #if HAVE_BOEHM_GC
4997 image = GC_MALLOC (sizeof (MonoDynamicImage));
4998 #else
4999 image = g_new0 (MonoDynamicImage, 1);
5000 #endif
5002 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5004 /*g_print ("created image %p\n", image);*/
5005 /* keep in sync with image.c */
5006 image->image.name = assembly_name;
5007 image->image.assembly_name = image->image.name; /* they may be different */
5008 image->image.module_name = module_name;
5009 image->image.version = g_strdup (version);
5010 image->image.md_version_major = 1;
5011 image->image.md_version_minor = 1;
5012 image->image.dynamic = TRUE;
5014 image->image.references = g_new0 (MonoAssembly*, 1);
5015 image->image.references [0] = NULL;
5017 mono_image_init (&image->image);
5019 image->token_fixups = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5020 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5021 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5022 image->method_aux_hash = g_hash_table_new (NULL, NULL);
5023 image->handleref = g_hash_table_new (NULL, NULL);
5024 image->handleref_managed = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5025 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5026 image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5027 image->methodspec = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5028 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5029 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5030 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5031 image->gen_params = g_ptr_array_new ();
5033 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5034 string_heap_init (&image->sheap);
5035 mono_image_add_stream_data (&image->us, "", 1);
5036 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5037 /* import tables... */
5038 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5039 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5040 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5041 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5042 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5043 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5044 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5045 stream_data_align (&image->code);
5047 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5049 for (i=0; i < MONO_TABLE_NUM; ++i) {
5050 image->tables [i].next_idx = 1;
5051 image->tables [i].columns = table_sizes [i];
5054 image->image.assembly = (MonoAssembly*)assembly;
5055 image->run = assembly->run;
5056 image->save = assembly->save;
5057 image->pe_kind = 0x1; /* ILOnly */
5058 image->machine = 0x14c; /* I386 */
5060 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5062 return image;
5064 #endif
5066 static void
5067 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5069 g_free (key);
5072 void
5073 mono_dynamic_image_free (MonoDynamicImage *image)
5075 MonoDynamicImage *di = image;
5076 GList *list;
5077 int i;
5079 if (di->methodspec)
5080 mono_g_hash_table_destroy (di->methodspec);
5081 if (di->typespec)
5082 g_hash_table_destroy (di->typespec);
5083 if (di->typeref)
5084 g_hash_table_destroy (di->typeref);
5085 if (di->handleref)
5086 g_hash_table_destroy (di->handleref);
5087 if (di->handleref_managed)
5088 mono_g_hash_table_destroy (di->handleref_managed);
5089 if (di->tokens)
5090 mono_g_hash_table_destroy (di->tokens);
5091 if (di->generic_def_objects)
5092 mono_g_hash_table_destroy (di->generic_def_objects);
5093 if (di->blob_cache) {
5094 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5095 g_hash_table_destroy (di->blob_cache);
5097 if (di->standalonesig_cache)
5098 g_hash_table_destroy (di->standalonesig_cache);
5099 for (list = di->array_methods; list; list = list->next) {
5100 ArrayMethod *am = (ArrayMethod *)list->data;
5101 g_free (am->sig);
5102 g_free (am->name);
5103 g_free (am);
5105 g_list_free (di->array_methods);
5106 if (di->gen_params) {
5107 for (i = 0; i < di->gen_params->len; i++) {
5108 GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
5109 if (entry->gparam->type.type) {
5110 MonoGenericParam *param = entry->gparam->type.type->data.generic_param;
5111 g_free ((char*)mono_generic_param_info (param)->name);
5112 g_free (param);
5114 mono_gc_deregister_root ((char*) &entry->gparam);
5115 g_free (entry);
5117 g_ptr_array_free (di->gen_params, TRUE);
5119 if (di->token_fixups)
5120 mono_g_hash_table_destroy (di->token_fixups);
5121 if (di->method_to_table_idx)
5122 g_hash_table_destroy (di->method_to_table_idx);
5123 if (di->field_to_table_idx)
5124 g_hash_table_destroy (di->field_to_table_idx);
5125 if (di->method_aux_hash)
5126 g_hash_table_destroy (di->method_aux_hash);
5127 g_free (di->strong_name);
5128 g_free (di->win32_res);
5129 if (di->public_key)
5130 g_free (di->public_key);
5132 /*g_print ("string heap destroy for image %p\n", di);*/
5133 mono_dynamic_stream_reset (&di->sheap);
5134 mono_dynamic_stream_reset (&di->code);
5135 mono_dynamic_stream_reset (&di->resources);
5136 mono_dynamic_stream_reset (&di->us);
5137 mono_dynamic_stream_reset (&di->blob);
5138 mono_dynamic_stream_reset (&di->tstream);
5139 mono_dynamic_stream_reset (&di->guid);
5140 for (i = 0; i < MONO_TABLE_NUM; ++i) {
5141 g_free (di->tables [i].values);
5145 #ifndef DISABLE_REFLECTION_EMIT
5148 * mono_image_basic_init:
5149 * @assembly: an assembly builder object
5151 * Create the MonoImage that represents the assembly builder and setup some
5152 * of the helper hash table and the basic metadata streams.
5154 void
5155 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5157 MonoDynamicAssembly *assembly;
5158 MonoDynamicImage *image;
5159 MonoDomain *domain = mono_object_domain (assemblyb);
5161 MONO_ARCH_SAVE_REGS;
5163 if (assemblyb->dynamic_assembly)
5164 return;
5166 #if HAVE_BOEHM_GC
5167 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
5168 #else
5169 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5170 #endif
5172 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5174 assembly->assembly.ref_count = 1;
5175 assembly->assembly.dynamic = TRUE;
5176 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5177 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5178 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5179 if (assemblyb->culture)
5180 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5181 else
5182 assembly->assembly.aname.culture = g_strdup ("");
5184 if (assemblyb->version) {
5185 char *vstr = mono_string_to_utf8 (assemblyb->version);
5186 char **version = g_strsplit (vstr, ".", 4);
5187 char **parts = version;
5188 assembly->assembly.aname.major = atoi (*parts++);
5189 assembly->assembly.aname.minor = atoi (*parts++);
5190 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5191 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5193 g_strfreev (version);
5194 g_free (vstr);
5195 } else {
5196 assembly->assembly.aname.major = 0;
5197 assembly->assembly.aname.minor = 0;
5198 assembly->assembly.aname.build = 0;
5199 assembly->assembly.aname.revision = 0;
5202 assembly->run = assemblyb->access != 2;
5203 assembly->save = assemblyb->access != 1;
5204 assembly->domain = domain;
5206 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5207 image->initial_image = TRUE;
5208 assembly->assembly.aname.name = image->image.name;
5209 assembly->assembly.image = &image->image;
5210 if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5211 /* -1 to correct for the trailing NULL byte */
5212 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5213 g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5215 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);
5218 mono_domain_assemblies_lock (domain);
5219 domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
5220 mono_domain_assemblies_unlock (domain);
5222 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5224 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5226 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5229 #endif /* !DISABLE_REFLECTION_EMIT */
5231 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5233 static int
5234 calc_section_size (MonoDynamicImage *assembly)
5236 int nsections = 0;
5238 /* alignment constraints */
5239 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5240 g_assert ((assembly->code.index % 4) == 0);
5241 assembly->meta_size += 3;
5242 assembly->meta_size &= ~3;
5243 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5244 g_assert ((assembly->resources.index % 4) == 0);
5246 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5247 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5248 nsections++;
5250 if (assembly->win32_res) {
5251 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5253 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5254 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5255 nsections++;
5258 assembly->sections [MONO_SECTION_RELOC].size = 12;
5259 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5260 nsections++;
5262 return nsections;
5265 typedef struct {
5266 guint32 id;
5267 guint32 offset;
5268 GSList *children;
5269 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5270 } ResTreeNode;
5272 static int
5273 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5275 ResTreeNode *t1 = (ResTreeNode*)a;
5276 ResTreeNode *t2 = (ResTreeNode*)b;
5278 return t1->id - t2->id;
5282 * resource_tree_create:
5284 * Organize the resources into a resource tree.
5286 static ResTreeNode *
5287 resource_tree_create (MonoArray *win32_resources)
5289 ResTreeNode *tree, *res_node, *type_node, *lang_node;
5290 GSList *l;
5291 int i;
5293 tree = g_new0 (ResTreeNode, 1);
5295 for (i = 0; i < mono_array_length (win32_resources); ++i) {
5296 MonoReflectionWin32Resource *win32_res =
5297 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5299 /* Create node */
5301 /* FIXME: BUG: this stores managed references in unmanaged memory */
5302 lang_node = g_new0 (ResTreeNode, 1);
5303 lang_node->id = win32_res->lang_id;
5304 lang_node->win32_res = win32_res;
5306 /* Create type node if neccesary */
5307 type_node = NULL;
5308 for (l = tree->children; l; l = l->next)
5309 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5310 type_node = (ResTreeNode*)l->data;
5311 break;
5314 if (!type_node) {
5315 type_node = g_new0 (ResTreeNode, 1);
5316 type_node->id = win32_res->res_type;
5319 * The resource types have to be sorted otherwise
5320 * Windows Explorer can't display the version information.
5322 tree->children = g_slist_insert_sorted (tree->children,
5323 type_node, resource_tree_compare_by_id);
5326 /* Create res node if neccesary */
5327 res_node = NULL;
5328 for (l = type_node->children; l; l = l->next)
5329 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5330 res_node = (ResTreeNode*)l->data;
5331 break;
5334 if (!res_node) {
5335 res_node = g_new0 (ResTreeNode, 1);
5336 res_node->id = win32_res->res_id;
5337 type_node->children = g_slist_append (type_node->children, res_node);
5340 res_node->children = g_slist_append (res_node->children, lang_node);
5343 return tree;
5347 * resource_tree_encode:
5349 * Encode the resource tree into the format used in the PE file.
5351 static void
5352 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5354 char *entries;
5355 MonoPEResourceDir dir;
5356 MonoPEResourceDirEntry dir_entry;
5357 MonoPEResourceDataEntry data_entry;
5358 GSList *l;
5359 guint32 res_id_entries;
5362 * For the format of the resource directory, see the article
5363 * "An In-Depth Look into the Win32 Portable Executable File Format" by
5364 * Matt Pietrek
5367 memset (&dir, 0, sizeof (dir));
5368 memset (&dir_entry, 0, sizeof (dir_entry));
5369 memset (&data_entry, 0, sizeof (data_entry));
5371 g_assert (sizeof (dir) == 16);
5372 g_assert (sizeof (dir_entry) == 8);
5373 g_assert (sizeof (data_entry) == 16);
5375 node->offset = p - begin;
5377 /* IMAGE_RESOURCE_DIRECTORY */
5378 res_id_entries = g_slist_length (node->children);
5379 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5381 memcpy (p, &dir, sizeof (dir));
5382 p += sizeof (dir);
5384 /* Reserve space for entries */
5385 entries = p;
5386 p += sizeof (dir_entry) * res_id_entries;
5388 /* Write children */
5389 for (l = node->children; l; l = l->next) {
5390 ResTreeNode *child = (ResTreeNode*)l->data;
5392 if (child->win32_res) {
5393 guint32 size;
5395 child->offset = p - begin;
5397 /* IMAGE_RESOURCE_DATA_ENTRY */
5398 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5399 size = mono_array_length (child->win32_res->res_data);
5400 data_entry.rde_size = GUINT32_TO_LE (size);
5402 memcpy (p, &data_entry, sizeof (data_entry));
5403 p += sizeof (data_entry);
5405 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5406 p += size;
5407 } else {
5408 resource_tree_encode (child, begin, p, &p);
5412 /* IMAGE_RESOURCE_ENTRY */
5413 for (l = node->children; l; l = l->next) {
5414 ResTreeNode *child = (ResTreeNode*)l->data;
5416 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5417 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5419 memcpy (entries, &dir_entry, sizeof (dir_entry));
5420 entries += sizeof (dir_entry);
5423 *endbuf = p;
5426 static void
5427 resource_tree_free (ResTreeNode * node)
5429 GSList * list;
5430 for (list = node->children; list; list = list->next)
5431 resource_tree_free ((ResTreeNode*)list->data);
5432 g_slist_free(node->children);
5433 g_free (node);
5436 static void
5437 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5439 char *buf;
5440 char *p;
5441 guint32 size, i;
5442 MonoReflectionWin32Resource *win32_res;
5443 ResTreeNode *tree;
5445 if (!assemblyb->win32_resources)
5446 return;
5449 * Resources are stored in a three level tree inside the PE file.
5450 * - level one contains a node for each type of resource
5451 * - level two contains a node for each resource
5452 * - level three contains a node for each instance of a resource for a
5453 * specific language.
5456 tree = resource_tree_create (assemblyb->win32_resources);
5458 /* Estimate the size of the encoded tree */
5459 size = 0;
5460 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5461 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5462 size += mono_array_length (win32_res->res_data);
5464 /* Directory structure */
5465 size += mono_array_length (assemblyb->win32_resources) * 256;
5466 p = buf = g_malloc (size);
5468 resource_tree_encode (tree, p, p, &p);
5470 g_assert (p - buf <= size);
5472 assembly->win32_res = g_malloc (p - buf);
5473 assembly->win32_res_size = p - buf;
5474 memcpy (assembly->win32_res, buf, p - buf);
5476 g_free (buf);
5477 resource_tree_free (tree);
5480 static void
5481 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5483 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5484 int i;
5486 p += sizeof (MonoPEResourceDir);
5487 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5488 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5489 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5490 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5491 fixup_resource_directory (res_section, child, rva);
5492 } else {
5493 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5494 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5497 p += sizeof (MonoPEResourceDirEntry);
5501 static void
5502 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5504 guint32 dummy;
5505 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5506 g_error ("WriteFile returned %d\n", GetLastError ());
5510 * mono_image_create_pefile:
5511 * @mb: a module builder object
5513 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
5514 * assembly->pefile where it can be easily retrieved later in chunks.
5516 void
5517 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5519 MonoMSDOSHeader *msdos;
5520 MonoDotNetHeader *header;
5521 MonoSectionTable *section;
5522 MonoCLIHeader *cli_header;
5523 guint32 size, image_size, virtual_base, text_offset;
5524 guint32 header_start, section_start, file_offset, virtual_offset;
5525 MonoDynamicImage *assembly;
5526 MonoReflectionAssemblyBuilder *assemblyb;
5527 MonoDynamicStream pefile_stream = {0};
5528 MonoDynamicStream *pefile = &pefile_stream;
5529 int i, nsections;
5530 guint32 *rva, value;
5531 guchar *p;
5532 static const unsigned char msheader[] = {
5533 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5534 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5535 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5536 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5537 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5538 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5539 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5540 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5543 assemblyb = mb->assemblyb;
5545 mono_image_basic_init (assemblyb);
5546 assembly = mb->dynamic_image;
5548 assembly->pe_kind = assemblyb->pe_kind;
5549 assembly->machine = assemblyb->machine;
5550 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5551 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5553 mono_image_build_metadata (mb);
5555 if (mb->is_main && assemblyb->resources) {
5556 int len = mono_array_length (assemblyb->resources);
5557 for (i = 0; i < len; ++i)
5558 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5561 if (mb->resources) {
5562 int len = mono_array_length (mb->resources);
5563 for (i = 0; i < len; ++i)
5564 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5567 build_compressed_metadata (assembly);
5569 if (mb->is_main)
5570 assembly_add_win32_resources (assembly, assemblyb);
5572 nsections = calc_section_size (assembly);
5574 /* The DOS header and stub */
5575 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5576 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5578 /* the dotnet header */
5579 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5581 /* the section tables */
5582 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5584 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5585 virtual_offset = VIRT_ALIGN;
5586 image_size = 0;
5588 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5589 if (!assembly->sections [i].size)
5590 continue;
5591 /* align offsets */
5592 file_offset += FILE_ALIGN - 1;
5593 file_offset &= ~(FILE_ALIGN - 1);
5594 virtual_offset += VIRT_ALIGN - 1;
5595 virtual_offset &= ~(VIRT_ALIGN - 1);
5597 assembly->sections [i].offset = file_offset;
5598 assembly->sections [i].rva = virtual_offset;
5600 file_offset += assembly->sections [i].size;
5601 virtual_offset += assembly->sections [i].size;
5602 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5605 file_offset += FILE_ALIGN - 1;
5606 file_offset &= ~(FILE_ALIGN - 1);
5608 image_size += section_start + sizeof (MonoSectionTable) * nsections;
5610 /* back-patch info */
5611 msdos = (MonoMSDOSHeader*)pefile->data;
5612 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5614 header = (MonoDotNetHeader*)(pefile->data + header_start);
5615 header->pesig [0] = 'P';
5616 header->pesig [1] = 'E';
5618 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5619 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5620 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5621 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5622 if (assemblyb->pekind == 1) {
5623 /* it's a dll */
5624 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5625 } else {
5626 /* it's an exe */
5627 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5630 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5632 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5633 header->pe.pe_major = 6;
5634 header->pe.pe_minor = 0;
5635 size = assembly->sections [MONO_SECTION_TEXT].size;
5636 size += FILE_ALIGN - 1;
5637 size &= ~(FILE_ALIGN - 1);
5638 header->pe.pe_code_size = GUINT32_FROM_LE(size);
5639 size = assembly->sections [MONO_SECTION_RSRC].size;
5640 size += FILE_ALIGN - 1;
5641 size &= ~(FILE_ALIGN - 1);
5642 header->pe.pe_data_size = GUINT32_FROM_LE(size);
5643 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5644 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5645 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5646 /* pe_rva_entry_point always at the beginning of the text section */
5647 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5649 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5650 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5651 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5652 header->nt.pe_os_major = GUINT16_FROM_LE (4);
5653 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5654 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5655 size = section_start;
5656 size += FILE_ALIGN - 1;
5657 size &= ~(FILE_ALIGN - 1);
5658 header->nt.pe_header_size = GUINT32_FROM_LE (size);
5659 size = image_size;
5660 size += VIRT_ALIGN - 1;
5661 size &= ~(VIRT_ALIGN - 1);
5662 header->nt.pe_image_size = GUINT32_FROM_LE (size);
5665 // Translate the PEFileKind value to the value expected by the Windows loader
5668 short kind;
5671 // PEFileKinds.Dll == 1
5672 // PEFileKinds.ConsoleApplication == 2
5673 // PEFileKinds.WindowApplication == 3
5675 // need to get:
5676 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5677 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5679 if (assemblyb->pekind == 3)
5680 kind = 2;
5681 else
5682 kind = 3;
5684 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5686 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5687 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5688 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5689 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5690 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5691 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
5693 /* fill data directory entries */
5695 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
5696 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5698 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
5699 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
5701 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
5702 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
5703 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
5704 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5705 /* patch entrypoint name */
5706 if (assemblyb->pekind == 1)
5707 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
5708 else
5709 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
5710 /* patch imported function RVA name */
5711 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
5712 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
5714 /* the import table */
5715 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
5716 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
5717 /* patch imported dll RVA name and other entries in the dir */
5718 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
5719 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
5720 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
5721 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5722 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
5723 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
5725 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
5726 value = (assembly->text_rva + assembly->imp_names_offset);
5727 *p++ = (value) & 0xff;
5728 *p++ = (value >> 8) & (0xff);
5729 *p++ = (value >> 16) & (0xff);
5730 *p++ = (value >> 24) & (0xff);
5732 /* the CLI header info */
5733 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
5734 cli_header->ch_size = GUINT32_FROM_LE (72);
5735 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
5736 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
5737 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
5738 if (assemblyb->entry_point) {
5739 guint32 table_idx = 0;
5740 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
5741 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
5742 table_idx = methodb->table_idx;
5743 } else {
5744 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
5746 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
5747 } else {
5748 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
5750 /* The embedded managed resources */
5751 text_offset = assembly->text_rva + assembly->code.index;
5752 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
5753 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
5754 text_offset += assembly->resources.index;
5755 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
5756 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
5757 text_offset += assembly->meta_size;
5758 if (assembly->strong_name_size) {
5759 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
5760 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
5761 text_offset += assembly->strong_name_size;
5764 /* write the section tables and section content */
5765 section = (MonoSectionTable*)(pefile->data + section_start);
5766 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5767 static const char section_names [][7] = {
5768 ".text", ".rsrc", ".reloc"
5770 if (!assembly->sections [i].size)
5771 continue;
5772 strcpy (section->st_name, section_names [i]);
5773 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5774 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5775 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5776 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5777 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5778 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5779 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5780 section ++;
5783 checked_write_file (file, pefile->data, pefile->index);
5785 mono_dynamic_stream_reset (pefile);
5787 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5788 if (!assembly->sections [i].size)
5789 continue;
5791 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5792 g_error ("SetFilePointer returned %d\n", GetLastError ());
5794 switch (i) {
5795 case MONO_SECTION_TEXT:
5796 /* patch entry point */
5797 p = (guchar*)(assembly->code.data + 2);
5798 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5799 *p++ = (value) & 0xff;
5800 *p++ = (value >> 8) & 0xff;
5801 *p++ = (value >> 16) & 0xff;
5802 *p++ = (value >> 24) & 0xff;
5804 checked_write_file (file, assembly->code.data, assembly->code.index);
5805 checked_write_file (file, assembly->resources.data, assembly->resources.index);
5806 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5807 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5810 g_free (assembly->image.raw_metadata);
5811 break;
5812 case MONO_SECTION_RELOC: {
5813 struct {
5814 guint32 page_rva;
5815 guint32 block_size;
5816 guint16 type_and_offset;
5817 guint16 term;
5818 } reloc;
5820 g_assert (sizeof (reloc) == 12);
5822 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5823 reloc.block_size = GUINT32_FROM_LE (12);
5826 * the entrypoint is always at the start of the text section
5827 * 3 is IMAGE_REL_BASED_HIGHLOW
5828 * 2 is patch_size_rva - text_rva
5830 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5831 reloc.term = 0;
5833 checked_write_file (file, &reloc, sizeof (reloc));
5835 break;
5837 case MONO_SECTION_RSRC:
5838 if (assembly->win32_res) {
5840 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5841 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5842 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5844 break;
5845 default:
5846 g_assert_not_reached ();
5850 /* check that the file is properly padded */
5851 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5852 g_error ("SetFilePointer returned %d\n", GetLastError ());
5853 if (! SetEndOfFile (file))
5854 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5856 mono_dynamic_stream_reset (&assembly->code);
5857 mono_dynamic_stream_reset (&assembly->us);
5858 mono_dynamic_stream_reset (&assembly->blob);
5859 mono_dynamic_stream_reset (&assembly->guid);
5860 mono_dynamic_stream_reset (&assembly->sheap);
5862 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5863 g_hash_table_destroy (assembly->blob_cache);
5864 assembly->blob_cache = NULL;
5867 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5869 void
5870 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5872 g_assert_not_reached ();
5875 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5877 #ifndef DISABLE_REFLECTION_EMIT
5879 MonoReflectionModule *
5880 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5882 char *name;
5883 MonoImage *image;
5884 MonoImageOpenStatus status;
5885 MonoDynamicAssembly *assembly;
5886 guint32 module_count;
5887 MonoImage **new_modules;
5888 gboolean *new_modules_loaded;
5890 name = mono_string_to_utf8 (fileName);
5892 image = mono_image_open (name, &status);
5893 if (!image) {
5894 MonoException *exc;
5895 if (status == MONO_IMAGE_ERROR_ERRNO)
5896 exc = mono_get_exception_file_not_found (fileName);
5897 else
5898 exc = mono_get_exception_bad_image_format (name);
5899 g_free (name);
5900 mono_raise_exception (exc);
5903 g_free (name);
5905 assembly = ab->dynamic_assembly;
5906 image->assembly = (MonoAssembly*)assembly;
5908 module_count = image->assembly->image->module_count;
5909 new_modules = g_new0 (MonoImage *, module_count + 1);
5910 new_modules_loaded = g_new0 (gboolean, module_count + 1);
5912 if (image->assembly->image->modules)
5913 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5914 if (image->assembly->image->modules_loaded)
5915 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
5916 new_modules [module_count] = image;
5917 new_modules_loaded [module_count] = TRUE;
5918 mono_image_addref (image);
5920 g_free (image->assembly->image->modules);
5921 image->assembly->image->modules = new_modules;
5922 image->assembly->image->modules_loaded = new_modules_loaded;
5923 image->assembly->image->module_count ++;
5925 mono_assembly_load_references (image, &status);
5926 if (status) {
5927 mono_image_close (image);
5928 mono_raise_exception (mono_get_exception_file_not_found (fileName));
5931 return mono_module_get_object (mono_domain_get (), image);
5934 #endif /* DISABLE_REFLECTION_EMIT */
5937 * We need to return always the same object for MethodInfo, FieldInfo etc..
5938 * but we need to consider the reflected type.
5939 * type uses a different hash, since it uses custom hash/equal functions.
5942 typedef struct {
5943 gpointer item;
5944 MonoClass *refclass;
5945 } ReflectedEntry;
5947 static gboolean
5948 reflected_equal (gconstpointer a, gconstpointer b) {
5949 const ReflectedEntry *ea = a;
5950 const ReflectedEntry *eb = b;
5952 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
5955 static guint
5956 reflected_hash (gconstpointer a) {
5957 const ReflectedEntry *ea = a;
5958 return mono_aligned_addr_hash (ea->item);
5961 #define CHECK_OBJECT(t,p,k) \
5962 do { \
5963 t _obj; \
5964 ReflectedEntry e; \
5965 e.item = (p); \
5966 e.refclass = (k); \
5967 mono_domain_lock (domain); \
5968 if (!domain->refobject_hash) \
5969 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5970 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
5971 mono_domain_unlock (domain); \
5972 return _obj; \
5974 mono_domain_unlock (domain); \
5975 } while (0)
5977 #ifdef HAVE_BOEHM_GC
5978 /* ReflectedEntry doesn't need to be GC tracked */
5979 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
5980 #define FREE_REFENTRY(entry) g_free ((entry))
5981 #define REFENTRY_REQUIRES_CLEANUP
5982 #else
5983 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5984 /* FIXME: */
5985 #define FREE_REFENTRY(entry)
5986 #endif
5988 #define CACHE_OBJECT(t,p,o,k) \
5989 do { \
5990 t _obj; \
5991 ReflectedEntry pe; \
5992 pe.item = (p); \
5993 pe.refclass = (k); \
5994 mono_domain_lock (domain); \
5995 if (!domain->refobject_hash) \
5996 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5997 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
5998 if (!_obj) { \
5999 ReflectedEntry *e = ALLOC_REFENTRY; \
6000 e->item = (p); \
6001 e->refclass = (k); \
6002 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
6003 _obj = o; \
6005 mono_domain_unlock (domain); \
6006 return _obj; \
6007 } while (0)
6009 static void
6010 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6012 mono_domain_lock (domain);
6013 if (domain->refobject_hash) {
6014 ReflectedEntry pe;
6015 gpointer orig_pe, orig_value;
6017 pe.item = o;
6018 pe.refclass = klass;
6019 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6020 mono_g_hash_table_remove (domain->refobject_hash, &pe);
6021 FREE_REFENTRY (orig_pe);
6024 mono_domain_unlock (domain);
6027 #ifdef REFENTRY_REQUIRES_CLEANUP
6028 static void
6029 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6031 FREE_REFENTRY (key);
6033 #endif
6035 void
6036 mono_reflection_cleanup_domain (MonoDomain *domain)
6038 if (domain->refobject_hash) {
6039 /*let's avoid scanning the whole hashtable if not needed*/
6040 #ifdef REFENTRY_REQUIRES_CLEANUP
6041 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6042 #endif
6043 mono_g_hash_table_destroy (domain->refobject_hash);
6044 domain->refobject_hash = NULL;
6048 #ifndef DISABLE_REFLECTION_EMIT
6049 static gpointer
6050 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6052 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6055 static gpointer
6056 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6058 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6061 void
6062 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6064 MonoDynamicImage *image = moduleb->dynamic_image;
6065 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6066 if (!image) {
6067 MonoError error;
6068 int module_count;
6069 MonoImage **new_modules;
6070 MonoImage *ass;
6071 char *name, *fqname;
6073 * FIXME: we already created an image in mono_image_basic_init (), but
6074 * we don't know which module it belongs to, since that is only
6075 * determined at assembly save time.
6077 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6078 name = mono_string_to_utf8 (ab->name);
6079 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6080 if (!mono_error_ok (&error)) {
6081 g_free (name);
6082 mono_error_raise_exception (&error);
6084 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6086 moduleb->module.image = &image->image;
6087 moduleb->dynamic_image = image;
6088 register_module (mono_object_domain (moduleb), moduleb, image);
6090 /* register the module with the assembly */
6091 ass = ab->dynamic_assembly->assembly.image;
6092 module_count = ass->module_count;
6093 new_modules = g_new0 (MonoImage *, module_count + 1);
6095 if (ass->modules)
6096 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6097 new_modules [module_count] = &image->image;
6098 mono_image_addref (&image->image);
6100 g_free (ass->modules);
6101 ass->modules = new_modules;
6102 ass->module_count ++;
6106 void
6107 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6109 MonoDynamicImage *image = moduleb->dynamic_image;
6111 g_assert (type->type);
6112 image->wrappers_type = mono_class_from_mono_type (type->type);
6115 #endif
6118 * mono_assembly_get_object:
6119 * @domain: an app domain
6120 * @assembly: an assembly
6122 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6124 MonoReflectionAssembly*
6125 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6127 static MonoClass *assembly_type;
6128 MonoReflectionAssembly *res;
6130 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6131 if (!assembly_type) {
6132 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoAssembly");
6133 if (class == NULL)
6134 class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Assembly");
6135 g_assert (class);
6136 assembly_type = class;
6138 res = (MonoReflectionAssembly *)mono_object_new (domain, assembly_type);
6139 res->assembly = assembly;
6141 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6146 MonoReflectionModule*
6147 mono_module_get_object (MonoDomain *domain, MonoImage *image)
6149 static MonoClass *module_type;
6150 MonoReflectionModule *res;
6151 char* basename;
6153 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6154 if (!module_type) {
6155 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6156 if (class == NULL)
6157 class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6158 g_assert (class);
6159 module_type = class;
6161 res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6163 res->image = image;
6164 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6166 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6167 basename = g_path_get_basename (image->name);
6168 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6169 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6171 g_free (basename);
6173 if (image->assembly->image == image) {
6174 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6175 } else {
6176 int i;
6177 res->token = 0;
6178 if (image->assembly->image->modules) {
6179 for (i = 0; i < image->assembly->image->module_count; i++) {
6180 if (image->assembly->image->modules [i] == image)
6181 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6183 g_assert (res->token);
6187 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6190 MonoReflectionModule*
6191 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6193 static MonoClass *module_type;
6194 MonoReflectionModule *res;
6195 MonoTableInfo *table;
6196 guint32 cols [MONO_FILE_SIZE];
6197 const char *name;
6198 guint32 i, name_idx;
6199 const char *val;
6201 if (!module_type) {
6202 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6203 if (class == NULL)
6204 class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6205 g_assert (class);
6206 module_type = class;
6208 res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6210 table = &image->tables [MONO_TABLE_FILE];
6211 g_assert (table_index < table->rows);
6212 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6214 res->image = NULL;
6215 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6216 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6218 /* Check whenever the row has a corresponding row in the moduleref table */
6219 table = &image->tables [MONO_TABLE_MODULEREF];
6220 for (i = 0; i < table->rows; ++i) {
6221 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6222 val = mono_metadata_string_heap (image, name_idx);
6223 if (strcmp (val, name) == 0)
6224 res->image = image->modules [i];
6227 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6228 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6229 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6230 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6231 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6233 return res;
6236 static gboolean
6237 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
6239 if ((t1->type != t2->type) ||
6240 (t1->byref != t2->byref))
6241 return FALSE;
6243 switch (t1->type) {
6244 case MONO_TYPE_VOID:
6245 case MONO_TYPE_BOOLEAN:
6246 case MONO_TYPE_CHAR:
6247 case MONO_TYPE_I1:
6248 case MONO_TYPE_U1:
6249 case MONO_TYPE_I2:
6250 case MONO_TYPE_U2:
6251 case MONO_TYPE_I4:
6252 case MONO_TYPE_U4:
6253 case MONO_TYPE_I8:
6254 case MONO_TYPE_U8:
6255 case MONO_TYPE_R4:
6256 case MONO_TYPE_R8:
6257 case MONO_TYPE_STRING:
6258 case MONO_TYPE_I:
6259 case MONO_TYPE_U:
6260 case MONO_TYPE_OBJECT:
6261 case MONO_TYPE_TYPEDBYREF:
6262 return TRUE;
6263 case MONO_TYPE_VALUETYPE:
6264 case MONO_TYPE_CLASS:
6265 case MONO_TYPE_SZARRAY:
6266 return t1->data.klass == t2->data.klass;
6267 case MONO_TYPE_PTR:
6268 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
6269 case MONO_TYPE_ARRAY:
6270 if (t1->data.array->rank != t2->data.array->rank)
6271 return FALSE;
6272 return t1->data.array->eklass == t2->data.array->eklass;
6273 case MONO_TYPE_GENERICINST: {
6274 int i;
6275 MonoGenericInst *i1 = t1->data.generic_class->context.class_inst;
6276 MonoGenericInst *i2 = t2->data.generic_class->context.class_inst;
6277 if (i1->type_argc != i2->type_argc)
6278 return FALSE;
6279 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
6280 &t2->data.generic_class->container_class->byval_arg))
6281 return FALSE;
6282 /* FIXME: we should probably just compare the instance pointers directly. */
6283 for (i = 0; i < i1->type_argc; ++i) {
6284 if (!mono_metadata_type_equal (i1->type_argv [i], i2->type_argv [i]))
6285 return FALSE;
6287 return TRUE;
6289 case MONO_TYPE_VAR:
6290 case MONO_TYPE_MVAR:
6291 return t1->data.generic_param == t2->data.generic_param;
6292 default:
6293 g_error ("implement type compare for %0x!", t1->type);
6294 return FALSE;
6297 return FALSE;
6300 static guint
6301 mymono_metadata_type_hash (MonoType *t1)
6303 guint hash;
6305 hash = t1->type;
6307 hash |= t1->byref << 6; /* do not collide with t1->type values */
6308 switch (t1->type) {
6309 case MONO_TYPE_VALUETYPE:
6310 case MONO_TYPE_CLASS:
6311 case MONO_TYPE_SZARRAY:
6312 /* check if the distribution is good enough */
6313 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
6314 case MONO_TYPE_PTR:
6315 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
6316 case MONO_TYPE_GENERICINST: {
6317 int i;
6318 MonoGenericInst *inst = t1->data.generic_class->context.class_inst;
6319 hash += g_str_hash (t1->data.generic_class->container_class->name);
6320 hash *= 13;
6321 for (i = 0; i < inst->type_argc; ++i) {
6322 hash += mymono_metadata_type_hash (inst->type_argv [i]);
6323 hash *= 13;
6325 return hash;
6328 return hash;
6331 static gboolean
6332 verify_safe_for_managed_space (MonoType *type)
6334 switch (type->type) {
6335 #ifdef DEBUG_HARDER
6336 case MONO_TYPE_ARRAY:
6337 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6338 case MONO_TYPE_PTR:
6339 return verify_safe_for_managed_space (type->data.type);
6340 case MONO_TYPE_SZARRAY:
6341 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6342 case MONO_TYPE_GENERICINST: {
6343 MonoGenericInst *inst = type->data.generic_class->inst;
6344 int i;
6345 if (!inst->is_open)
6346 break;
6347 for (i = 0; i < inst->type_argc; ++i)
6348 if (!verify_safe_for_managed_space (inst->type_argv [i]))
6349 return FALSE;
6350 break;
6352 #endif
6353 case MONO_TYPE_VAR:
6354 case MONO_TYPE_MVAR:
6355 return TRUE;
6357 return TRUE;
6360 static MonoType*
6361 mono_type_normalize (MonoType *type)
6363 int i;
6364 MonoGenericClass *gclass;
6365 MonoGenericInst *ginst;
6366 MonoClass *gtd;
6367 MonoGenericContainer *gcontainer;
6368 MonoType **argv = NULL;
6369 gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
6371 if (type->type != MONO_TYPE_GENERICINST)
6372 return type;
6374 gclass = type->data.generic_class;
6375 ginst = gclass->context.class_inst;
6376 if (!ginst->is_open)
6377 return type;
6379 gtd = gclass->container_class;
6380 gcontainer = gtd->generic_container;
6381 argv = g_newa (MonoType*, ginst->type_argc);
6383 for (i = 0; i < ginst->type_argc; ++i) {
6384 MonoType *t = ginst->type_argv [i], *norm;
6385 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
6386 is_denorm_gtd = FALSE;
6387 norm = mono_type_normalize (t);
6388 argv [i] = norm;
6389 if (norm != t)
6390 requires_rebind = TRUE;
6393 if (is_denorm_gtd)
6394 return type->byref == gtd->byval_arg.byref ? &gtd->byval_arg : &gtd->this_arg;
6396 if (requires_rebind) {
6397 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
6398 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
6401 return type;
6404 * mono_type_get_object:
6405 * @domain: an app domain
6406 * @type: a type
6408 * Return an System.MonoType object representing the type @type.
6410 MonoReflectionType*
6411 mono_type_get_object (MonoDomain *domain, MonoType *type)
6413 MonoType *norm_type;
6414 MonoReflectionType *res;
6415 MonoClass *klass = mono_class_from_mono_type (type);
6417 /*we must avoid using @type as it might have come
6418 * from a mono_metadata_type_dup and the caller
6419 * expects that is can be freed.
6420 * Using the right type from
6422 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6424 /* void is very common */
6425 if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6426 return (MonoReflectionType*)domain->typeof_void;
6429 * If the vtable of the given class was already created, we can use
6430 * the MonoType from there and avoid all locking and hash table lookups.
6432 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6433 * that the resulting object is different.
6435 if (type == &klass->byval_arg && !klass->image->dynamic) {
6436 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6437 if (vtable && vtable->type)
6438 return vtable->type;
6441 mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6442 mono_domain_lock (domain);
6443 if (!domain->type_hash)
6444 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash,
6445 (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
6446 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
6447 mono_domain_unlock (domain);
6448 mono_loader_unlock ();
6449 return res;
6452 /*Types must be normalized so a generic instance of the GTD get's the same inner type.
6453 * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
6454 * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
6455 * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
6456 * artifact of how generics are encoded and should be transparent to managed code so we
6457 * need to weed out this diference when retrieving managed System.Type objects.
6459 norm_type = mono_type_normalize (type);
6460 if (norm_type != type) {
6461 res = mono_type_get_object (domain, norm_type);
6462 mono_g_hash_table_insert (domain->type_hash, type, res);
6463 mono_domain_unlock (domain);
6464 mono_loader_unlock ();
6465 return res;
6468 /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
6469 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
6470 g_assert (0);
6472 if (!verify_safe_for_managed_space (type)) {
6473 mono_domain_unlock (domain);
6474 mono_loader_unlock ();
6475 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6478 if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
6479 gboolean is_type_done = TRUE;
6480 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
6481 * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
6482 * We can't simply close the types as this will interfere with other parts of the generics machinery.
6484 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
6485 MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
6487 if (gparam->owner && gparam->owner->is_method) {
6488 MonoMethod *method = gparam->owner->owner.method;
6489 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
6490 is_type_done = FALSE;
6491 } else if (gparam->owner && !gparam->owner->is_method) {
6492 MonoClass *klass = gparam->owner->owner.klass;
6493 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
6494 is_type_done = FALSE;
6498 /* g_assert_not_reached (); */
6499 /* should this be considered an error condition? */
6500 if (is_type_done && !type->byref) {
6501 mono_domain_unlock (domain);
6502 mono_loader_unlock ();
6503 return mono_class_get_ref_info (klass);
6506 #ifdef HAVE_SGEN_GC
6507 res = (MonoReflectionType *)mono_gc_alloc_pinned_obj (mono_class_vtable (domain, mono_defaults.monotype_class), mono_class_instance_size (mono_defaults.monotype_class));
6508 #else
6509 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
6510 #endif
6511 res->type = type;
6512 mono_g_hash_table_insert (domain->type_hash, type, res);
6514 if (type->type == MONO_TYPE_VOID)
6515 domain->typeof_void = (MonoObject*)res;
6517 mono_domain_unlock (domain);
6518 mono_loader_unlock ();
6519 return res;
6523 * mono_method_get_object:
6524 * @domain: an app domain
6525 * @method: a method
6526 * @refclass: the reflected type (can be NULL)
6528 * Return an System.Reflection.MonoMethod object representing the method @method.
6530 MonoReflectionMethod*
6531 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6534 * We use the same C representation for methods and constructors, but the type
6535 * name in C# is different.
6537 static MonoClass *System_Reflection_MonoMethod = NULL;
6538 static MonoClass *System_Reflection_MonoCMethod = NULL;
6539 static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6540 static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6541 MonoClass *klass;
6542 MonoReflectionMethod *ret;
6544 if (method->is_inflated) {
6545 MonoReflectionGenericMethod *gret;
6547 refclass = method->klass;
6548 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6549 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6550 if (!System_Reflection_MonoGenericCMethod)
6551 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6552 klass = System_Reflection_MonoGenericCMethod;
6553 } else {
6554 if (!System_Reflection_MonoGenericMethod)
6555 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6556 klass = System_Reflection_MonoGenericMethod;
6558 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6559 gret->method.method = method;
6560 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6561 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6562 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6565 if (!refclass)
6566 refclass = method->klass;
6568 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6569 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6570 if (!System_Reflection_MonoCMethod)
6571 System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6572 klass = System_Reflection_MonoCMethod;
6574 else {
6575 if (!System_Reflection_MonoMethod)
6576 System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6577 klass = System_Reflection_MonoMethod;
6579 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6580 ret->method = method;
6581 MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6582 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6586 * mono_method_clear_object:
6588 * Clear the cached reflection objects for the dynamic method METHOD.
6590 void
6591 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
6593 MonoClass *klass;
6594 g_assert (method->dynamic);
6596 klass = method->klass;
6597 while (klass) {
6598 clear_cached_object (domain, method, klass);
6599 klass = klass->parent;
6601 /* Added by mono_param_get_objects () */
6602 clear_cached_object (domain, &(method->signature), NULL);
6603 klass = method->klass;
6604 while (klass) {
6605 clear_cached_object (domain, &(method->signature), klass);
6606 klass = klass->parent;
6611 * mono_field_get_object:
6612 * @domain: an app domain
6613 * @klass: a type
6614 * @field: a field
6616 * Return an System.Reflection.MonoField object representing the field @field
6617 * in class @klass.
6619 MonoReflectionField*
6620 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6622 MonoReflectionField *res;
6623 static MonoClass *monofield_klass;
6625 CHECK_OBJECT (MonoReflectionField *, field, klass);
6626 if (!monofield_klass)
6627 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6628 res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6629 res->klass = klass;
6630 res->field = field;
6631 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6632 if (is_field_on_inst (field))
6633 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6634 else
6635 res->attrs = field->type->attrs;
6636 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6637 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6641 * mono_property_get_object:
6642 * @domain: an app domain
6643 * @klass: a type
6644 * @property: a property
6646 * Return an System.Reflection.MonoProperty object representing the property @property
6647 * in class @klass.
6649 MonoReflectionProperty*
6650 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6652 MonoReflectionProperty *res;
6653 static MonoClass *monoproperty_klass;
6655 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6656 if (!monoproperty_klass)
6657 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6658 res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6659 res->klass = klass;
6660 res->property = property;
6661 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6665 * mono_event_get_object:
6666 * @domain: an app domain
6667 * @klass: a type
6668 * @event: a event
6670 * Return an System.Reflection.MonoEvent object representing the event @event
6671 * in class @klass.
6673 MonoReflectionEvent*
6674 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6676 MonoReflectionEvent *res;
6677 MonoReflectionMonoEvent *mono_event;
6678 static MonoClass *monoevent_klass;
6680 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6681 if (!monoevent_klass)
6682 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6683 mono_event = (MonoReflectionMonoEvent *)mono_object_new (domain, monoevent_klass);
6684 mono_event->klass = klass;
6685 mono_event->event = event;
6686 res = (MonoReflectionEvent*)mono_event;
6687 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6691 * mono_get_reflection_missing_object:
6692 * @domain: Domain where the object lives
6694 * Returns the System.Reflection.Missing.Value singleton object
6695 * (of type System.Reflection.Missing).
6697 * Used as the value for ParameterInfo.DefaultValue when Optional
6698 * is present
6700 static MonoObject *
6701 mono_get_reflection_missing_object (MonoDomain *domain)
6703 MonoObject *obj;
6704 static MonoClassField *missing_value_field = NULL;
6706 if (!missing_value_field) {
6707 MonoClass *missing_klass;
6708 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6709 mono_class_init (missing_klass);
6710 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6711 g_assert (missing_value_field);
6713 obj = mono_field_get_value_object (domain, missing_value_field, NULL);
6714 g_assert (obj);
6715 return obj;
6718 static MonoObject*
6719 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6721 if (!*dbnull)
6722 *dbnull = mono_get_dbnull_object (domain);
6723 return *dbnull;
6726 static MonoObject*
6727 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6729 if (!*reflection_missing)
6730 *reflection_missing = mono_get_reflection_missing_object (domain);
6731 return *reflection_missing;
6735 * mono_param_get_objects:
6736 * @domain: an app domain
6737 * @method: a method
6739 * Return an System.Reflection.ParameterInfo array object representing the parameters
6740 * in the method @method.
6742 MonoArray*
6743 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6745 static MonoClass *System_Reflection_ParameterInfo;
6746 static MonoClass *System_Reflection_ParameterInfo_array;
6747 MonoArray *res = NULL;
6748 MonoReflectionMethod *member = NULL;
6749 MonoReflectionParameter *param = NULL;
6750 char **names, **blobs = NULL;
6751 guint32 *types = NULL;
6752 MonoType *type = NULL;
6753 MonoObject *dbnull = NULL;
6754 MonoObject *missing = NULL;
6755 MonoMarshalSpec **mspecs;
6756 MonoMethodSignature *sig;
6757 MonoVTable *pinfo_vtable;
6758 int i;
6760 if (!System_Reflection_ParameterInfo_array) {
6761 MonoClass *klass;
6763 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6764 mono_memory_barrier ();
6765 System_Reflection_ParameterInfo = klass;
6767 klass = mono_array_class_get (klass, 1);
6768 mono_memory_barrier ();
6769 System_Reflection_ParameterInfo_array = klass;
6772 if (!mono_method_signature (method)->param_count)
6773 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6775 /* Note: the cache is based on the address of the signature into the method
6776 * since we already cache MethodInfos with the method as keys.
6778 CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
6780 sig = mono_method_signature (method);
6781 member = mono_method_get_object (domain, method, refclass);
6782 names = g_new (char *, sig->param_count);
6783 mono_method_get_param_names (method, (const char **) names);
6785 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
6786 mono_method_get_marshal_info (method, mspecs);
6788 res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
6789 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
6790 for (i = 0; i < sig->param_count; ++i) {
6791 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
6792 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
6793 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
6794 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
6795 param->PositionImpl = i;
6796 param->AttrsImpl = sig->params [i]->attrs;
6798 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
6799 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6800 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6801 else
6802 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6803 } else {
6805 if (!blobs) {
6806 blobs = g_new0 (char *, sig->param_count);
6807 types = g_new0 (guint32, sig->param_count);
6808 get_default_param_value_blobs (method, blobs, types);
6811 /* Build MonoType for the type from the Constant Table */
6812 if (!type)
6813 type = g_new0 (MonoType, 1);
6814 type->type = types [i];
6815 type->data.klass = NULL;
6816 if (types [i] == MONO_TYPE_CLASS)
6817 type->data.klass = mono_defaults.object_class;
6818 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
6819 /* For enums, types [i] contains the base type */
6821 type->type = MONO_TYPE_VALUETYPE;
6822 type->data.klass = mono_class_from_mono_type (sig->params [i]);
6823 } else
6824 type->data.klass = mono_class_from_mono_type (type);
6826 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
6828 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6829 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
6830 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6831 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6832 else
6833 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6838 if (mspecs [i + 1])
6839 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
6841 mono_array_setref (res, i, param);
6843 g_free (names);
6844 g_free (blobs);
6845 g_free (types);
6846 g_free (type);
6848 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
6849 if (mspecs [i])
6850 mono_metadata_free_marshal_spec (mspecs [i]);
6851 g_free (mspecs);
6853 CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
6856 MonoArray*
6857 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
6859 return mono_param_get_objects_internal (domain, method, NULL);
6863 * mono_method_body_get_object:
6864 * @domain: an app domain
6865 * @method: a method
6867 * Return an System.Reflection.MethodBody object representing the method @method.
6869 MonoReflectionMethodBody*
6870 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
6872 static MonoClass *System_Reflection_MethodBody = NULL;
6873 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
6874 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
6875 MonoReflectionMethodBody *ret;
6876 MonoMethodHeader *header;
6877 guint32 method_rva, local_var_sig_token;
6878 char *ptr;
6879 unsigned char format, flags;
6880 int i;
6882 if (!System_Reflection_MethodBody)
6883 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
6884 if (!System_Reflection_LocalVariableInfo)
6885 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
6886 if (!System_Reflection_ExceptionHandlingClause)
6887 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
6889 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
6891 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6892 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
6893 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
6894 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
6895 return NULL;
6896 header = mono_method_get_header (method);
6898 /* Obtain local vars signature token */
6899 method_rva = mono_metadata_decode_row_col (&method->klass->image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
6900 ptr = mono_image_rva_map (method->klass->image, method_rva);
6901 flags = *(const unsigned char *) ptr;
6902 format = flags & METHOD_HEADER_FORMAT_MASK;
6903 switch (format){
6904 case METHOD_HEADER_TINY_FORMAT:
6905 local_var_sig_token = 0;
6906 break;
6907 case METHOD_HEADER_FAT_FORMAT:
6908 ptr += 2;
6909 ptr += 2;
6910 ptr += 4;
6911 local_var_sig_token = read32 (ptr);
6912 break;
6913 default:
6914 g_assert_not_reached ();
6917 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
6919 ret->init_locals = header->init_locals;
6920 ret->max_stack = header->max_stack;
6921 ret->local_var_sig_token = local_var_sig_token;
6922 MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
6923 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
6925 /* Locals */
6926 MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
6927 for (i = 0; i < header->num_locals; ++i) {
6928 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
6929 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
6930 info->is_pinned = header->locals [i]->pinned;
6931 info->local_index = i;
6932 mono_array_setref (ret->locals, i, info);
6935 /* Exceptions */
6936 MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
6937 for (i = 0; i < header->num_clauses; ++i) {
6938 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
6939 MonoExceptionClause *clause = &header->clauses [i];
6941 info->flags = clause->flags;
6942 info->try_offset = clause->try_offset;
6943 info->try_length = clause->try_len;
6944 info->handler_offset = clause->handler_offset;
6945 info->handler_length = clause->handler_len;
6946 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
6947 info->filter_offset = clause->data.filter_offset;
6948 else if (clause->data.catch_class)
6949 MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
6951 mono_array_setref (ret->clauses, i, info);
6954 mono_metadata_free_mh (header);
6955 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
6956 return ret;
6960 * mono_get_dbnull_object:
6961 * @domain: Domain where the object lives
6963 * Returns the System.DBNull.Value singleton object
6965 * Used as the value for ParameterInfo.DefaultValue
6967 MonoObject *
6968 mono_get_dbnull_object (MonoDomain *domain)
6970 MonoObject *obj;
6971 static MonoClassField *dbnull_value_field = NULL;
6973 if (!dbnull_value_field) {
6974 MonoClass *dbnull_klass;
6975 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
6976 mono_class_init (dbnull_klass);
6977 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
6978 g_assert (dbnull_value_field);
6980 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
6981 g_assert (obj);
6982 return obj;
6985 static void
6986 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
6988 guint32 param_index, i, lastp, crow = 0;
6989 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
6990 gint32 idx;
6992 MonoClass *klass = method->klass;
6993 MonoImage *image = klass->image;
6994 MonoMethodSignature *methodsig = mono_method_signature (method);
6996 MonoTableInfo *constt;
6997 MonoTableInfo *methodt;
6998 MonoTableInfo *paramt;
7000 if (!methodsig->param_count)
7001 return;
7003 mono_class_init (klass);
7005 if (klass->image->dynamic) {
7006 MonoReflectionMethodAux *aux;
7007 if (method->is_inflated)
7008 method = ((MonoMethodInflated*)method)->declaring;
7009 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7010 if (aux && aux->param_defaults) {
7011 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7012 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7014 return;
7017 methodt = &klass->image->tables [MONO_TABLE_METHOD];
7018 paramt = &klass->image->tables [MONO_TABLE_PARAM];
7019 constt = &image->tables [MONO_TABLE_CONSTANT];
7021 idx = mono_method_get_index (method) - 1;
7022 g_assert (idx != -1);
7024 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7025 if (idx + 1 < methodt->rows)
7026 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7027 else
7028 lastp = paramt->rows + 1;
7030 for (i = param_index; i < lastp; ++i) {
7031 guint32 paramseq;
7033 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7034 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7036 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7037 continue;
7039 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7040 if (!crow) {
7041 continue;
7044 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7045 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7046 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7049 return;
7052 MonoObject *
7053 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7055 void *retval;
7056 MonoClass *klass;
7057 MonoObject *object;
7058 MonoType *basetype = type;
7060 if (!blob)
7061 return NULL;
7063 klass = mono_class_from_mono_type (type);
7064 if (klass->valuetype) {
7065 object = mono_object_new (domain, klass);
7066 retval = ((gchar *) object + sizeof (MonoObject));
7067 if (klass->enumtype)
7068 basetype = mono_class_enum_basetype (klass);
7069 } else {
7070 retval = &object;
7073 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
7074 return object;
7075 else
7076 return NULL;
7079 static int
7080 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7081 int found_sep;
7082 char *s;
7084 memset (assembly, 0, sizeof (MonoAssemblyName));
7085 assembly->name = p;
7086 assembly->culture = "";
7087 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7089 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
7090 p++;
7091 found_sep = 0;
7092 while (g_ascii_isspace (*p) || *p == ',') {
7093 *p++ = 0;
7094 found_sep = 1;
7095 continue;
7097 /* failed */
7098 if (!found_sep)
7099 return 1;
7100 while (*p) {
7101 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7102 p += 8;
7103 assembly->major = strtoul (p, &s, 10);
7104 if (s == p || *s != '.')
7105 return 1;
7106 p = ++s;
7107 assembly->minor = strtoul (p, &s, 10);
7108 if (s == p || *s != '.')
7109 return 1;
7110 p = ++s;
7111 assembly->build = strtoul (p, &s, 10);
7112 if (s == p || *s != '.')
7113 return 1;
7114 p = ++s;
7115 assembly->revision = strtoul (p, &s, 10);
7116 if (s == p)
7117 return 1;
7118 p = s;
7119 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7120 p += 8;
7121 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7122 assembly->culture = "";
7123 p += 7;
7124 } else {
7125 assembly->culture = p;
7126 while (*p && *p != ',') {
7127 p++;
7130 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7131 p += 15;
7132 if (strncmp (p, "null", 4) == 0) {
7133 p += 4;
7134 } else {
7135 int len;
7136 gchar *start = p;
7137 while (*p && *p != ',') {
7138 p++;
7140 len = (p - start + 1);
7141 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7142 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7143 g_strlcpy ((char*)assembly->public_key_token, start, len);
7145 } else {
7146 while (*p && *p != ',')
7147 p++;
7149 found_sep = 0;
7150 while (g_ascii_isspace (*p) || *p == ',') {
7151 *p++ = 0;
7152 found_sep = 1;
7153 continue;
7155 /* failed */
7156 if (!found_sep)
7157 return 1;
7160 return 0;
7164 * mono_reflection_parse_type:
7165 * @name: type name
7167 * Parse a type name as accepted by the GetType () method and output the info
7168 * extracted in the info structure.
7169 * the name param will be mangled, so, make a copy before passing it to this function.
7170 * The fields in info will be valid until the memory pointed to by name is valid.
7172 * See also mono_type_get_name () below.
7174 * Returns: 0 on parse error.
7176 static int
7177 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7178 MonoTypeNameParse *info)
7180 char *start, *p, *w, *temp, *last_point, *startn;
7181 int in_modifiers = 0;
7182 int isbyref = 0, rank, arity = 0, i;
7184 start = p = w = name;
7186 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7187 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7188 info->name = info->name_space = NULL;
7189 info->nested = NULL;
7190 info->modifiers = NULL;
7191 info->type_arguments = NULL;
7193 /* last_point separates the namespace from the name */
7194 last_point = NULL;
7195 /* Skips spaces */
7196 while (*p == ' ') p++, start++, w++, name++;
7198 while (*p) {
7199 switch (*p) {
7200 case '+':
7201 *p = 0; /* NULL terminate the name */
7202 startn = p + 1;
7203 info->nested = g_list_append (info->nested, startn);
7204 /* we have parsed the nesting namespace + name */
7205 if (info->name)
7206 break;
7207 if (last_point) {
7208 info->name_space = start;
7209 *last_point = 0;
7210 info->name = last_point + 1;
7211 } else {
7212 info->name_space = (char *)"";
7213 info->name = start;
7215 break;
7216 case '.':
7217 last_point = p;
7218 break;
7219 case '\\':
7220 ++p;
7221 break;
7222 case '&':
7223 case '*':
7224 case '[':
7225 case ',':
7226 case ']':
7227 in_modifiers = 1;
7228 break;
7229 case '`':
7230 ++p;
7231 i = strtol (p, &temp, 10);
7232 arity += i;
7233 if (p == temp)
7234 return 0;
7235 p = temp-1;
7236 break;
7237 default:
7238 break;
7240 if (in_modifiers)
7241 break;
7242 // *w++ = *p++;
7243 p++;
7246 if (!info->name) {
7247 if (last_point) {
7248 info->name_space = start;
7249 *last_point = 0;
7250 info->name = last_point + 1;
7251 } else {
7252 info->name_space = (char *)"";
7253 info->name = start;
7256 while (*p) {
7257 switch (*p) {
7258 case '&':
7259 if (isbyref) /* only one level allowed by the spec */
7260 return 0;
7261 isbyref = 1;
7262 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7263 *p++ = 0;
7264 break;
7265 case '*':
7266 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7267 *p++ = 0;
7268 break;
7269 case '[':
7270 if (arity != 0) {
7271 *p++ = 0;
7272 info->type_arguments = g_ptr_array_new ();
7273 for (i = 0; i < arity; i++) {
7274 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7275 gboolean fqname = FALSE;
7277 g_ptr_array_add (info->type_arguments, subinfo);
7279 if (*p == '[') {
7280 p++;
7281 fqname = TRUE;
7284 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7285 return 0;
7287 /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
7288 if (fqname && (*p != ']')) {
7289 char *aname;
7291 if (*p != ',')
7292 return 0;
7293 *p++ = 0;
7295 aname = p;
7296 while (*p && (*p != ']'))
7297 p++;
7299 if (*p != ']')
7300 return 0;
7302 *p++ = 0;
7303 while (*aname) {
7304 if (g_ascii_isspace (*aname)) {
7305 ++aname;
7306 continue;
7308 break;
7310 if (!*aname ||
7311 !assembly_name_to_aname (&subinfo->assembly, aname))
7312 return 0;
7313 } else if (fqname && (*p == ']')) {
7314 *p++ = 0;
7317 if (i + 1 < arity) {
7318 if (*p != ',')
7319 return 0;
7320 } else {
7321 if (*p != ']')
7322 return 0;
7324 *p++ = 0;
7327 arity = 0;
7328 break;
7330 rank = 1;
7331 *p++ = 0;
7332 while (*p) {
7333 if (*p == ']')
7334 break;
7335 if (*p == ',')
7336 rank++;
7337 else if (*p == '*') /* '*' means unknown lower bound */
7338 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7339 else
7340 return 0;
7341 ++p;
7343 if (*p++ != ']')
7344 return 0;
7345 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7346 break;
7347 case ']':
7348 if (is_recursed)
7349 goto end;
7350 return 0;
7351 case ',':
7352 if (is_recursed)
7353 goto end;
7354 *p++ = 0;
7355 while (*p) {
7356 if (g_ascii_isspace (*p)) {
7357 ++p;
7358 continue;
7360 break;
7362 if (!*p)
7363 return 0; /* missing assembly name */
7364 if (!assembly_name_to_aname (&info->assembly, p))
7365 return 0;
7366 break;
7367 default:
7368 return 0;
7370 if (info->assembly.name)
7371 break;
7373 // *w = 0; /* terminate class name */
7374 end:
7375 if (!info->name || !*info->name)
7376 return 0;
7377 if (endptr)
7378 *endptr = p;
7379 /* add other consistency checks */
7380 return 1;
7384 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7386 return _mono_reflection_parse_type (name, NULL, FALSE, info);
7389 static MonoType*
7390 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7392 gboolean type_resolve = FALSE;
7393 MonoType *type;
7394 MonoImage *rootimage = image;
7396 if (info->assembly.name) {
7397 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7398 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7400 * This could happen in the AOT compiler case when the search hook is not
7401 * installed.
7403 assembly = image->assembly;
7404 if (!assembly) {
7405 /* then we must load the assembly ourselve - see #60439 */
7406 assembly = mono_assembly_load (&info->assembly, NULL, NULL);
7407 if (!assembly)
7408 return NULL;
7410 image = assembly->image;
7411 } else if (!image) {
7412 image = mono_defaults.corlib;
7415 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7416 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7417 image = mono_defaults.corlib;
7418 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7421 return type;
7424 static MonoType*
7425 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7427 MonoClass *klass;
7428 GList *mod;
7429 int modval;
7430 gboolean bounded = FALSE;
7432 if (!image)
7433 image = mono_defaults.corlib;
7435 if (ignorecase)
7436 klass = mono_class_from_name_case (image, info->name_space, info->name);
7437 else
7438 klass = mono_class_from_name (image, info->name_space, info->name);
7439 if (!klass)
7440 return NULL;
7441 for (mod = info->nested; mod; mod = mod->next) {
7442 gpointer iter = NULL;
7443 MonoClass *parent;
7445 parent = klass;
7446 mono_class_init (parent);
7448 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7449 if (ignorecase) {
7450 if (mono_utf8_strcasecmp (klass->name, mod->data) == 0)
7451 break;
7452 } else {
7453 if (strcmp (klass->name, mod->data) == 0)
7454 break;
7457 if (!klass)
7458 break;
7460 if (!klass)
7461 return NULL;
7462 mono_class_init (klass);
7464 if (info->type_arguments) {
7465 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7466 MonoReflectionType *the_type;
7467 MonoType *instance;
7468 int i;
7470 for (i = 0; i < info->type_arguments->len; i++) {
7471 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7473 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7474 if (!type_args [i]) {
7475 g_free (type_args);
7476 return NULL;
7480 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7482 instance = mono_reflection_bind_generic_parameters (
7483 the_type, info->type_arguments->len, type_args);
7485 g_free (type_args);
7486 if (!instance)
7487 return NULL;
7489 klass = mono_class_from_mono_type (instance);
7492 for (mod = info->modifiers; mod; mod = mod->next) {
7493 modval = GPOINTER_TO_UINT (mod->data);
7494 if (!modval) { /* byref: must be last modifier */
7495 return &klass->this_arg;
7496 } else if (modval == -1) {
7497 klass = mono_ptr_class_get (&klass->byval_arg);
7498 } else if (modval == -2) {
7499 bounded = TRUE;
7500 } else { /* array rank */
7501 klass = mono_bounded_array_class_get (klass, modval, bounded);
7503 mono_class_init (klass);
7506 return &klass->byval_arg;
7510 * mono_reflection_get_type:
7511 * @image: a metadata context
7512 * @info: type description structure
7513 * @ignorecase: flag for case-insensitive string compares
7514 * @type_resolve: whenever type resolve was already tried
7516 * Build a MonoType from the type description in @info.
7520 MonoType*
7521 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7522 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7525 static MonoType*
7526 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7528 MonoReflectionAssemblyBuilder *abuilder;
7529 MonoType *type;
7530 int i;
7532 g_assert (assembly->dynamic);
7533 abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (((MonoDynamicAssembly*)assembly)->domain, assembly);
7535 /* Enumerate all modules */
7537 type = NULL;
7538 if (abuilder->modules) {
7539 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7540 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7541 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7542 if (type)
7543 break;
7547 if (!type && abuilder->loaded_modules) {
7548 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7549 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7550 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7551 if (type)
7552 break;
7556 return type;
7559 MonoType*
7560 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7562 MonoType *type;
7563 MonoReflectionAssembly *assembly;
7564 GString *fullName;
7565 GList *mod;
7567 if (image && image->dynamic)
7568 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7569 else
7570 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7571 if (type)
7572 return type;
7573 if (!mono_domain_has_type_resolve (mono_domain_get ()))
7574 return NULL;
7576 if (type_resolve) {
7577 if (*type_resolve)
7578 return NULL;
7579 else
7580 *type_resolve = TRUE;
7583 /* Reconstruct the type name */
7584 fullName = g_string_new ("");
7585 if (info->name_space && (info->name_space [0] != '\0'))
7586 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7587 else
7588 g_string_printf (fullName, "%s", info->name);
7589 for (mod = info->nested; mod; mod = mod->next)
7590 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7592 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7593 if (assembly) {
7594 if (assembly->assembly->dynamic)
7595 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7596 else
7597 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
7598 info, ignorecase);
7600 g_string_free (fullName, TRUE);
7601 return type;
7604 void
7605 mono_reflection_free_type_info (MonoTypeNameParse *info)
7607 g_list_free (info->modifiers);
7608 g_list_free (info->nested);
7610 if (info->type_arguments) {
7611 int i;
7613 for (i = 0; i < info->type_arguments->len; i++) {
7614 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7616 mono_reflection_free_type_info (subinfo);
7617 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7618 g_free (subinfo);
7621 g_ptr_array_free (info->type_arguments, TRUE);
7626 * mono_reflection_type_from_name:
7627 * @name: type name.
7628 * @image: a metadata context (can be NULL).
7630 * Retrieves a MonoType from its @name. If the name is not fully qualified,
7631 * it defaults to get the type from @image or, if @image is NULL or loading
7632 * from it fails, uses corlib.
7635 MonoType*
7636 mono_reflection_type_from_name (char *name, MonoImage *image)
7638 MonoType *type = NULL;
7639 MonoTypeNameParse info;
7640 char *tmp;
7642 /* Make a copy since parse_type modifies its argument */
7643 tmp = g_strdup (name);
7645 /*g_print ("requested type %s\n", str);*/
7646 if (mono_reflection_parse_type (tmp, &info)) {
7647 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7650 g_free (tmp);
7651 mono_reflection_free_type_info (&info);
7652 return type;
7656 * mono_reflection_get_token:
7658 * Return the metadata token of OBJ which should be an object
7659 * representing a metadata element.
7661 guint32
7662 mono_reflection_get_token (MonoObject *obj)
7664 MonoClass *klass;
7665 guint32 token = 0;
7667 klass = obj->vtable->klass;
7669 if (strcmp (klass->name, "MethodBuilder") == 0) {
7670 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7672 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7673 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7674 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7676 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7677 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7678 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7680 /* Call mono_image_create_token so the object gets added to the tokens hash table */
7681 token = mono_image_create_token (((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image, obj, FALSE, TRUE);
7682 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7683 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7684 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7685 } else if (strcmp (klass->name, "MonoType") == 0) {
7686 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
7687 MonoClass *mc = mono_class_from_mono_type (type);
7688 if (!mono_class_init (mc))
7689 mono_raise_exception (mono_class_get_exception_for_failure (mc));
7691 token = mc->type_token;
7692 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7693 strcmp (klass->name, "MonoMethod") == 0 ||
7694 strcmp (klass->name, "MonoGenericMethod") == 0 ||
7695 strcmp (klass->name, "MonoGenericCMethod") == 0) {
7696 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7697 if (m->method->is_inflated) {
7698 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7699 return inflated->declaring->token;
7700 } else {
7701 token = m->method->token;
7703 } else if (strcmp (klass->name, "MonoField") == 0) {
7704 MonoReflectionField *f = (MonoReflectionField*)obj;
7706 if (is_field_on_inst (f->field)) {
7707 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
7708 int field_index = f->field - dgclass->fields;
7709 MonoObject *obj;
7711 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
7712 obj = dgclass->field_objects [field_index];
7713 return mono_reflection_get_token (obj);
7715 token = mono_class_get_field_token (f->field);
7716 } else if (strcmp (klass->name, "MonoProperty") == 0) {
7717 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7719 token = mono_class_get_property_token (p->property);
7720 } else if (strcmp (klass->name, "MonoEvent") == 0) {
7721 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
7723 token = mono_class_get_event_token (p->event);
7724 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
7725 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7726 MonoClass *member_class = mono_object_class (p->MemberImpl);
7727 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
7729 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7730 } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
7731 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7733 token = m->token;
7734 } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
7735 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7736 } else {
7737 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7738 MonoException *ex = mono_get_exception_not_implemented (msg);
7739 g_free (msg);
7740 mono_raise_exception (ex);
7743 return token;
7746 static void*
7747 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
7749 int slen, type = t->type;
7750 MonoClass *tklass = t->data.klass;
7752 handle_enum:
7753 switch (type) {
7754 case MONO_TYPE_U1:
7755 case MONO_TYPE_I1:
7756 case MONO_TYPE_BOOLEAN: {
7757 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7758 *bval = *p;
7759 *end = p + 1;
7760 return bval;
7762 case MONO_TYPE_CHAR:
7763 case MONO_TYPE_U2:
7764 case MONO_TYPE_I2: {
7765 guint16 *val = g_malloc (sizeof (guint16));
7766 *val = read16 (p);
7767 *end = p + 2;
7768 return val;
7770 #if SIZEOF_VOID_P == 4
7771 case MONO_TYPE_U:
7772 case MONO_TYPE_I:
7773 #endif
7774 case MONO_TYPE_R4:
7775 case MONO_TYPE_U4:
7776 case MONO_TYPE_I4: {
7777 guint32 *val = g_malloc (sizeof (guint32));
7778 *val = read32 (p);
7779 *end = p + 4;
7780 return val;
7782 #if SIZEOF_VOID_P == 8
7783 case MONO_TYPE_U: /* error out instead? this should probably not happen */
7784 case MONO_TYPE_I:
7785 #endif
7786 case MONO_TYPE_U8:
7787 case MONO_TYPE_I8: {
7788 guint64 *val = g_malloc (sizeof (guint64));
7789 *val = read64 (p);
7790 *end = p + 8;
7791 return val;
7793 case MONO_TYPE_R8: {
7794 double *val = g_malloc (sizeof (double));
7795 readr8 (p, val);
7796 *end = p + 8;
7797 return val;
7799 case MONO_TYPE_VALUETYPE:
7800 if (t->data.klass->enumtype) {
7801 type = mono_class_enum_basetype (t->data.klass)->type;
7802 goto handle_enum;
7803 } else {
7804 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7806 break;
7807 case MONO_TYPE_STRING:
7808 if (*p == (char)0xFF) {
7809 *end = p + 1;
7810 return NULL;
7812 slen = mono_metadata_decode_value (p, &p);
7813 *end = p + slen;
7814 return mono_string_new_len (mono_domain_get (), p, slen);
7815 case MONO_TYPE_CLASS: {
7816 char *n;
7817 MonoType *t;
7818 if (*p == (char)0xFF) {
7819 *end = p + 1;
7820 return NULL;
7822 handle_type:
7823 slen = mono_metadata_decode_value (p, &p);
7824 n = g_memdup (p, slen + 1);
7825 n [slen] = 0;
7826 t = mono_reflection_type_from_name (n, image);
7827 if (!t)
7828 g_warning ("Cannot load type '%s'", n);
7829 g_free (n);
7830 *end = p + slen;
7831 if (t)
7832 return mono_type_get_object (mono_domain_get (), t);
7833 else
7834 return NULL;
7836 case MONO_TYPE_OBJECT: {
7837 char subt = *p++;
7838 MonoObject *obj;
7839 MonoClass *subc = NULL;
7840 void *val;
7842 if (subt == 0x50) {
7843 goto handle_type;
7844 } else if (subt == 0x0E) {
7845 type = MONO_TYPE_STRING;
7846 goto handle_enum;
7847 } else if (subt == 0x1D) {
7848 MonoType simple_type = {{0}};
7849 int etype = *p;
7850 p ++;
7852 if (etype == 0x51)
7853 /* See Partition II, Appendix B3 */
7854 etype = MONO_TYPE_OBJECT;
7855 type = MONO_TYPE_SZARRAY;
7856 simple_type.type = etype;
7857 tklass = mono_class_from_mono_type (&simple_type);
7858 goto handle_enum;
7859 } else if (subt == 0x55) {
7860 char *n;
7861 MonoType *t;
7862 slen = mono_metadata_decode_value (p, &p);
7863 n = g_memdup (p, slen + 1);
7864 n [slen] = 0;
7865 t = mono_reflection_type_from_name (n, image);
7866 if (!t)
7867 g_error ("Cannot load type '%s'", n);
7868 g_free (n);
7869 p += slen;
7870 subc = mono_class_from_mono_type (t);
7871 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
7872 MonoType simple_type = {{0}};
7873 simple_type.type = subt;
7874 subc = mono_class_from_mono_type (&simple_type);
7875 } else {
7876 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
7878 val = load_cattr_value (image, &subc->byval_arg, p, end);
7879 obj = mono_object_new (mono_domain_get (), subc);
7880 g_assert (!subc->has_references);
7881 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
7882 g_free (val);
7883 return obj;
7885 case MONO_TYPE_SZARRAY: {
7886 MonoArray *arr;
7887 guint32 i, alen, basetype;
7888 alen = read32 (p);
7889 p += 4;
7890 if (alen == 0xffffffff) {
7891 *end = p;
7892 return NULL;
7894 arr = mono_array_new (mono_domain_get(), tklass, alen);
7895 basetype = tklass->byval_arg.type;
7896 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
7897 basetype = mono_class_enum_basetype (tklass)->type;
7898 switch (basetype)
7900 case MONO_TYPE_U1:
7901 case MONO_TYPE_I1:
7902 case MONO_TYPE_BOOLEAN:
7903 for (i = 0; i < alen; i++) {
7904 MonoBoolean val = *p++;
7905 mono_array_set (arr, MonoBoolean, i, val);
7907 break;
7908 case MONO_TYPE_CHAR:
7909 case MONO_TYPE_U2:
7910 case MONO_TYPE_I2:
7911 for (i = 0; i < alen; i++) {
7912 guint16 val = read16 (p);
7913 mono_array_set (arr, guint16, i, val);
7914 p += 2;
7916 break;
7917 case MONO_TYPE_R4:
7918 case MONO_TYPE_U4:
7919 case MONO_TYPE_I4:
7920 for (i = 0; i < alen; i++) {
7921 guint32 val = read32 (p);
7922 mono_array_set (arr, guint32, i, val);
7923 p += 4;
7925 break;
7926 case MONO_TYPE_R8:
7927 for (i = 0; i < alen; i++) {
7928 double val;
7929 readr8 (p, &val);
7930 mono_array_set (arr, double, i, val);
7931 p += 8;
7933 break;
7934 case MONO_TYPE_U8:
7935 case MONO_TYPE_I8:
7936 for (i = 0; i < alen; i++) {
7937 guint64 val = read64 (p);
7938 mono_array_set (arr, guint64, i, val);
7939 p += 8;
7941 break;
7942 case MONO_TYPE_CLASS:
7943 case MONO_TYPE_OBJECT:
7944 case MONO_TYPE_STRING:
7945 for (i = 0; i < alen; i++) {
7946 MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
7947 mono_array_setref (arr, i, item);
7949 break;
7950 default:
7951 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
7953 *end=p;
7954 return arr;
7956 default:
7957 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
7959 return NULL;
7962 static MonoObject*
7963 create_cattr_typed_arg (MonoType *t, MonoObject *val)
7965 static MonoClass *klass;
7966 static MonoMethod *ctor;
7967 MonoObject *retval;
7968 void *params [2], *unboxed;
7970 if (!klass)
7971 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
7972 if (!ctor)
7973 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7975 params [0] = mono_type_get_object (mono_domain_get (), t);
7976 params [1] = val;
7977 retval = mono_object_new (mono_domain_get (), klass);
7978 unboxed = mono_object_unbox (retval);
7979 mono_runtime_invoke (ctor, unboxed, params, NULL);
7981 return retval;
7984 static MonoObject*
7985 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
7987 static MonoClass *klass;
7988 static MonoMethod *ctor;
7989 MonoObject *retval;
7990 void *unboxed, *params [2];
7992 if (!klass)
7993 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
7994 if (!ctor)
7995 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7997 params [0] = minfo;
7998 params [1] = typedarg;
7999 retval = mono_object_new (mono_domain_get (), klass);
8000 unboxed = mono_object_unbox (retval);
8001 mono_runtime_invoke (ctor, unboxed, params, NULL);
8003 return retval;
8006 static gboolean
8007 type_is_reference (MonoType *type)
8009 switch (type->type) {
8010 case MONO_TYPE_BOOLEAN:
8011 case MONO_TYPE_CHAR:
8012 case MONO_TYPE_U:
8013 case MONO_TYPE_I:
8014 case MONO_TYPE_U1:
8015 case MONO_TYPE_I1:
8016 case MONO_TYPE_U2:
8017 case MONO_TYPE_I2:
8018 case MONO_TYPE_U4:
8019 case MONO_TYPE_I4:
8020 case MONO_TYPE_U8:
8021 case MONO_TYPE_I8:
8022 case MONO_TYPE_R8:
8023 case MONO_TYPE_R4:
8024 case MONO_TYPE_VALUETYPE:
8025 return FALSE;
8026 default:
8027 return TRUE;
8031 static void
8032 free_param_data (MonoMethodSignature *sig, void **params) {
8033 int i;
8034 for (i = 0; i < sig->param_count; ++i) {
8035 if (!type_is_reference (sig->params [i]))
8036 g_free (params [i]);
8041 * Find the field index in the metadata FieldDef table.
8043 static guint32
8044 find_field_index (MonoClass *klass, MonoClassField *field) {
8045 int i;
8047 for (i = 0; i < klass->field.count; ++i) {
8048 if (field == &klass->fields [i])
8049 return klass->field.first + 1 + i;
8051 return 0;
8055 * Find the property index in the metadata Property table.
8057 static guint32
8058 find_property_index (MonoClass *klass, MonoProperty *property) {
8059 int i;
8061 for (i = 0; i < klass->ext->property.count; ++i) {
8062 if (property == &klass->ext->properties [i])
8063 return klass->ext->property.first + 1 + i;
8065 return 0;
8069 * Find the event index in the metadata Event table.
8071 static guint32
8072 find_event_index (MonoClass *klass, MonoEvent *event) {
8073 int i;
8075 for (i = 0; i < klass->ext->event.count; ++i) {
8076 if (event == &klass->ext->events [i])
8077 return klass->ext->event.first + 1 + i;
8079 return 0;
8082 static MonoObject*
8083 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
8085 const char *p = (const char*)data;
8086 const char *named;
8087 guint32 i, j, num_named;
8088 MonoObject *attr;
8089 void *params_buf [32];
8090 void **params;
8091 MonoMethodSignature *sig;
8093 mono_class_init (method->klass);
8095 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL))
8096 return NULL;
8098 if (len == 0) {
8099 attr = mono_object_new (mono_domain_get (), method->klass);
8100 mono_runtime_invoke (method, attr, NULL, NULL);
8101 return attr;
8104 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8105 return NULL;
8107 /*g_print ("got attr %s\n", method->klass->name);*/
8109 sig = mono_method_signature (method);
8110 if (sig->param_count < 32)
8111 params = params_buf;
8112 else
8113 /* Allocate using GC so it gets GC tracking */
8114 params = mono_gc_alloc_fixed (sig->param_count * sizeof (void*), NULL);
8116 /* skip prolog */
8117 p += 2;
8118 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8119 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8122 named = p;
8123 attr = mono_object_new (mono_domain_get (), method->klass);
8124 mono_runtime_invoke (method, attr, params, NULL);
8125 free_param_data (method->signature, params);
8126 num_named = read16 (named);
8127 named += 2;
8128 for (j = 0; j < num_named; j++) {
8129 gint name_len;
8130 char *name, named_type, data_type;
8131 named_type = *named++;
8132 data_type = *named++; /* type of data */
8133 if (data_type == MONO_TYPE_SZARRAY)
8134 data_type = *named++;
8135 if (data_type == MONO_TYPE_ENUM) {
8136 gint type_len;
8137 char *type_name;
8138 type_len = mono_metadata_decode_blob_size (named, &named);
8139 type_name = g_malloc (type_len + 1);
8140 memcpy (type_name, named, type_len);
8141 type_name [type_len] = 0;
8142 named += type_len;
8143 /* FIXME: lookup the type and check type consistency */
8144 g_free (type_name);
8146 name_len = mono_metadata_decode_blob_size (named, &named);
8147 name = g_malloc (name_len + 1);
8148 memcpy (name, named, name_len);
8149 name [name_len] = 0;
8150 named += name_len;
8151 if (named_type == 0x53) {
8152 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
8153 void *val = load_cattr_value (image, field->type, named, &named);
8154 mono_field_set_value (attr, field, val);
8155 if (!type_is_reference (field->type))
8156 g_free (val);
8157 } else if (named_type == 0x54) {
8158 MonoProperty *prop;
8159 void *pparams [1];
8160 MonoType *prop_type;
8162 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
8163 /* can we have more that 1 arg in a custom attr named property? */
8164 prop_type = prop->get? mono_method_signature (prop->get)->ret :
8165 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8166 pparams [0] = load_cattr_value (image, prop_type, named, &named);
8167 mono_property_set_value (prop, attr, pparams, NULL);
8168 if (!type_is_reference (prop_type))
8169 g_free (pparams [0]);
8171 g_free (name);
8174 if (params != params_buf)
8175 mono_gc_free_fixed (params);
8177 return attr;
8181 * mono_reflection_create_custom_attr_data_args:
8183 * Create an array of typed and named arguments from the cattr blob given by DATA.
8184 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
8185 * NAMED_ARG_INFO will contain information about the named arguments.
8187 void
8188 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)
8190 MonoArray *typedargs, *namedargs;
8191 MonoClass *attrklass;
8192 MonoDomain *domain;
8193 const char *p = (const char*)data;
8194 const char *named;
8195 guint32 i, j, num_named;
8196 CattrNamedArg *arginfo = NULL;
8198 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL))
8199 return;
8201 mono_class_init (method->klass);
8203 *typed_args = NULL;
8204 *named_args = NULL;
8205 *named_arg_info = NULL;
8207 domain = mono_domain_get ();
8209 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8210 return;
8212 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
8214 /* skip prolog */
8215 p += 2;
8216 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8217 MonoObject *obj;
8218 void *val;
8220 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8221 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
8222 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
8223 mono_array_setref (typedargs, i, obj);
8225 if (!type_is_reference (mono_method_signature (method)->params [i]))
8226 g_free (val);
8229 named = p;
8230 num_named = read16 (named);
8231 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
8232 named += 2;
8233 attrklass = method->klass;
8235 arginfo = g_new0 (CattrNamedArg, num_named);
8236 *named_arg_info = arginfo;
8238 for (j = 0; j < num_named; j++) {
8239 gint name_len;
8240 char *name, named_type, data_type;
8241 named_type = *named++;
8242 data_type = *named++; /* type of data */
8243 if (data_type == MONO_TYPE_SZARRAY)
8244 data_type = *named++;
8245 if (data_type == MONO_TYPE_ENUM) {
8246 gint type_len;
8247 char *type_name;
8248 type_len = mono_metadata_decode_blob_size (named, &named);
8249 type_name = g_malloc (type_len + 1);
8250 memcpy (type_name, named, type_len);
8251 type_name [type_len] = 0;
8252 named += type_len;
8253 /* FIXME: lookup the type and check type consistency */
8254 g_free (type_name);
8256 name_len = mono_metadata_decode_blob_size (named, &named);
8257 name = g_malloc (name_len + 1);
8258 memcpy (name, named, name_len);
8259 name [name_len] = 0;
8260 named += name_len;
8261 if (named_type == 0x53) {
8262 MonoObject *obj;
8263 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
8264 void *val;
8266 arginfo [j].type = field->type;
8267 arginfo [j].field = field;
8269 val = load_cattr_value (image, field->type, named, &named);
8270 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
8271 mono_array_setref (namedargs, j, obj);
8272 if (!type_is_reference (field->type))
8273 g_free (val);
8274 } else if (named_type == 0x54) {
8275 MonoObject *obj;
8276 MonoType *prop_type;
8277 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
8278 void *val;
8280 prop_type = prop->get? mono_method_signature (prop->get)->ret :
8281 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8283 arginfo [j].type = prop_type;
8284 arginfo [j].prop = prop;
8286 val = load_cattr_value (image, prop_type, named, &named);
8287 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
8288 mono_array_setref (namedargs, j, obj);
8289 if (!type_is_reference (prop_type))
8290 g_free (val);
8292 g_free (name);
8295 *typed_args = typedargs;
8296 *named_args = namedargs;
8299 static MonoObject*
8300 create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
8302 MonoArray *typedargs, *namedargs;
8303 static MonoMethod *ctor;
8304 MonoDomain *domain;
8305 MonoObject *attr;
8306 void *params [3];
8307 CattrNamedArg *arginfo;
8308 int i;
8310 mono_class_init (method->klass);
8312 if (!ctor)
8313 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 3);
8315 domain = mono_domain_get ();
8316 if (len == 0) {
8317 /* This is for Attributes with no parameters */
8318 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8319 params [0] = mono_method_get_object (domain, method, NULL);
8320 params [1] = params [2] = NULL;
8321 mono_runtime_invoke (method, attr, params, NULL);
8322 return attr;
8325 mono_reflection_create_custom_attr_data_args (image, method, data, len, &typedargs, &namedargs, &arginfo);
8326 if (!typedargs || !namedargs)
8327 return NULL;
8329 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8330 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
8331 MonoObject *typedarg;
8333 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
8334 mono_array_setref (typedargs, i, typedarg);
8337 for (i = 0; i < mono_array_length (namedargs); ++i) {
8338 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
8339 MonoObject *typedarg, *namedarg, *minfo;
8341 if (arginfo [i].prop)
8342 minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
8343 else
8344 minfo = (MonoObject*)mono_field_get_object (domain, NULL, arginfo [i].field);
8346 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
8347 namedarg = create_cattr_named_arg (minfo, typedarg);
8349 mono_array_setref (namedargs, i, namedarg);
8352 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8353 params [0] = mono_method_get_object (domain, method, NULL);
8354 params [1] = typedargs;
8355 params [2] = namedargs;
8356 mono_runtime_invoke (ctor, attr, params, NULL);
8357 return attr;
8360 MonoArray*
8361 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
8363 MonoArray *result;
8364 MonoObject *attr;
8365 int i;
8367 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, cinfo->num_attrs);
8368 for (i = 0; i < cinfo->num_attrs; ++i) {
8369 if (!cinfo->attrs [i].ctor)
8370 /* The cattr type is not finished yet */
8371 /* We should include the type name but cinfo doesn't contain it */
8372 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
8373 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
8374 mono_array_setref (result, i, attr);
8376 return result;
8379 static MonoArray*
8380 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass)
8382 MonoArray *result;
8383 MonoObject *attr;
8384 int i, n;
8386 n = 0;
8387 for (i = 0; i < cinfo->num_attrs; ++i) {
8388 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
8389 n ++;
8392 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
8393 n = 0;
8394 for (i = 0; i < cinfo->num_attrs; ++i) {
8395 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
8396 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
8397 mono_array_setref (result, n, attr);
8398 n ++;
8401 return result;
8404 static MonoArray*
8405 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
8407 MonoArray *result;
8408 MonoObject *attr;
8409 int i;
8411 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
8412 for (i = 0; i < cinfo->num_attrs; ++i) {
8413 attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
8414 mono_array_setref (result, i, attr);
8416 return result;
8420 * mono_custom_attrs_from_index:
8422 * Returns: NULL if no attributes are found or if a loading error occurs.
8424 MonoCustomAttrInfo*
8425 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
8427 guint32 mtoken, i, len;
8428 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
8429 MonoTableInfo *ca;
8430 MonoCustomAttrInfo *ainfo;
8431 GList *tmp, *list = NULL;
8432 const char *data;
8434 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
8436 i = mono_metadata_custom_attrs_from_index (image, idx);
8437 if (!i)
8438 return NULL;
8439 i --;
8440 while (i < ca->rows) {
8441 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
8442 break;
8443 list = g_list_prepend (list, GUINT_TO_POINTER (i));
8444 ++i;
8446 len = g_list_length (list);
8447 if (!len)
8448 return NULL;
8449 ainfo = g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
8450 ainfo->num_attrs = len;
8451 ainfo->image = image;
8452 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
8453 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
8454 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
8455 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
8456 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
8457 mtoken |= MONO_TOKEN_METHOD_DEF;
8458 break;
8459 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
8460 mtoken |= MONO_TOKEN_MEMBER_REF;
8461 break;
8462 default:
8463 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
8464 break;
8466 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
8467 if (!ainfo->attrs [i].ctor) {
8468 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
8469 g_list_free (list);
8470 g_free (ainfo);
8471 return NULL;
8474 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
8475 /*FIXME raising an exception here doesn't make any sense*/
8476 g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
8477 g_list_free (list);
8478 g_free (ainfo);
8479 return NULL;
8481 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
8482 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
8483 ainfo->attrs [i].data = (guchar*)data;
8485 g_list_free (list);
8487 return ainfo;
8490 MonoCustomAttrInfo*
8491 mono_custom_attrs_from_method (MonoMethod *method)
8493 guint32 idx;
8496 * An instantiated method has the same cattrs as the generic method definition.
8498 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8499 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8501 if (method->is_inflated)
8502 method = ((MonoMethodInflated *) method)->declaring;
8504 if (method->dynamic || method->klass->image->dynamic)
8505 return lookup_custom_attr (method->klass->image, method);
8507 if (!method->token)
8508 /* Synthetic methods */
8509 return NULL;
8511 idx = mono_method_get_index (method);
8512 idx <<= MONO_CUSTOM_ATTR_BITS;
8513 idx |= MONO_CUSTOM_ATTR_METHODDEF;
8514 return mono_custom_attrs_from_index (method->klass->image, idx);
8517 MonoCustomAttrInfo*
8518 mono_custom_attrs_from_class (MonoClass *klass)
8520 guint32 idx;
8522 if (klass->generic_class)
8523 klass = klass->generic_class->container_class;
8525 if (klass->image->dynamic)
8526 return lookup_custom_attr (klass->image, klass);
8528 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
8529 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
8530 idx <<= MONO_CUSTOM_ATTR_BITS;
8531 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
8532 } else {
8533 idx = mono_metadata_token_index (klass->type_token);
8534 idx <<= MONO_CUSTOM_ATTR_BITS;
8535 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
8537 return mono_custom_attrs_from_index (klass->image, idx);
8540 MonoCustomAttrInfo*
8541 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
8543 guint32 idx;
8545 if (assembly->image->dynamic)
8546 return lookup_custom_attr (assembly->image, assembly);
8547 idx = 1; /* there is only one assembly */
8548 idx <<= MONO_CUSTOM_ATTR_BITS;
8549 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
8550 return mono_custom_attrs_from_index (assembly->image, idx);
8553 static MonoCustomAttrInfo*
8554 mono_custom_attrs_from_module (MonoImage *image)
8556 guint32 idx;
8558 if (image->dynamic)
8559 return lookup_custom_attr (image, image);
8560 idx = 1; /* there is only one module */
8561 idx <<= MONO_CUSTOM_ATTR_BITS;
8562 idx |= MONO_CUSTOM_ATTR_MODULE;
8563 return mono_custom_attrs_from_index (image, idx);
8566 MonoCustomAttrInfo*
8567 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
8569 guint32 idx;
8571 if (klass->image->dynamic) {
8572 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
8573 return lookup_custom_attr (klass->image, property);
8575 idx = find_property_index (klass, property);
8576 idx <<= MONO_CUSTOM_ATTR_BITS;
8577 idx |= MONO_CUSTOM_ATTR_PROPERTY;
8578 return mono_custom_attrs_from_index (klass->image, idx);
8581 MonoCustomAttrInfo*
8582 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
8584 guint32 idx;
8586 if (klass->image->dynamic) {
8587 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
8588 return lookup_custom_attr (klass->image, event);
8590 idx = find_event_index (klass, event);
8591 idx <<= MONO_CUSTOM_ATTR_BITS;
8592 idx |= MONO_CUSTOM_ATTR_EVENT;
8593 return mono_custom_attrs_from_index (klass->image, idx);
8596 MonoCustomAttrInfo*
8597 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
8599 guint32 idx;
8600 if (klass->image->dynamic) {
8601 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
8602 return lookup_custom_attr (klass->image, field);
8604 idx = find_field_index (klass, field);
8605 idx <<= MONO_CUSTOM_ATTR_BITS;
8606 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
8607 return mono_custom_attrs_from_index (klass->image, idx);
8610 MonoCustomAttrInfo*
8611 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
8613 MonoTableInfo *ca;
8614 guint32 i, idx, method_index;
8615 guint32 param_list, param_last, param_pos, found;
8616 MonoImage *image;
8617 MonoReflectionMethodAux *aux;
8620 * An instantiated method has the same cattrs as the generic method definition.
8622 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8623 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8625 if (method->is_inflated)
8626 method = ((MonoMethodInflated *) method)->declaring;
8628 if (method->klass->image->dynamic) {
8629 MonoCustomAttrInfo *res, *ainfo;
8630 int size;
8632 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8633 if (!aux || !aux->param_cattr)
8634 return NULL;
8636 /* Need to copy since it will be freed later */
8637 ainfo = aux->param_cattr [param];
8638 if (!ainfo)
8639 return NULL;
8640 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
8641 res = g_malloc0 (size);
8642 memcpy (res, ainfo, size);
8643 return res;
8646 image = method->klass->image;
8647 method_index = mono_method_get_index (method);
8648 ca = &image->tables [MONO_TABLE_METHOD];
8650 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
8651 if (method_index == ca->rows) {
8652 ca = &image->tables [MONO_TABLE_PARAM];
8653 param_last = ca->rows + 1;
8654 } else {
8655 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
8656 ca = &image->tables [MONO_TABLE_PARAM];
8658 found = FALSE;
8659 for (i = param_list; i < param_last; ++i) {
8660 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
8661 if (param_pos == param) {
8662 found = TRUE;
8663 break;
8666 if (!found)
8667 return NULL;
8668 idx = i;
8669 idx <<= MONO_CUSTOM_ATTR_BITS;
8670 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
8671 return mono_custom_attrs_from_index (image, idx);
8674 gboolean
8675 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8677 int i;
8678 MonoClass *klass;
8679 for (i = 0; i < ainfo->num_attrs; ++i) {
8680 klass = ainfo->attrs [i].ctor->klass;
8681 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
8682 return TRUE;
8684 return FALSE;
8687 MonoObject*
8688 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8690 int i, attr_index;
8691 MonoClass *klass;
8692 MonoArray *attrs;
8694 attr_index = -1;
8695 for (i = 0; i < ainfo->num_attrs; ++i) {
8696 klass = ainfo->attrs [i].ctor->klass;
8697 if (mono_class_has_parent (klass, attr_klass)) {
8698 attr_index = i;
8699 break;
8702 if (attr_index == -1)
8703 return NULL;
8705 attrs = mono_custom_attrs_construct (ainfo);
8706 if (attrs)
8707 return mono_array_get (attrs, MonoObject*, attr_index);
8708 else
8709 return NULL;
8713 * mono_reflection_get_custom_attrs_info:
8714 * @obj: a reflection object handle
8716 * Return the custom attribute info for attributes defined for the
8717 * reflection handle @obj. The objects.
8719 * FIXME this function leaks like a sieve for SRE objects.
8721 MonoCustomAttrInfo*
8722 mono_reflection_get_custom_attrs_info (MonoObject *obj)
8724 MonoClass *klass;
8725 MonoCustomAttrInfo *cinfo = NULL;
8727 klass = obj->vtable->klass;
8728 if (klass == mono_defaults.monotype_class) {
8729 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
8730 klass = mono_class_from_mono_type (type);
8731 if (!mono_class_init (klass))
8732 mono_raise_exception (mono_class_get_exception_for_failure (klass));
8733 cinfo = mono_custom_attrs_from_class (klass);
8734 } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
8735 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
8736 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
8737 } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
8738 MonoReflectionModule *module = (MonoReflectionModule*)obj;
8739 cinfo = mono_custom_attrs_from_module (module->image);
8740 } else if (strcmp ("MonoProperty", klass->name) == 0) {
8741 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
8742 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
8743 } else if (strcmp ("MonoEvent", klass->name) == 0) {
8744 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
8745 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
8746 } else if (strcmp ("MonoField", klass->name) == 0) {
8747 MonoReflectionField *rfield = (MonoReflectionField*)obj;
8748 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
8749 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
8750 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8751 cinfo = mono_custom_attrs_from_method (rmethod->method);
8752 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
8753 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8754 cinfo = mono_custom_attrs_from_method (rmethod->method);
8755 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
8756 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
8757 MonoClass *member_class = mono_object_class (param->MemberImpl);
8758 if (mono_class_is_reflection_method_or_constructor (member_class)) {
8759 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8760 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
8761 } else if (is_sr_mono_property (member_class)) {
8762 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
8763 MonoMethod *method;
8764 if (!(method = prop->property->get))
8765 method = prop->property->set;
8766 g_assert (method);
8768 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8770 #ifndef DISABLE_REFLECTION_EMIT
8771 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
8772 MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl);
8773 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8774 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
8775 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
8776 MonoMethod *method = NULL;
8777 if (is_sre_ctor_builder (mono_object_class (c->cb)))
8778 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
8779 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
8780 method = ((MonoReflectionMethod *)c->cb)->method;
8781 else
8782 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));
8784 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8786 #endif
8787 else {
8788 char *type_name = mono_type_get_full_name (member_class);
8789 char *msg = g_strdup_printf ("Custom attributes on a ParamInfo with member %s are not supported", type_name);
8790 MonoException *ex = mono_get_exception_not_supported (msg);
8791 g_free (type_name);
8792 g_free (msg);
8793 mono_raise_exception (ex);
8795 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
8796 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
8797 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
8798 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
8799 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8800 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
8801 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
8802 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
8803 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
8804 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
8805 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8806 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
8807 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
8808 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8809 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
8810 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
8811 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8812 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
8813 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
8814 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
8815 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
8816 } else { /* handle other types here... */
8817 g_error ("get custom attrs not yet supported for %s", klass->name);
8820 return cinfo;
8824 * mono_reflection_get_custom_attrs_by_type:
8825 * @obj: a reflection object handle
8827 * Return an array with all the custom attributes defined of the
8828 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
8829 * of that type are returned. The objects are fully build. Return NULL if a loading error
8830 * occurs.
8832 MonoArray*
8833 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass)
8835 MonoArray *result;
8836 MonoCustomAttrInfo *cinfo;
8838 cinfo = mono_reflection_get_custom_attrs_info (obj);
8839 if (cinfo) {
8840 if (attr_klass)
8841 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass);
8842 else
8843 result = mono_custom_attrs_construct (cinfo);
8844 if (!cinfo->cached)
8845 mono_custom_attrs_free (cinfo);
8846 } else {
8847 if (mono_loader_get_last_error ())
8848 return NULL;
8849 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
8852 return result;
8856 * mono_reflection_get_custom_attrs:
8857 * @obj: a reflection object handle
8859 * Return an array with all the custom attributes defined of the
8860 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
8861 * occurs.
8863 MonoArray*
8864 mono_reflection_get_custom_attrs (MonoObject *obj)
8866 return mono_reflection_get_custom_attrs_by_type (obj, NULL);
8870 * mono_reflection_get_custom_attrs_data:
8871 * @obj: a reflection obj handle
8873 * Returns an array of System.Reflection.CustomAttributeData,
8874 * which include information about attributes reflected on
8875 * types loaded using the Reflection Only methods
8877 MonoArray*
8878 mono_reflection_get_custom_attrs_data (MonoObject *obj)
8880 MonoArray *result;
8881 MonoCustomAttrInfo *cinfo;
8883 cinfo = mono_reflection_get_custom_attrs_info (obj);
8884 if (cinfo) {
8885 result = mono_custom_attrs_data_construct (cinfo);
8886 if (!cinfo->cached)
8887 mono_custom_attrs_free (cinfo);
8888 } else
8889 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
8891 return result;
8894 static MonoReflectionType*
8895 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
8897 static MonoMethod *method_get_underlying_system_type = NULL;
8898 MonoMethod *usertype_method;
8900 if (!method_get_underlying_system_type)
8901 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
8902 usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
8903 return (MonoReflectionType *) mono_runtime_invoke (usertype_method, t, NULL, NULL);
8907 static gboolean
8908 is_corlib_type (MonoClass *class)
8910 return class->image == mono_defaults.corlib;
8913 #define check_corlib_type_cached(_class, _namespace, _name) do { \
8914 static MonoClass *cached_class; \
8915 if (cached_class) \
8916 return cached_class == _class; \
8917 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
8918 cached_class = _class; \
8919 return TRUE; \
8921 return FALSE; \
8922 } while (0) \
8925 #ifndef DISABLE_REFLECTION_EMIT
8926 static gboolean
8927 is_sre_array (MonoClass *class)
8929 check_corlib_type_cached (class, "System.Reflection.Emit", "ArrayType");
8932 static gboolean
8933 is_sre_byref (MonoClass *class)
8935 check_corlib_type_cached (class, "System.Reflection.Emit", "ByRefType");
8938 static gboolean
8939 is_sre_pointer (MonoClass *class)
8941 check_corlib_type_cached (class, "System.Reflection.Emit", "PointerType");
8944 static gboolean
8945 is_sre_generic_instance (MonoClass *class)
8947 check_corlib_type_cached (class, "System.Reflection", "MonoGenericClass");
8950 static gboolean
8951 is_sre_type_builder (MonoClass *class)
8953 check_corlib_type_cached (class, "System.Reflection.Emit", "TypeBuilder");
8956 static gboolean
8957 is_sre_method_builder (MonoClass *class)
8959 check_corlib_type_cached (class, "System.Reflection.Emit", "MethodBuilder");
8962 static gboolean
8963 is_sre_ctor_builder (MonoClass *class)
8965 check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorBuilder");
8968 static gboolean
8969 is_sre_field_builder (MonoClass *class)
8971 check_corlib_type_cached (class, "System.Reflection.Emit", "FieldBuilder");
8974 static gboolean
8975 is_sre_method_on_tb_inst (MonoClass *class)
8977 check_corlib_type_cached (class, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
8980 static gboolean
8981 is_sre_ctor_on_tb_inst (MonoClass *class)
8983 check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
8986 MonoType*
8987 mono_reflection_type_get_handle (MonoReflectionType* ref)
8989 MonoClass *class;
8990 if (!ref)
8991 return NULL;
8992 if (ref->type)
8993 return ref->type;
8995 if (is_usertype (ref)) {
8996 ref = mono_reflection_type_get_underlying_system_type (ref);
8997 if (ref == NULL || is_usertype (ref))
8998 return NULL;
8999 if (ref->type)
9000 return ref->type;
9003 class = mono_object_class (ref);
9005 if (is_sre_array (class)) {
9006 MonoType *res;
9007 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
9008 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
9009 g_assert (base);
9010 if (sre_array->rank == 0) //single dimentional array
9011 res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
9012 else
9013 res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
9014 sre_array->type.type = res;
9015 return res;
9016 } else if (is_sre_byref (class)) {
9017 MonoType *res;
9018 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
9019 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
9020 g_assert (base);
9021 res = &mono_class_from_mono_type (base)->this_arg;
9022 sre_byref->type.type = res;
9023 return res;
9024 } else if (is_sre_pointer (class)) {
9025 MonoType *res;
9026 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
9027 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
9028 g_assert (base);
9029 res = &mono_ptr_class_get (base)->byval_arg;
9030 sre_pointer->type.type = res;
9031 return res;
9032 } else if (is_sre_generic_instance (class)) {
9033 MonoType *res, **types;
9034 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
9035 int i, count;
9037 count = mono_array_length (gclass->type_arguments);
9038 types = g_new0 (MonoType*, count);
9039 for (i = 0; i < count; ++i) {
9040 MonoReflectionType *t = mono_array_get (gclass->type_arguments, gpointer, i);
9041 types [i] = mono_reflection_type_get_handle (t);
9042 if (!types[i]) {
9043 g_free (types);
9044 return NULL;
9048 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
9049 g_free (types);
9050 g_assert (res);
9051 gclass->type.type = res;
9052 return res;
9055 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
9056 return NULL;
9061 void
9062 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
9064 mono_reflection_type_get_handle (type);
9067 void
9068 mono_reflection_register_with_runtime (MonoReflectionType *type)
9070 MonoType *res = mono_reflection_type_get_handle (type);
9071 MonoDomain *domain = mono_object_domain ((MonoObject*)type);
9072 MonoClass *class;
9074 if (!res)
9075 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
9077 class = mono_class_from_mono_type (res);
9079 mono_loader_lock (); /*same locking as mono_type_get_object*/
9080 mono_domain_lock (domain);
9082 if (!class->image->dynamic) {
9083 mono_class_setup_supertypes (class);
9084 } else {
9085 if (!domain->type_hash)
9086 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash,
9087 (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
9088 mono_g_hash_table_insert (domain->type_hash, res, type);
9090 mono_domain_unlock (domain);
9091 mono_loader_unlock ();
9095 * LOCKING: Assumes the loader lock is held.
9097 static MonoMethodSignature*
9098 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
9099 MonoMethodSignature *sig;
9100 int count, i;
9102 count = parameters? mono_array_length (parameters): 0;
9104 sig = image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
9105 sig->param_count = count;
9106 sig->sentinelpos = -1; /* FIXME */
9107 for (i = 0; i < count; ++i)
9108 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
9109 return sig;
9113 * LOCKING: Assumes the loader lock is held.
9115 static MonoMethodSignature*
9116 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
9117 MonoMethodSignature *sig;
9119 sig = parameters_to_signature (image, ctor->parameters);
9120 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9121 sig->ret = &mono_defaults.void_class->byval_arg;
9122 return sig;
9126 * LOCKING: Assumes the loader lock is held.
9128 static MonoMethodSignature*
9129 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
9130 MonoMethodSignature *sig;
9132 sig = parameters_to_signature (image, method->parameters);
9133 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9134 sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
9135 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
9136 return sig;
9139 static MonoMethodSignature*
9140 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
9141 MonoMethodSignature *sig;
9143 sig = parameters_to_signature (NULL, method->parameters);
9144 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9145 sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
9146 sig->generic_param_count = 0;
9147 return sig;
9150 static void
9151 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
9153 MonoClass *klass = mono_object_class (prop);
9154 if (strcmp (klass->name, "PropertyBuilder") == 0) {
9155 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
9156 *name = mono_string_to_utf8 (pb->name);
9157 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
9158 } else {
9159 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
9160 *name = g_strdup (p->property->name);
9161 if (p->property->get)
9162 *type = mono_method_signature (p->property->get)->ret;
9163 else
9164 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
9168 static void
9169 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
9171 MonoClass *klass = mono_object_class (field);
9172 if (strcmp (klass->name, "FieldBuilder") == 0) {
9173 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
9174 *name = mono_string_to_utf8 (fb->name);
9175 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9176 } else {
9177 MonoReflectionField *f = (MonoReflectionField *)field;
9178 *name = g_strdup (mono_field_get_name (f->field));
9179 *type = f->field->type;
9183 #else /* DISABLE_REFLECTION_EMIT */
9185 void
9186 mono_reflection_register_with_runtime (MonoReflectionType *type)
9188 /* This is empty */
9191 static gboolean
9192 is_sre_type_builder (MonoClass *class)
9194 return FALSE;
9197 static gboolean
9198 is_sre_generic_instance (MonoClass *class)
9200 return FALSE;
9203 #endif /* !DISABLE_REFLECTION_EMIT */
9206 static gboolean
9207 is_sr_mono_field (MonoClass *class)
9209 check_corlib_type_cached (class, "System.Reflection", "MonoField");
9212 static gboolean
9213 is_sr_mono_property (MonoClass *class)
9215 check_corlib_type_cached (class, "System.Reflection", "MonoProperty");
9218 static gboolean
9219 is_sr_mono_method (MonoClass *class)
9221 check_corlib_type_cached (class, "System.Reflection", "MonoMethod");
9224 static gboolean
9225 is_sr_mono_cmethod (MonoClass *class)
9227 check_corlib_type_cached (class, "System.Reflection", "MonoCMethod");
9230 static gboolean
9231 is_sr_mono_generic_method (MonoClass *class)
9233 check_corlib_type_cached (class, "System.Reflection", "MonoGenericMethod");
9236 static gboolean
9237 is_sr_mono_generic_cmethod (MonoClass *class)
9239 check_corlib_type_cached (class, "System.Reflection", "MonoGenericCMethod");
9242 gboolean
9243 mono_class_is_reflection_method_or_constructor (MonoClass *class)
9245 return is_sr_mono_method (class) || is_sr_mono_cmethod (class) || is_sr_mono_generic_method (class) || is_sr_mono_generic_cmethod (class);
9248 static gboolean
9249 is_usertype (MonoReflectionType *ref)
9251 MonoClass *class = mono_object_class (ref);
9252 return class->image != mono_defaults.corlib || strcmp ("TypeDelegator", class->name) == 0;
9255 static MonoReflectionType*
9256 mono_reflection_type_resolve_user_types (MonoReflectionType *type)
9258 if (!type || type->type)
9259 return type;
9261 if (is_usertype (type)) {
9262 type = mono_reflection_type_get_underlying_system_type (type);
9263 if (is_usertype (type))
9264 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported22"));
9267 return type;
9270 * Encode a value in a custom attribute stream of bytes.
9271 * The value to encode is either supplied as an object in argument val
9272 * (valuetypes are boxed), or as a pointer to the data in the
9273 * argument argval.
9274 * @type represents the type of the value
9275 * @buffer is the start of the buffer
9276 * @p the current position in the buffer
9277 * @buflen contains the size of the buffer and is used to return the new buffer size
9278 * if this needs to be realloced.
9279 * @retbuffer and @retp return the start and the position of the buffer
9281 static void
9282 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
9284 MonoTypeEnum simple_type;
9286 if ((p-buffer) + 10 >= *buflen) {
9287 char *newbuf;
9288 *buflen *= 2;
9289 newbuf = g_realloc (buffer, *buflen);
9290 p = newbuf + (p-buffer);
9291 buffer = newbuf;
9293 if (!argval)
9294 argval = ((char*)arg + sizeof (MonoObject));
9295 simple_type = type->type;
9296 handle_enum:
9297 switch (simple_type) {
9298 case MONO_TYPE_BOOLEAN:
9299 case MONO_TYPE_U1:
9300 case MONO_TYPE_I1:
9301 *p++ = *argval;
9302 break;
9303 case MONO_TYPE_CHAR:
9304 case MONO_TYPE_U2:
9305 case MONO_TYPE_I2:
9306 swap_with_size (p, argval, 2, 1);
9307 p += 2;
9308 break;
9309 case MONO_TYPE_U4:
9310 case MONO_TYPE_I4:
9311 case MONO_TYPE_R4:
9312 swap_with_size (p, argval, 4, 1);
9313 p += 4;
9314 break;
9315 case MONO_TYPE_R8:
9316 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
9317 p [0] = argval [4];
9318 p [1] = argval [5];
9319 p [2] = argval [6];
9320 p [3] = argval [7];
9321 p [4] = argval [0];
9322 p [5] = argval [1];
9323 p [6] = argval [2];
9324 p [7] = argval [3];
9325 #else
9326 swap_with_size (p, argval, 8, 1);
9327 #endif
9328 p += 8;
9329 break;
9330 case MONO_TYPE_U8:
9331 case MONO_TYPE_I8:
9332 swap_with_size (p, argval, 8, 1);
9333 p += 8;
9334 break;
9335 case MONO_TYPE_VALUETYPE:
9336 if (type->data.klass->enumtype) {
9337 simple_type = mono_class_enum_basetype (type->data.klass)->type;
9338 goto handle_enum;
9339 } else {
9340 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
9342 break;
9343 case MONO_TYPE_STRING: {
9344 char *str;
9345 guint32 slen;
9346 if (!arg) {
9347 *p++ = 0xFF;
9348 break;
9350 str = mono_string_to_utf8 ((MonoString*)arg);
9351 slen = strlen (str);
9352 if ((p-buffer) + 10 + slen >= *buflen) {
9353 char *newbuf;
9354 *buflen *= 2;
9355 *buflen += slen;
9356 newbuf = g_realloc (buffer, *buflen);
9357 p = newbuf + (p-buffer);
9358 buffer = newbuf;
9360 mono_metadata_encode_value (slen, p, &p);
9361 memcpy (p, str, slen);
9362 p += slen;
9363 g_free (str);
9364 break;
9366 case MONO_TYPE_CLASS: {
9367 char *str;
9368 guint32 slen;
9369 if (!arg) {
9370 *p++ = 0xFF;
9371 break;
9373 handle_type:
9374 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
9375 slen = strlen (str);
9376 if ((p-buffer) + 10 + slen >= *buflen) {
9377 char *newbuf;
9378 *buflen *= 2;
9379 *buflen += slen;
9380 newbuf = g_realloc (buffer, *buflen);
9381 p = newbuf + (p-buffer);
9382 buffer = newbuf;
9384 mono_metadata_encode_value (slen, p, &p);
9385 memcpy (p, str, slen);
9386 p += slen;
9387 g_free (str);
9388 break;
9390 case MONO_TYPE_SZARRAY: {
9391 int len, i;
9392 MonoClass *eclass, *arg_eclass;
9394 if (!arg) {
9395 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
9396 break;
9398 len = mono_array_length ((MonoArray*)arg);
9399 *p++ = len & 0xff;
9400 *p++ = (len >> 8) & 0xff;
9401 *p++ = (len >> 16) & 0xff;
9402 *p++ = (len >> 24) & 0xff;
9403 *retp = p;
9404 *retbuffer = buffer;
9405 eclass = type->data.klass;
9406 arg_eclass = mono_object_class (arg)->element_class;
9408 if (!eclass) {
9409 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
9410 eclass = mono_defaults.object_class;
9412 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
9413 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9414 int elsize = mono_class_array_element_size (arg_eclass);
9415 for (i = 0; i < len; ++i) {
9416 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
9417 elptr += elsize;
9419 } else if (eclass->valuetype && arg_eclass->valuetype) {
9420 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9421 int elsize = mono_class_array_element_size (eclass);
9422 for (i = 0; i < len; ++i) {
9423 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
9424 elptr += elsize;
9426 } else {
9427 for (i = 0; i < len; ++i) {
9428 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
9431 break;
9433 case MONO_TYPE_OBJECT: {
9434 MonoClass *klass;
9435 char *str;
9436 guint32 slen;
9439 * The parameter type is 'object' but the type of the actual
9440 * argument is not. So we have to add type information to the blob
9441 * too. This is completely undocumented in the spec.
9444 if (arg == NULL) {
9445 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
9446 *p++ = 0xFF;
9447 break;
9450 klass = mono_object_class (arg);
9452 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
9453 *p++ = 0x50;
9454 goto handle_type;
9455 } else if (klass->enumtype) {
9456 *p++ = 0x55;
9457 } else if (klass == mono_defaults.string_class) {
9458 simple_type = MONO_TYPE_STRING;
9459 *p++ = 0x0E;
9460 goto handle_enum;
9461 } else if (klass->rank == 1) {
9462 *p++ = 0x1D;
9463 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
9464 /* See Partition II, Appendix B3 */
9465 *p++ = 0x51;
9466 else
9467 *p++ = klass->element_class->byval_arg.type;
9468 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
9469 break;
9470 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
9471 *p++ = simple_type = klass->byval_arg.type;
9472 goto handle_enum;
9473 } else {
9474 g_error ("unhandled type in custom attr");
9476 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
9477 slen = strlen (str);
9478 if ((p-buffer) + 10 + slen >= *buflen) {
9479 char *newbuf;
9480 *buflen *= 2;
9481 *buflen += slen;
9482 newbuf = g_realloc (buffer, *buflen);
9483 p = newbuf + (p-buffer);
9484 buffer = newbuf;
9486 mono_metadata_encode_value (slen, p, &p);
9487 memcpy (p, str, slen);
9488 p += slen;
9489 g_free (str);
9490 simple_type = mono_class_enum_basetype (klass)->type;
9491 goto handle_enum;
9493 default:
9494 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
9496 *retp = p;
9497 *retbuffer = buffer;
9500 static void
9501 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
9503 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9504 char *str = type_get_qualified_name (type, NULL);
9505 int slen = strlen (str);
9507 *p++ = 0x55;
9509 * This seems to be optional...
9510 * *p++ = 0x80;
9512 mono_metadata_encode_value (slen, p, &p);
9513 memcpy (p, str, slen);
9514 p += slen;
9515 g_free (str);
9516 } else if (type->type == MONO_TYPE_OBJECT) {
9517 *p++ = 0x51;
9518 } else if (type->type == MONO_TYPE_CLASS) {
9519 /* it should be a type: encode_cattr_value () has the check */
9520 *p++ = 0x50;
9521 } else {
9522 mono_metadata_encode_value (type->type, p, &p);
9523 if (type->type == MONO_TYPE_SZARRAY)
9524 /* See the examples in Partition VI, Annex B */
9525 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
9528 *retp = p;
9531 #ifndef DISABLE_REFLECTION_EMIT
9532 static void
9533 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
9535 int len;
9536 /* Preallocate a large enough buffer */
9537 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9538 char *str = type_get_qualified_name (type, NULL);
9539 len = strlen (str);
9540 g_free (str);
9541 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
9542 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
9543 len = strlen (str);
9544 g_free (str);
9545 } else {
9546 len = 0;
9548 len += strlen (name);
9550 if ((p-buffer) + 20 + len >= *buflen) {
9551 char *newbuf;
9552 *buflen *= 2;
9553 *buflen += len;
9554 newbuf = g_realloc (buffer, *buflen);
9555 p = newbuf + (p-buffer);
9556 buffer = newbuf;
9559 encode_field_or_prop_type (type, p, &p);
9561 len = strlen (name);
9562 mono_metadata_encode_value (len, p, &p);
9563 memcpy (p, name, len);
9564 p += len;
9565 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
9566 *retp = p;
9567 *retbuffer = buffer;
9571 * mono_reflection_get_custom_attrs_blob:
9572 * @ctor: custom attribute constructor
9573 * @ctorArgs: arguments o the constructor
9574 * @properties:
9575 * @propValues:
9576 * @fields:
9577 * @fieldValues:
9579 * Creates the blob of data that needs to be saved in the metadata and that represents
9580 * the custom attributed described by @ctor, @ctorArgs etc.
9581 * Returns: a Byte array representing the blob of data.
9583 MonoArray*
9584 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
9586 MonoArray *result;
9587 MonoMethodSignature *sig;
9588 MonoObject *arg;
9589 char *buffer, *p;
9590 guint32 buflen, i;
9592 MONO_ARCH_SAVE_REGS;
9594 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
9595 /* sig is freed later so allocate it in the heap */
9596 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
9597 } else {
9598 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
9601 g_assert (mono_array_length (ctorArgs) == sig->param_count);
9602 buflen = 256;
9603 p = buffer = g_malloc (buflen);
9604 /* write the prolog */
9605 *p++ = 1;
9606 *p++ = 0;
9607 for (i = 0; i < sig->param_count; ++i) {
9608 arg = mono_array_get (ctorArgs, MonoObject*, i);
9609 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
9611 i = 0;
9612 if (properties)
9613 i += mono_array_length (properties);
9614 if (fields)
9615 i += mono_array_length (fields);
9616 *p++ = i & 0xff;
9617 *p++ = (i >> 8) & 0xff;
9618 if (properties) {
9619 MonoObject *prop;
9620 for (i = 0; i < mono_array_length (properties); ++i) {
9621 MonoType *ptype;
9622 char *pname;
9624 prop = mono_array_get (properties, gpointer, i);
9625 get_prop_name_and_type (prop, &pname, &ptype);
9626 *p++ = 0x54; /* PROPERTY signature */
9627 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
9628 g_free (pname);
9632 if (fields) {
9633 MonoObject *field;
9634 for (i = 0; i < mono_array_length (fields); ++i) {
9635 MonoType *ftype;
9636 char *fname;
9638 field = mono_array_get (fields, gpointer, i);
9639 get_field_name_and_type (field, &fname, &ftype);
9640 *p++ = 0x53; /* FIELD signature */
9641 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
9642 g_free (fname);
9646 g_assert (p - buffer <= buflen);
9647 buflen = p - buffer;
9648 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9649 p = mono_array_addr (result, char, 0);
9650 memcpy (p, buffer, buflen);
9651 g_free (buffer);
9652 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
9653 g_free (sig);
9654 return result;
9658 * mono_reflection_setup_internal_class:
9659 * @tb: a TypeBuilder object
9661 * Creates a MonoClass that represents the TypeBuilder.
9662 * This is a trick that lets us simplify a lot of reflection code
9663 * (and will allow us to support Build and Run assemblies easier).
9665 void
9666 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
9668 MonoError error;
9669 MonoClass *klass, *parent;
9671 MONO_ARCH_SAVE_REGS;
9673 RESOLVE_TYPE (tb->parent);
9675 mono_loader_lock ();
9677 if (tb->parent) {
9678 /* check so we can compile corlib correctly */
9679 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
9680 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
9681 parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
9682 } else {
9683 parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
9685 } else {
9686 parent = NULL;
9689 /* the type has already being created: it means we just have to change the parent */
9690 if (tb->type.type) {
9691 klass = mono_class_from_mono_type (tb->type.type);
9692 klass->parent = NULL;
9693 /* fool mono_class_setup_parent */
9694 klass->supertypes = NULL;
9695 mono_class_setup_parent (klass, parent);
9696 mono_class_setup_mono_type (klass);
9697 mono_loader_unlock ();
9698 return;
9701 klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
9703 klass->image = &tb->module->dynamic_image->image;
9705 klass->inited = 1; /* we lie to the runtime */
9706 klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
9707 if (!mono_error_ok (&error))
9708 goto failure;
9709 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
9710 if (!mono_error_ok (&error))
9711 goto failure;
9712 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
9713 klass->flags = tb->attrs;
9715 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
9717 klass->element_class = klass;
9719 if (mono_class_get_ref_info (klass) == NULL) {
9721 mono_class_set_ref_info (klass, tb);
9723 /* Put into cache so mono_class_get () will find it.
9724 Skip nested types as those should not be available on the global scope. */
9725 if (!tb->nesting_type) {
9726 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
9727 } else {
9728 klass->image->reflection_info_unregister_classes =
9729 g_slist_prepend (klass->image->reflection_info_unregister_classes, klass);
9731 } else {
9732 g_assert (mono_class_get_ref_info (klass) == tb);
9735 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
9736 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
9738 if (parent != NULL) {
9739 mono_class_setup_parent (klass, parent);
9740 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
9741 const char *old_n = klass->name;
9742 /* trick to get relative numbering right when compiling corlib */
9743 klass->name = "BuildingObject";
9744 mono_class_setup_parent (klass, mono_defaults.object_class);
9745 klass->name = old_n;
9748 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
9749 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
9750 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
9751 klass->instance_size = sizeof (MonoObject);
9752 klass->size_inited = 1;
9753 mono_class_setup_vtable_general (klass, NULL, 0);
9756 mono_class_setup_mono_type (klass);
9758 mono_class_setup_supertypes (klass);
9761 * FIXME: handle interfaces.
9764 tb->type.type = &klass->byval_arg;
9766 if (tb->nesting_type) {
9767 g_assert (tb->nesting_type->type);
9768 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
9771 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
9773 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
9775 mono_loader_unlock ();
9776 return;
9778 failure:
9779 mono_loader_unlock ();
9780 mono_error_raise_exception (&error);
9784 * mono_reflection_setup_generic_class:
9785 * @tb: a TypeBuilder object
9787 * Setup the generic class before adding the first generic parameter.
9789 void
9790 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
9795 * mono_reflection_create_generic_class:
9796 * @tb: a TypeBuilder object
9798 * Creates the generic class after all generic parameters have been added.
9800 void
9801 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
9803 MonoClass *klass;
9804 int count, i;
9806 MONO_ARCH_SAVE_REGS;
9808 klass = mono_class_from_mono_type (tb->type.type);
9810 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
9812 if (klass->generic_container || (count == 0))
9813 return;
9815 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
9817 klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
9819 klass->generic_container->owner.klass = klass;
9820 klass->generic_container->type_argc = count;
9821 klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
9823 klass->is_generic = 1;
9825 for (i = 0; i < count; i++) {
9826 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
9827 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
9828 klass->generic_container->type_params [i] = *param;
9829 /*Make sure we are a diferent type instance */
9830 klass->generic_container->type_params [i].param.owner = klass->generic_container;
9831 klass->generic_container->type_params [i].info.pklass = NULL;
9832 klass->generic_container->type_params [i].info.flags = gparam->attrs;
9834 g_assert (klass->generic_container->type_params [i].param.owner);
9837 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
9841 * mono_reflection_create_internal_class:
9842 * @tb: a TypeBuilder object
9844 * Actually create the MonoClass that is associated with the TypeBuilder.
9846 void
9847 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
9849 MonoClass *klass;
9851 MONO_ARCH_SAVE_REGS;
9853 klass = mono_class_from_mono_type (tb->type.type);
9855 mono_loader_lock ();
9856 if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
9857 MonoReflectionFieldBuilder *fb;
9858 MonoClass *ec;
9859 MonoType *enum_basetype;
9861 g_assert (tb->fields != NULL);
9862 g_assert (mono_array_length (tb->fields) >= 1);
9864 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
9866 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
9867 mono_loader_unlock ();
9868 return;
9871 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9872 klass->element_class = mono_class_from_mono_type (enum_basetype);
9873 if (!klass->element_class)
9874 klass->element_class = mono_class_from_mono_type (enum_basetype);
9877 * get the element_class from the current corlib.
9879 ec = default_class_from_mono_type (enum_basetype);
9880 klass->instance_size = ec->instance_size;
9881 klass->size_inited = 1;
9883 * this is almost safe to do with enums and it's needed to be able
9884 * to create objects of the enum type (for use in SetConstant).
9886 /* FIXME: Does this mean enums can't have method overrides ? */
9887 mono_class_setup_vtable_general (klass, NULL, 0);
9889 mono_loader_unlock ();
9892 static MonoMarshalSpec*
9893 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
9894 MonoReflectionMarshal *minfo)
9896 MonoMarshalSpec *res;
9898 res = image_g_new0 (image, MonoMarshalSpec, 1);
9899 res->native = minfo->type;
9901 switch (minfo->type) {
9902 case MONO_NATIVE_LPARRAY:
9903 res->data.array_data.elem_type = minfo->eltype;
9904 if (minfo->has_size) {
9905 res->data.array_data.param_num = minfo->param_num;
9906 res->data.array_data.num_elem = minfo->count;
9907 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
9909 else {
9910 res->data.array_data.param_num = -1;
9911 res->data.array_data.num_elem = -1;
9912 res->data.array_data.elem_mult = -1;
9914 break;
9916 case MONO_NATIVE_BYVALTSTR:
9917 case MONO_NATIVE_BYVALARRAY:
9918 res->data.array_data.num_elem = minfo->count;
9919 break;
9921 case MONO_NATIVE_CUSTOM:
9922 if (minfo->marshaltyperef)
9923 res->data.custom_data.custom_name =
9924 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
9925 if (minfo->mcookie)
9926 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
9927 break;
9929 default:
9930 break;
9933 return res;
9935 #endif /* !DISABLE_REFLECTION_EMIT */
9937 MonoReflectionMarshal*
9938 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
9939 MonoMarshalSpec *spec)
9941 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
9942 MonoReflectionMarshal *minfo;
9943 MonoType *mtype;
9945 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
9946 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
9947 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
9948 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
9951 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
9952 minfo->type = spec->native;
9954 switch (minfo->type) {
9955 case MONO_NATIVE_LPARRAY:
9956 minfo->eltype = spec->data.array_data.elem_type;
9957 minfo->count = spec->data.array_data.num_elem;
9958 minfo->param_num = spec->data.array_data.param_num;
9959 break;
9961 case MONO_NATIVE_BYVALTSTR:
9962 case MONO_NATIVE_BYVALARRAY:
9963 minfo->count = spec->data.array_data.num_elem;
9964 break;
9966 case MONO_NATIVE_CUSTOM:
9967 if (spec->data.custom_data.custom_name) {
9968 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
9969 if (mtype)
9970 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
9972 MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
9974 if (spec->data.custom_data.cookie)
9975 MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
9976 break;
9978 default:
9979 break;
9982 return minfo;
9985 #ifndef DISABLE_REFLECTION_EMIT
9986 static MonoMethod*
9987 reflection_methodbuilder_to_mono_method (MonoClass *klass,
9988 ReflectionMethodBuilder *rmb,
9989 MonoMethodSignature *sig)
9991 MonoError error;
9992 MonoMethod *m;
9993 MonoMethodWrapper *wrapperm;
9994 MonoMarshalSpec **specs;
9995 MonoReflectionMethodAux *method_aux;
9996 MonoImage *image;
9997 gboolean dynamic;
9998 int i;
10000 mono_error_init (&error);
10002 * Methods created using a MethodBuilder should have their memory allocated
10003 * inside the image mempool, while dynamic methods should have their memory
10004 * malloc'd.
10006 dynamic = rmb->refs != NULL;
10007 image = dynamic ? NULL : klass->image;
10009 if (!dynamic)
10010 g_assert (!klass->generic_class);
10012 mono_loader_lock ();
10014 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
10015 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
10016 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
10017 else
10018 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
10020 wrapperm = (MonoMethodWrapper*)m;
10022 m->dynamic = dynamic;
10023 m->slot = -1;
10024 m->flags = rmb->attrs;
10025 m->iflags = rmb->iattrs;
10026 m->name = mono_string_to_utf8_image (image, rmb->name, &error);
10027 g_assert (mono_error_ok (&error));
10028 m->klass = klass;
10029 m->signature = sig;
10030 m->sre_method = TRUE;
10031 m->skip_visibility = rmb->skip_visibility;
10032 if (rmb->table_idx)
10033 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
10035 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
10036 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
10037 m->string_ctor = 1;
10039 m->signature->pinvoke = 1;
10040 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
10041 m->signature->pinvoke = 1;
10043 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10045 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
10046 g_assert (mono_error_ok (&error));
10047 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
10048 g_assert (mono_error_ok (&error));
10050 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
10052 if (klass->image->dynamic)
10053 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10055 mono_loader_unlock ();
10057 return m;
10058 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
10059 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
10060 MonoMethodHeader *header;
10061 guint32 code_size;
10062 gint32 max_stack, i;
10063 gint32 num_locals = 0;
10064 gint32 num_clauses = 0;
10065 guint8 *code;
10067 if (rmb->ilgen) {
10068 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
10069 code_size = rmb->ilgen->code_len;
10070 max_stack = rmb->ilgen->max_stack;
10071 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
10072 if (rmb->ilgen->ex_handlers)
10073 num_clauses = method_count_clauses (rmb->ilgen);
10074 } else {
10075 if (rmb->code) {
10076 code = mono_array_addr (rmb->code, guint8, 0);
10077 code_size = mono_array_length (rmb->code);
10078 /* we probably need to run a verifier on the code... */
10079 max_stack = 8;
10081 else {
10082 code = NULL;
10083 code_size = 0;
10084 max_stack = 8;
10088 header = image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
10089 header->code_size = code_size;
10090 header->code = image_g_malloc (image, code_size);
10091 memcpy ((char*)header->code, code, code_size);
10092 header->max_stack = max_stack;
10093 header->init_locals = rmb->init_locals;
10094 header->num_locals = num_locals;
10096 for (i = 0; i < num_locals; ++i) {
10097 MonoReflectionLocalBuilder *lb =
10098 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
10100 header->locals [i] = image_g_new0 (image, MonoType, 1);
10101 memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
10104 header->num_clauses = num_clauses;
10105 if (num_clauses) {
10106 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
10107 rmb->ilgen, num_clauses);
10110 wrapperm->header = header;
10113 if (rmb->generic_params) {
10114 int count = mono_array_length (rmb->generic_params);
10115 MonoGenericContainer *container = rmb->generic_container;
10117 g_assert (container);
10119 container->type_argc = count;
10120 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
10121 container->owner.method = m;
10123 m->is_generic = TRUE;
10124 mono_method_set_generic_container (m, container);
10126 for (i = 0; i < count; i++) {
10127 MonoReflectionGenericParam *gp =
10128 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
10129 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
10130 container->type_params [i] = *param;
10133 if (klass->generic_container) {
10134 container->parent = klass->generic_container;
10135 container->context.class_inst = klass->generic_container->context.class_inst;
10137 container->context.method_inst = mono_get_shared_generic_inst (container);
10140 if (rmb->refs) {
10141 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
10142 int i;
10143 void **data;
10145 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
10147 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
10148 data [0] = GUINT_TO_POINTER (rmb->nrefs);
10149 for (i = 0; i < rmb->nrefs; ++i)
10150 data [i + 1] = rmb->refs [i];
10153 method_aux = NULL;
10155 /* Parameter info */
10156 if (rmb->pinfo) {
10157 if (!method_aux)
10158 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10159 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
10160 for (i = 0; i <= m->signature->param_count; ++i) {
10161 MonoReflectionParamBuilder *pb;
10162 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10163 if ((i > 0) && (pb->attrs)) {
10164 /* Make a copy since it might point to a shared type structure */
10165 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
10166 m->signature->params [i - 1]->attrs = pb->attrs;
10169 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
10170 MonoDynamicImage *assembly;
10171 guint32 idx, def_type, len;
10172 char *p;
10173 const char *p2;
10175 if (!method_aux->param_defaults) {
10176 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
10177 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
10179 assembly = (MonoDynamicImage*)klass->image;
10180 idx = encode_constant (assembly, pb->def_value, &def_type);
10181 /* Copy the data from the blob since it might get realloc-ed */
10182 p = assembly->blob.data + idx;
10183 len = mono_metadata_decode_blob_size (p, &p2);
10184 len += p2 - p;
10185 method_aux->param_defaults [i] = image_g_malloc (image, len);
10186 method_aux->param_default_types [i] = def_type;
10187 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
10190 if (pb->name) {
10191 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
10192 g_assert (mono_error_ok (&error));
10194 if (pb->cattrs) {
10195 if (!method_aux->param_cattr)
10196 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
10197 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
10203 /* Parameter marshalling */
10204 specs = NULL;
10205 if (rmb->pinfo)
10206 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
10207 MonoReflectionParamBuilder *pb;
10208 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10209 if (pb->marshal_info) {
10210 if (specs == NULL)
10211 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
10212 specs [pb->position] =
10213 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
10217 if (specs != NULL) {
10218 if (!method_aux)
10219 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10220 method_aux->param_marshall = specs;
10223 if (klass->image->dynamic && method_aux)
10224 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10226 mono_loader_unlock ();
10228 return m;
10231 static MonoMethod*
10232 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
10234 ReflectionMethodBuilder rmb;
10235 MonoMethodSignature *sig;
10237 mono_loader_lock ();
10238 sig = ctor_builder_to_signature (klass->image, mb);
10239 mono_loader_unlock ();
10241 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
10243 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10244 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10246 /* If we are in a generic class, we might be called multiple times from inflate_method */
10247 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10248 /* ilgen is no longer needed */
10249 mb->ilgen = NULL;
10252 return mb->mhandle;
10255 static MonoMethod*
10256 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
10258 ReflectionMethodBuilder rmb;
10259 MonoMethodSignature *sig;
10261 mono_loader_lock ();
10262 sig = method_builder_to_signature (klass->image, mb);
10263 mono_loader_unlock ();
10265 reflection_methodbuilder_from_method_builder (&rmb, mb);
10267 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10268 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10270 /* If we are in a generic class, we might be called multiple times from inflate_method */
10271 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10272 /* ilgen is no longer needed */
10273 mb->ilgen = NULL;
10275 return mb->mhandle;
10278 static MonoClassField*
10279 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
10281 MonoClassField *field;
10282 MonoType *custom;
10284 field = g_new0 (MonoClassField, 1);
10286 field->name = mono_string_to_utf8 (fb->name);
10287 if (fb->attrs || fb->modreq || fb->modopt) {
10288 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10289 field->type->attrs = fb->attrs;
10291 g_assert (klass->image->dynamic);
10292 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
10293 g_free (field->type);
10294 field->type = custom;
10295 } else {
10296 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10298 if (fb->offset != -1)
10299 field->offset = fb->offset;
10300 field->parent = klass;
10301 mono_save_custom_attrs (klass->image, field, fb->cattrs);
10303 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
10305 return field;
10307 #endif
10309 MonoType*
10310 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
10312 MonoClass *klass;
10313 MonoReflectionTypeBuilder *tb = NULL;
10314 gboolean is_dynamic = FALSE;
10315 MonoDomain *domain;
10316 MonoClass *geninst;
10318 mono_loader_lock ();
10320 domain = mono_object_domain (type);
10322 if (is_sre_type_builder (mono_object_class (type))) {
10323 tb = (MonoReflectionTypeBuilder *) type;
10325 is_dynamic = TRUE;
10326 } else if (is_sre_generic_instance (mono_object_class (type))) {
10327 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
10328 MonoReflectionType *gtd = rgi->generic_type;
10330 if (is_sre_type_builder (mono_object_class (gtd))) {
10331 tb = (MonoReflectionTypeBuilder *)gtd;
10332 is_dynamic = TRUE;
10336 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
10337 if (tb && tb->generic_container)
10338 mono_reflection_create_generic_class (tb);
10340 klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10341 if (!klass->generic_container) {
10342 mono_loader_unlock ();
10343 return NULL;
10346 if (klass->wastypebuilder) {
10347 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
10349 is_dynamic = TRUE;
10352 mono_loader_unlock ();
10354 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
10356 return &geninst->byval_arg;
10359 MonoClass*
10360 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
10362 MonoGenericClass *gclass;
10363 MonoGenericInst *inst;
10365 g_assert (klass->generic_container);
10367 inst = mono_metadata_get_generic_inst (type_argc, types);
10368 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
10370 return mono_generic_class_get_class (gclass);
10373 MonoReflectionMethod*
10374 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
10376 MonoClass *klass;
10377 MonoMethod *method, *inflated;
10378 MonoMethodInflated *imethod;
10379 MonoGenericContext tmp_context;
10380 MonoGenericInst *ginst;
10381 MonoType **type_argv;
10382 int count, i;
10384 MONO_ARCH_SAVE_REGS;
10386 /*FIXME but this no longer should happen*/
10387 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
10388 #ifndef DISABLE_REFLECTION_EMIT
10389 MonoReflectionMethodBuilder *mb = NULL;
10390 MonoReflectionTypeBuilder *tb;
10391 MonoClass *klass;
10393 mb = (MonoReflectionMethodBuilder *) rmethod;
10394 tb = (MonoReflectionTypeBuilder *) mb->type;
10395 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10397 method = methodbuilder_to_mono_method (klass, mb);
10398 #else
10399 g_assert_not_reached ();
10400 method = NULL;
10401 #endif
10402 } else {
10403 method = rmethod->method;
10406 klass = method->klass;
10408 if (method->is_inflated)
10409 method = ((MonoMethodInflated *) method)->declaring;
10411 count = mono_method_signature (method)->generic_param_count;
10412 if (count != mono_array_length (types))
10413 return NULL;
10415 type_argv = g_new0 (MonoType *, count);
10416 for (i = 0; i < count; i++) {
10417 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
10418 type_argv [i] = mono_reflection_type_get_handle (garg);
10420 ginst = mono_metadata_get_generic_inst (count, type_argv);
10421 g_free (type_argv);
10423 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
10424 tmp_context.method_inst = ginst;
10426 inflated = mono_class_inflate_generic_method (method, &tmp_context);
10427 imethod = (MonoMethodInflated *) inflated;
10429 /*FIXME but I think this is no longer necessary*/
10430 if (method->klass->image->dynamic) {
10431 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10433 * This table maps metadata structures representing inflated methods/fields
10434 * to the reflection objects representing their generic definitions.
10436 mono_loader_lock ();
10437 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
10438 mono_loader_unlock ();
10441 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
10444 #ifndef DISABLE_REFLECTION_EMIT
10446 static MonoMethod *
10447 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
10449 MonoMethodInflated *imethod;
10450 MonoGenericContext *context;
10451 int i;
10454 * With generic code sharing the klass might not be inflated.
10455 * This can happen because classes inflated with their own
10456 * type arguments are "normalized" to the uninflated class.
10458 if (!klass->generic_class)
10459 return method;
10461 context = mono_class_get_context (klass);
10463 if (klass->method.count) {
10464 /* Find the already created inflated method */
10465 for (i = 0; i < klass->method.count; ++i) {
10466 g_assert (klass->methods [i]->is_inflated);
10467 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
10468 break;
10470 g_assert (i < klass->method.count);
10471 imethod = (MonoMethodInflated*)klass->methods [i];
10472 } else {
10473 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
10476 if (method->is_generic && method->klass->image->dynamic) {
10477 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10479 mono_loader_lock ();
10480 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
10481 mono_loader_unlock ();
10483 return (MonoMethod *) imethod;
10486 static MonoMethod *
10487 inflate_method (MonoReflectionType *type, MonoObject *obj)
10489 MonoMethod *method;
10490 MonoClass *gklass;
10492 MonoClass *type_class = mono_object_class (type);
10494 if (is_sre_generic_instance (type_class)) {
10495 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
10496 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
10497 } else if (is_sre_type_builder (type_class)) {
10498 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10499 } else if (type->type) {
10500 gklass = mono_class_from_mono_type (type->type);
10501 gklass = mono_class_get_generic_type_definition (gklass);
10502 } else {
10503 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
10506 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
10507 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
10508 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
10509 else
10510 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
10511 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
10512 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
10513 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
10514 method = ((MonoReflectionMethod *) obj)->method;
10515 else {
10516 method = NULL; /* prevent compiler warning */
10517 g_error ("can't handle type %s", obj->vtable->klass->name);
10520 return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
10523 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
10524 void
10525 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
10526 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
10527 MonoArray *events)
10529 MonoGenericClass *gclass;
10530 MonoDynamicGenericClass *dgclass;
10531 MonoClass *klass, *gklass;
10532 MonoType *gtype;
10533 int i;
10535 MONO_ARCH_SAVE_REGS;
10537 gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
10538 klass = mono_class_from_mono_type (gtype);
10539 g_assert (gtype->type == MONO_TYPE_GENERICINST);
10540 gclass = gtype->data.generic_class;
10542 if (!gclass->is_dynamic)
10543 return;
10545 dgclass = (MonoDynamicGenericClass *) gclass;
10547 if (dgclass->initialized)
10548 return;
10550 gklass = gclass->container_class;
10551 mono_class_init (gklass);
10553 dgclass->count_methods = methods ? mono_array_length (methods) : 0;
10554 dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
10555 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
10557 dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
10558 dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
10559 dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
10560 dgclass->field_objects = g_new0 (MonoObject*, dgclass->count_fields);
10561 dgclass->field_generic_types = g_new0 (MonoType*, dgclass->count_fields);
10563 for (i = 0; i < dgclass->count_methods; i++) {
10564 MonoObject *obj = mono_array_get (methods, gpointer, i);
10566 dgclass->methods [i] = inflate_method ((MonoReflectionType*)type, obj);
10569 for (i = 0; i < dgclass->count_ctors; i++) {
10570 MonoObject *obj = mono_array_get (ctors, gpointer, i);
10572 dgclass->ctors [i] = inflate_method ((MonoReflectionType*)type, obj);
10575 for (i = 0; i < dgclass->count_fields; i++) {
10576 MonoObject *obj = mono_array_get (fields, gpointer, i);
10577 MonoClassField *field, *inflated_field = NULL;
10579 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
10580 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
10581 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
10582 field = ((MonoReflectionField *) obj)->field;
10583 else {
10584 field = NULL; /* prevent compiler warning */
10585 g_assert_not_reached ();
10588 dgclass->fields [i] = *field;
10589 dgclass->fields [i].parent = klass;
10590 dgclass->fields [i].type = mono_class_inflate_generic_type (
10591 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
10592 dgclass->field_generic_types [i] = field->type;
10593 MOVING_GC_REGISTER (&dgclass->field_objects [i]);
10594 dgclass->field_objects [i] = obj;
10596 if (inflated_field) {
10597 g_free (inflated_field);
10598 } else {
10599 dgclass->fields [i].name = g_strdup (dgclass->fields [i].name);
10603 dgclass->initialized = TRUE;
10606 static void
10607 fix_partial_generic_class (MonoClass *klass)
10609 MonoClass *gklass = klass->generic_class->container_class;
10610 MonoDynamicGenericClass *dgclass;
10611 int i;
10613 if (klass->wastypebuilder)
10614 return;
10616 dgclass = (MonoDynamicGenericClass *) klass->generic_class;
10618 if (!dgclass->initialized)
10619 return;
10621 if (klass->method.count != gklass->method.count) {
10622 klass->method.count = gklass->method.count;
10623 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
10625 for (i = 0; i < klass->method.count; i++) {
10626 klass->methods [i] = mono_class_inflate_generic_method_full (
10627 gklass->methods [i], klass, mono_class_get_context (klass));
10631 if (klass->interface_count && klass->interface_count != gklass->interface_count) {
10632 klass->interface_count = gklass->interface_count;
10633 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
10634 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10636 for (i = 0; i < gklass->interface_count; ++i) {
10637 MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
10638 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
10639 mono_metadata_free_type (iface_type);
10641 ensure_runtime_vtable (klass->interfaces [i]);
10643 klass->interfaces_inited = 1;
10646 if (klass->field.count != gklass->field.count) {
10647 klass->field.count = gklass->field.count;
10648 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
10650 for (i = 0; i < klass->field.count; i++) {
10651 klass->fields [i] = gklass->fields [i];
10652 klass->fields [i].parent = klass;
10653 klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
10657 /*We can only finish with this klass once it's parent has as well*/
10658 if (gklass->wastypebuilder)
10659 klass->wastypebuilder = TRUE;
10660 return;
10663 static void
10664 ensure_generic_class_runtime_vtable (MonoClass *klass)
10666 MonoClass *gklass = klass->generic_class->container_class;
10668 ensure_runtime_vtable (gklass);
10670 fix_partial_generic_class (klass);
10673 static void
10674 ensure_runtime_vtable (MonoClass *klass)
10676 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10677 int i, num, j;
10679 if (!klass->image->dynamic || (!tb && !klass->generic_class) || klass->wastypebuilder)
10680 return;
10681 if (klass->parent)
10682 ensure_runtime_vtable (klass->parent);
10684 if (tb) {
10685 num = tb->ctors? mono_array_length (tb->ctors): 0;
10686 num += tb->num_methods;
10687 klass->method.count = num;
10688 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
10689 num = tb->ctors? mono_array_length (tb->ctors): 0;
10690 for (i = 0; i < num; ++i)
10691 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
10692 num = tb->num_methods;
10693 j = i;
10694 for (i = 0; i < num; ++i)
10695 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
10697 if (tb->interfaces) {
10698 klass->interface_count = mono_array_length (tb->interfaces);
10699 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
10700 for (i = 0; i < klass->interface_count; ++i) {
10701 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
10702 klass->interfaces [i] = mono_class_from_mono_type (iface);
10703 ensure_runtime_vtable (klass->interfaces [i]);
10705 klass->interfaces_inited = 1;
10707 } else if (klass->generic_class){
10708 ensure_generic_class_runtime_vtable (klass);
10711 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
10712 for (i = 0; i < klass->method.count; ++i)
10713 klass->methods [i]->slot = i;
10715 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10716 mono_class_setup_interface_offsets (klass);
10717 mono_class_setup_interface_id (klass);
10721 * The generic vtable is needed even if image->run is not set since some
10722 * runtime code like ves_icall_Type_GetMethodsByName depends on
10723 * method->slot being defined.
10727 * tb->methods could not be freed since it is used for determining
10728 * overrides during dynamic vtable construction.
10732 static MonoMethod*
10733 mono_reflection_method_get_handle (MonoObject *method)
10735 MonoClass *class = mono_object_class (method);
10736 if (is_sr_mono_method (class) || is_sr_mono_generic_method (class)) {
10737 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
10738 return sr_method->method;
10740 if (is_sre_method_builder (class)) {
10741 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
10742 return mb->mhandle;
10744 if (is_sre_method_on_tb_inst (class)) {
10745 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
10746 MonoMethod *result;
10747 /*FIXME move this to a proper method and unify with resolve_object*/
10748 if (m->method_args) {
10749 result = mono_reflection_method_on_tb_inst_get_handle (m);
10750 } else {
10751 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
10752 MonoClass *inflated_klass = mono_class_from_mono_type (type);
10753 MonoMethod *mono_method;
10755 if (is_sre_method_builder (mono_object_class (m->mb)))
10756 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
10757 else if (is_sr_mono_method (mono_object_class (m->mb)))
10758 mono_method = ((MonoReflectionMethod *)m->mb)->method;
10759 else
10760 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)));
10762 result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
10764 return result;
10767 g_error ("Can't handle methods of type %s:%s", class->name_space, class->name);
10768 return NULL;
10771 void
10772 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
10774 MonoReflectionTypeBuilder *tb;
10775 int i, onum;
10777 *overrides = NULL;
10778 *num_overrides = 0;
10780 g_assert (klass->image->dynamic);
10782 if (!mono_class_get_ref_info (klass))
10783 return;
10785 g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
10787 tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
10789 onum = 0;
10790 if (tb->methods) {
10791 for (i = 0; i < tb->num_methods; ++i) {
10792 MonoReflectionMethodBuilder *mb =
10793 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10794 if (mb->override_method)
10795 onum ++;
10799 if (onum) {
10800 *overrides = g_new0 (MonoMethod*, onum * 2);
10802 onum = 0;
10803 for (i = 0; i < tb->num_methods; ++i) {
10804 MonoReflectionMethodBuilder *mb =
10805 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10806 if (mb->override_method) {
10807 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject *)mb->override_method);
10808 (*overrides) [onum * 2 + 1] = mb->mhandle;
10810 g_assert (mb->mhandle);
10812 onum ++;
10817 *num_overrides = onum;
10820 static void
10821 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
10823 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10824 MonoReflectionFieldBuilder *fb;
10825 MonoClassField *field;
10826 MonoImage *image = klass->image;
10827 const char *p, *p2;
10828 int i;
10829 guint32 len, idx, real_size = 0;
10831 klass->field.count = tb->num_fields;
10832 klass->field.first = 0;
10834 mono_error_init (error);
10836 if (tb->class_size) {
10837 g_assert ((tb->packing_size & 0xfffffff0) == 0);
10838 klass->packing_size = tb->packing_size;
10839 real_size = klass->instance_size + tb->class_size;
10842 if (!klass->field.count) {
10843 klass->instance_size = MAX (klass->instance_size, real_size);
10844 return;
10847 klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
10848 mono_class_alloc_ext (klass);
10849 klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
10851 This is, guess what, a hack.
10852 The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
10853 On the static path no field class is resolved, only types are built. This is the right thing to do
10854 but we suck.
10855 Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
10857 klass->size_inited = 1;
10859 for (i = 0; i < klass->field.count; ++i) {
10860 fb = mono_array_get (tb->fields, gpointer, i);
10861 field = &klass->fields [i];
10862 field->name = mono_string_to_utf8_image (image, fb->name, error);
10863 if (!mono_error_ok (error))
10864 return;
10865 if (fb->attrs) {
10866 field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10867 field->type->attrs = fb->attrs;
10868 } else {
10869 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10871 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
10872 klass->ext->field_def_values [i].data = mono_array_addr (fb->rva_data, char, 0);
10873 if (fb->offset != -1)
10874 field->offset = fb->offset;
10875 field->parent = klass;
10876 fb->handle = field;
10877 mono_save_custom_attrs (klass->image, field, fb->cattrs);
10879 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10880 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
10882 if (fb->def_value) {
10883 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
10884 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
10885 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
10886 /* Copy the data from the blob since it might get realloc-ed */
10887 p = assembly->blob.data + idx;
10888 len = mono_metadata_decode_blob_size (p, &p2);
10889 len += p2 - p;
10890 klass->ext->field_def_values [i].data = mono_image_alloc (image, len);
10891 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
10895 klass->instance_size = MAX (klass->instance_size, real_size);
10896 mono_class_layout_fields (klass);
10899 static void
10900 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
10902 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10903 MonoReflectionPropertyBuilder *pb;
10904 MonoImage *image = klass->image;
10905 MonoProperty *properties;
10906 int i;
10908 mono_error_init (error);
10910 if (!klass->ext)
10911 klass->ext = image_g_new0 (image, MonoClassExt, 1);
10913 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
10914 klass->ext->property.first = 0;
10916 properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
10917 klass->ext->properties = properties;
10918 for (i = 0; i < klass->ext->property.count; ++i) {
10919 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
10920 properties [i].parent = klass;
10921 properties [i].attrs = pb->attrs;
10922 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
10923 if (!mono_error_ok (error))
10924 return;
10925 if (pb->get_method)
10926 properties [i].get = pb->get_method->mhandle;
10927 if (pb->set_method)
10928 properties [i].set = pb->set_method->mhandle;
10930 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
10934 MonoReflectionEvent *
10935 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
10937 MonoEvent *event = g_new0 (MonoEvent, 1);
10938 MonoClass *klass;
10940 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10942 event->parent = klass;
10943 event->attrs = eb->attrs;
10944 event->name = mono_string_to_utf8 (eb->name);
10945 if (eb->add_method)
10946 event->add = eb->add_method->mhandle;
10947 if (eb->remove_method)
10948 event->remove = eb->remove_method->mhandle;
10949 if (eb->raise_method)
10950 event->raise = eb->raise_method->mhandle;
10952 #ifndef MONO_SMALL_CONFIG
10953 if (eb->other_methods) {
10954 int j;
10955 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
10956 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
10957 MonoReflectionMethodBuilder *mb =
10958 mono_array_get (eb->other_methods,
10959 MonoReflectionMethodBuilder*, j);
10960 event->other [j] = mb->mhandle;
10963 #endif
10965 return mono_event_get_object (mono_object_domain (tb), klass, event);
10968 static void
10969 typebuilder_setup_events (MonoClass *klass, MonoError *error)
10971 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10972 MonoReflectionEventBuilder *eb;
10973 MonoImage *image = klass->image;
10974 MonoEvent *events;
10975 int i;
10977 mono_error_init (error);
10979 if (!klass->ext)
10980 klass->ext = image_g_new0 (image, MonoClassExt, 1);
10982 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
10983 klass->ext->event.first = 0;
10985 events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
10986 klass->ext->events = events;
10987 for (i = 0; i < klass->ext->event.count; ++i) {
10988 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
10989 events [i].parent = klass;
10990 events [i].attrs = eb->attrs;
10991 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
10992 if (!mono_error_ok (error))
10993 return;
10994 if (eb->add_method)
10995 events [i].add = eb->add_method->mhandle;
10996 if (eb->remove_method)
10997 events [i].remove = eb->remove_method->mhandle;
10998 if (eb->raise_method)
10999 events [i].raise = eb->raise_method->mhandle;
11001 #ifndef MONO_SMALL_CONFIG
11002 if (eb->other_methods) {
11003 int j;
11004 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
11005 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11006 MonoReflectionMethodBuilder *mb =
11007 mono_array_get (eb->other_methods,
11008 MonoReflectionMethodBuilder*, j);
11009 events [i].other [j] = mb->mhandle;
11012 #endif
11013 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
11017 static gboolean
11018 remove_instantiations_of_and_ensure_contents (gpointer key,
11019 gpointer value,
11020 gpointer user_data)
11022 MonoType *type = (MonoType*)key;
11023 MonoClass *klass = (MonoClass*)user_data;
11025 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
11026 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
11027 return TRUE;
11028 } else
11029 return FALSE;
11032 static void
11033 check_array_for_usertypes (MonoArray *arr)
11035 int i;
11037 if (!arr)
11038 return;
11040 for (i = 0; i < mono_array_length (arr); ++i)
11041 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i);
11044 MonoReflectionType*
11045 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11047 MonoError error;
11048 MonoClass *klass;
11049 MonoDomain* domain;
11050 MonoReflectionType* res;
11051 int i, j;
11053 MONO_ARCH_SAVE_REGS;
11055 domain = mono_object_domain (tb);
11056 klass = mono_class_from_mono_type (tb->type.type);
11059 * Check for user defined Type subclasses.
11061 RESOLVE_TYPE (tb->parent);
11062 check_array_for_usertypes (tb->interfaces);
11063 if (tb->fields) {
11064 for (i = 0; i < mono_array_length (tb->fields); ++i) {
11065 MonoReflectionFieldBuilder *fb = mono_array_get (tb->fields, gpointer, i);
11066 if (fb) {
11067 RESOLVE_TYPE (fb->type);
11068 check_array_for_usertypes (fb->modreq);
11069 check_array_for_usertypes (fb->modopt);
11070 if (fb->marshal_info && fb->marshal_info->marshaltyperef)
11071 RESOLVE_TYPE (fb->marshal_info->marshaltyperef);
11075 if (tb->methods) {
11076 for (i = 0; i < mono_array_length (tb->methods); ++i) {
11077 MonoReflectionMethodBuilder *mb = mono_array_get (tb->methods, gpointer, i);
11078 if (mb) {
11079 RESOLVE_TYPE (mb->rtype);
11080 check_array_for_usertypes (mb->return_modreq);
11081 check_array_for_usertypes (mb->return_modopt);
11082 check_array_for_usertypes (mb->parameters);
11083 if (mb->param_modreq)
11084 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11085 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11086 if (mb->param_modopt)
11087 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11088 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11092 if (tb->ctors) {
11093 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
11094 MonoReflectionCtorBuilder *mb = mono_array_get (tb->ctors, gpointer, i);
11095 if (mb) {
11096 check_array_for_usertypes (mb->parameters);
11097 if (mb->param_modreq)
11098 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11099 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11100 if (mb->param_modopt)
11101 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11102 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11107 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
11110 * we need to lock the domain because the lock will be taken inside
11111 * So, we need to keep the locking order correct.
11113 mono_loader_lock ();
11114 mono_domain_lock (domain);
11115 if (klass->wastypebuilder) {
11116 mono_domain_unlock (domain);
11117 mono_loader_unlock ();
11118 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11121 * Fields to set in klass:
11122 * the various flags: delegate/unicode/contextbound etc.
11124 klass->flags = tb->attrs;
11125 klass->has_cctor = 1;
11126 klass->has_finalize = 1;
11128 /* fool mono_class_setup_parent */
11129 klass->supertypes = NULL;
11130 mono_class_setup_parent (klass, klass->parent);
11131 mono_class_setup_mono_type (klass);
11133 #if 0
11134 if (!((MonoDynamicImage*)klass->image)->run) {
11135 if (klass->generic_container) {
11136 /* FIXME: The code below can't handle generic classes */
11137 klass->wastypebuilder = TRUE;
11138 mono_loader_unlock ();
11139 mono_domain_unlock (domain);
11140 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11143 #endif
11145 /* enums are done right away */
11146 if (!klass->enumtype)
11147 ensure_runtime_vtable (klass);
11149 if (tb->subtypes) {
11150 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
11151 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
11152 mono_class_alloc_ext (klass);
11153 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)));
11157 klass->nested_classes_inited = TRUE;
11159 /* fields and object layout */
11160 if (klass->parent) {
11161 if (!klass->parent->size_inited)
11162 mono_class_init (klass->parent);
11163 klass->instance_size = klass->parent->instance_size;
11164 klass->sizes.class_size = 0;
11165 klass->min_align = klass->parent->min_align;
11166 /* if the type has no fields we won't call the field_setup
11167 * routine which sets up klass->has_references.
11169 klass->has_references |= klass->parent->has_references;
11170 } else {
11171 klass->instance_size = sizeof (MonoObject);
11172 klass->min_align = 1;
11175 /* FIXME: handle packing_size and instance_size */
11176 typebuilder_setup_fields (klass, &error);
11177 if (!mono_error_ok (&error))
11178 goto failure;
11179 typebuilder_setup_properties (klass, &error);
11180 if (!mono_error_ok (&error))
11181 goto failure;
11183 typebuilder_setup_events (klass, &error);
11184 if (!mono_error_ok (&error))
11185 goto failure;
11187 klass->wastypebuilder = TRUE;
11190 * If we are a generic TypeBuilder, there might be instantiations in the type cache
11191 * which have type System.Reflection.MonoGenericClass, but after the type is created,
11192 * we want to return normal System.MonoType objects, so clear these out from the cache.
11194 * Together with this we must ensure the contents of all instances to match the created type.
11196 if (domain->type_hash && klass->generic_container)
11197 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
11199 mono_domain_unlock (domain);
11200 mono_loader_unlock ();
11202 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
11203 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11204 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
11207 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11208 g_assert (res != (MonoReflectionType*)tb);
11210 return res;
11212 failure:
11213 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11214 klass->wastypebuilder = TRUE;
11215 mono_domain_unlock (domain);
11216 mono_loader_unlock ();
11217 mono_error_raise_exception (&error);
11218 return NULL;
11221 void
11222 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
11224 MonoGenericParamFull *param;
11225 MonoImage *image;
11226 MonoClass *pklass;
11228 MONO_ARCH_SAVE_REGS;
11230 param = g_new0 (MonoGenericParamFull, 1);
11232 if (gparam->mbuilder) {
11233 if (!gparam->mbuilder->generic_container) {
11234 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
11235 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11236 gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11237 gparam->mbuilder->generic_container->is_method = TRUE;
11239 * Cannot set owner.method, since the MonoMethod is not created yet.
11240 * Set the image field instead, so type_in_image () works.
11242 gparam->mbuilder->generic_container->image = klass->image;
11244 param->param.owner = gparam->mbuilder->generic_container;
11245 } else if (gparam->tbuilder) {
11246 if (!gparam->tbuilder->generic_container) {
11247 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
11248 gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11249 gparam->tbuilder->generic_container->owner.klass = klass;
11251 param->param.owner = gparam->tbuilder->generic_container;
11254 param->info.name = mono_string_to_utf8 (gparam->name);
11255 param->param.num = gparam->index;
11257 image = &gparam->tbuilder->module->dynamic_image->image;
11258 pklass = mono_class_from_generic_parameter ((MonoGenericParam *) param, image, gparam->mbuilder != NULL);
11260 gparam->type.type = &pklass->byval_arg;
11262 mono_class_set_ref_info (pklass, gparam);
11263 mono_image_lock (image);
11264 image->reflection_info_unregister_classes = g_slist_prepend (image->reflection_info_unregister_classes, pklass);
11265 mono_image_unlock (image);
11268 MonoArray *
11269 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
11271 MonoReflectionModuleBuilder *module = sig->module;
11272 MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
11273 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11274 guint32 buflen, i;
11275 MonoArray *result;
11276 SigBuffer buf;
11278 check_array_for_usertypes (sig->arguments);
11280 sigbuffer_init (&buf, 32);
11282 sigbuffer_add_value (&buf, 0x07);
11283 sigbuffer_add_value (&buf, na);
11284 if (assembly != NULL){
11285 for (i = 0; i < na; ++i) {
11286 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11287 encode_reflection_type (assembly, type, &buf);
11291 buflen = buf.p - buf.buf;
11292 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11293 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11294 sigbuffer_free (&buf);
11296 return result;
11299 MonoArray *
11300 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
11302 MonoDynamicImage *assembly = sig->module->dynamic_image;
11303 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11304 guint32 buflen, i;
11305 MonoArray *result;
11306 SigBuffer buf;
11308 check_array_for_usertypes (sig->arguments);
11310 sigbuffer_init (&buf, 32);
11312 sigbuffer_add_value (&buf, 0x06);
11313 for (i = 0; i < na; ++i) {
11314 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11315 encode_reflection_type (assembly, type, &buf);
11318 buflen = buf.p - buf.buf;
11319 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11320 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11321 sigbuffer_free (&buf);
11323 return result;
11326 void
11327 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
11329 ReflectionMethodBuilder rmb;
11330 MonoMethodSignature *sig;
11331 MonoClass *klass;
11332 GSList *l;
11333 int i;
11335 sig = dynamic_method_to_signature (mb);
11337 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
11340 * Resolve references.
11343 * Every second entry in the refs array is reserved for storing handle_class,
11344 * which is needed by the ldtoken implementation in the JIT.
11346 rmb.nrefs = mb->nrefs;
11347 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
11348 for (i = 0; i < mb->nrefs; i += 2) {
11349 MonoClass *handle_class;
11350 gpointer ref;
11351 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
11353 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11354 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11356 * The referenced DynamicMethod should already be created by the managed
11357 * code, except in the case of circular references. In that case, we store
11358 * method in the refs array, and fix it up later when the referenced
11359 * DynamicMethod is created.
11361 if (method->mhandle) {
11362 ref = method->mhandle;
11363 } else {
11364 /* FIXME: GC object stored in unmanaged memory */
11365 ref = method;
11367 /* FIXME: GC object stored in unmanaged memory */
11368 method->referenced_by = g_slist_append (method->referenced_by, mb);
11370 handle_class = mono_defaults.methodhandle_class;
11371 } else {
11372 MonoException *ex = NULL;
11373 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
11374 if (!ref)
11375 ex = mono_get_exception_type_load (NULL, NULL);
11376 else if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
11377 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
11379 if (ex) {
11380 g_free (rmb.refs);
11381 mono_raise_exception (ex);
11382 return;
11386 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
11387 rmb.refs [i + 1] = handle_class;
11390 klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
11392 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11394 /* Fix up refs entries pointing at us */
11395 for (l = mb->referenced_by; l; l = l->next) {
11396 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
11397 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
11398 gpointer *data;
11400 g_assert (method->mhandle);
11402 data = (gpointer*)wrapper->method_data;
11403 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
11404 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
11405 data [i + 1] = mb->mhandle;
11408 g_slist_free (mb->referenced_by);
11410 g_free (rmb.refs);
11412 /* ilgen is no longer needed */
11413 mb->ilgen = NULL;
11416 #endif /* DISABLE_REFLECTION_EMIT */
11418 void
11419 mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod *mb)
11421 g_assert (mb);
11423 if (mb->mhandle)
11424 mono_runtime_free_method (
11425 mono_object_get_domain ((MonoObject*)mb), mb->mhandle);
11430 * mono_reflection_is_valid_dynamic_token:
11432 * Returns TRUE if token is valid.
11435 gboolean
11436 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
11438 return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
11441 #ifndef DISABLE_REFLECTION_EMIT
11444 * mono_reflection_lookup_dynamic_token:
11446 * Finish the Builder object pointed to by TOKEN and return the corresponding
11447 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
11448 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
11449 * mapping table.
11451 * LOCKING: Take the loader lock
11453 gpointer
11454 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
11456 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
11457 MonoObject *obj;
11458 MonoClass *klass;
11460 mono_loader_lock ();
11461 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
11462 mono_loader_unlock ();
11463 if (!obj) {
11464 if (valid_token)
11465 g_error ("Could not find required dynamic token 0x%08x", token);
11466 else
11467 return NULL;
11470 if (!handle_class)
11471 handle_class = &klass;
11472 return resolve_object (image, obj, handle_class, context);
11476 * ensure_complete_type:
11478 * Ensure that KLASS is completed if it is a dynamic type, or references
11479 * dynamic types.
11481 static void
11482 ensure_complete_type (MonoClass *klass)
11484 if (klass->image->dynamic && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
11485 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11487 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11489 // Asserting here could break a lot of code
11490 //g_assert (klass->wastypebuilder);
11493 if (klass->generic_class) {
11494 MonoGenericInst *inst = klass->generic_class->context.class_inst;
11495 int i;
11497 for (i = 0; i < inst->type_argc; ++i) {
11498 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
11503 static gpointer
11504 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
11506 gpointer result = NULL;
11508 if (strcmp (obj->vtable->klass->name, "String") == 0) {
11509 result = mono_string_intern ((MonoString*)obj);
11510 *handle_class = mono_defaults.string_class;
11511 g_assert (result);
11512 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
11513 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11514 MonoClass *mc = mono_class_from_mono_type (type);
11515 if (!mono_class_init (mc))
11516 mono_raise_exception (mono_class_get_exception_for_failure (mc));
11518 if (context) {
11519 MonoType *inflated = mono_class_inflate_generic_type (type, context);
11520 result = mono_class_from_mono_type (inflated);
11521 mono_metadata_free_type (inflated);
11522 } else {
11523 result = mono_class_from_mono_type (type);
11525 *handle_class = mono_defaults.typehandle_class;
11526 g_assert (result);
11527 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
11528 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
11529 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
11530 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
11531 result = ((MonoReflectionMethod*)obj)->method;
11532 if (context)
11533 result = mono_class_inflate_generic_method (result, context);
11534 *handle_class = mono_defaults.methodhandle_class;
11535 g_assert (result);
11536 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
11537 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
11538 result = mb->mhandle;
11539 if (!result) {
11540 /* Type is not yet created */
11541 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
11543 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11546 * Hopefully this has been filled in by calling CreateType() on the
11547 * TypeBuilder.
11550 * TODO: This won't work if the application finishes another
11551 * TypeBuilder instance instead of this one.
11553 result = mb->mhandle;
11555 if (context)
11556 result = mono_class_inflate_generic_method (result, context);
11557 *handle_class = mono_defaults.methodhandle_class;
11558 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
11559 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
11561 result = cb->mhandle;
11562 if (!result) {
11563 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
11565 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11566 result = cb->mhandle;
11568 if (context)
11569 result = mono_class_inflate_generic_method (result, context);
11570 *handle_class = mono_defaults.methodhandle_class;
11571 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
11572 MonoClassField *field = ((MonoReflectionField*)obj)->field;
11574 ensure_complete_type (field->parent);
11575 if (context) {
11576 MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
11577 MonoClass *class = mono_class_from_mono_type (inflated);
11578 MonoClassField *inflated_field;
11579 gpointer iter = NULL;
11580 mono_metadata_free_type (inflated);
11581 while ((inflated_field = mono_class_get_fields (class, &iter))) {
11582 if (!strcmp (field->name, inflated_field->name))
11583 break;
11585 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
11586 result = inflated_field;
11587 } else {
11588 result = field;
11590 *handle_class = mono_defaults.fieldhandle_class;
11591 g_assert (result);
11592 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
11593 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
11594 result = fb->handle;
11596 if (!result) {
11597 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
11599 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11600 result = fb->handle;
11603 if (fb->handle && fb->handle->parent->generic_container) {
11604 MonoClass *klass = fb->handle->parent;
11605 MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
11606 MonoClass *inflated = mono_class_from_mono_type (type);
11608 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
11609 g_assert (result);
11610 mono_metadata_free_type (type);
11612 *handle_class = mono_defaults.fieldhandle_class;
11613 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
11614 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
11615 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
11616 MonoClass *klass;
11618 klass = type->data.klass;
11619 if (klass->wastypebuilder) {
11620 /* Already created */
11621 result = klass;
11623 else {
11624 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11625 result = type->data.klass;
11626 g_assert (result);
11628 *handle_class = mono_defaults.typehandle_class;
11629 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
11630 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
11631 MonoMethodSignature *sig;
11632 int nargs, i;
11634 if (helper->arguments)
11635 nargs = mono_array_length (helper->arguments);
11636 else
11637 nargs = 0;
11639 sig = mono_metadata_signature_alloc (image, nargs);
11640 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
11641 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
11643 if (helper->unmanaged_call_conv) { /* unmanaged */
11644 sig->call_convention = helper->unmanaged_call_conv - 1;
11645 sig->pinvoke = TRUE;
11646 } else if (helper->call_conv & 0x02) {
11647 sig->call_convention = MONO_CALL_VARARG;
11648 } else {
11649 sig->call_convention = MONO_CALL_DEFAULT;
11652 sig->param_count = nargs;
11653 /* TODO: Copy type ? */
11654 sig->ret = helper->return_type->type;
11655 for (i = 0; i < nargs; ++i)
11656 sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
11658 result = sig;
11659 *handle_class = NULL;
11660 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11661 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11662 /* Already created by the managed code */
11663 g_assert (method->mhandle);
11664 result = method->mhandle;
11665 *handle_class = mono_defaults.methodhandle_class;
11666 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
11667 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11668 type = mono_class_inflate_generic_type (type, context);
11669 result = mono_class_from_mono_type (type);
11670 *handle_class = mono_defaults.typehandle_class;
11671 g_assert (result);
11672 mono_metadata_free_type (type);
11673 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
11674 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11675 type = mono_class_inflate_generic_type (type, context);
11676 result = mono_class_from_mono_type (type);
11677 *handle_class = mono_defaults.typehandle_class;
11678 g_assert (result);
11679 mono_metadata_free_type (type);
11680 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
11681 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
11682 MonoClass *inflated;
11683 MonoType *type;
11684 MonoClassField *field;
11686 if (is_sre_field_builder (mono_object_class (f->fb)))
11687 field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
11688 else if (is_sr_mono_field (mono_object_class (f->fb)))
11689 field = ((MonoReflectionField*)f->fb)->field;
11690 else
11691 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)));
11693 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
11694 inflated = mono_class_from_mono_type (type);
11696 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
11697 ensure_complete_type (field->parent);
11698 g_assert (result);
11699 mono_metadata_free_type (type);
11700 *handle_class = mono_defaults.fieldhandle_class;
11701 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
11702 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
11703 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
11704 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11705 MonoMethod *method;
11707 if (is_sre_ctor_builder (mono_object_class (c->cb)))
11708 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
11709 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
11710 method = ((MonoReflectionMethod *)c->cb)->method;
11711 else
11712 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)));
11714 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
11715 *handle_class = mono_defaults.methodhandle_class;
11716 mono_metadata_free_type (type);
11717 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
11718 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
11719 if (m->method_args) {
11720 result = mono_reflection_method_on_tb_inst_get_handle (m);
11721 if (context)
11722 result = mono_class_inflate_generic_method (result, context);
11723 } else {
11724 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
11725 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11726 MonoMethod *method;
11728 if (is_sre_method_builder (mono_object_class (m->mb)))
11729 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
11730 else if (is_sr_mono_method (mono_object_class (m->mb)))
11731 method = ((MonoReflectionMethod *)m->mb)->method;
11732 else
11733 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)));
11735 result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
11736 mono_metadata_free_type (type);
11738 *handle_class = mono_defaults.methodhandle_class;
11739 } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
11740 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
11741 MonoType *mtype;
11742 MonoClass *klass;
11743 MonoMethod *method;
11744 gpointer iter;
11745 char *name;
11747 mtype = mono_reflection_type_get_handle (m->parent);
11748 klass = mono_class_from_mono_type (mtype);
11750 /* Find the method */
11752 name = mono_string_to_utf8 (m->name);
11753 iter = NULL;
11754 while ((method = mono_class_get_methods (klass, &iter))) {
11755 if (!strcmp (method->name, name))
11756 break;
11758 g_free (name);
11760 // FIXME:
11761 g_assert (method);
11762 // FIXME: Check parameters/return value etc. match
11764 result = method;
11765 *handle_class = mono_defaults.methodhandle_class;
11766 } else if (is_sre_array (mono_object_get_class(obj)) ||
11767 is_sre_byref (mono_object_get_class(obj)) ||
11768 is_sre_pointer (mono_object_get_class(obj))) {
11769 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
11770 MonoType *type = mono_reflection_type_get_handle (ref_type);
11771 result = mono_class_from_mono_type (type);
11772 *handle_class = mono_defaults.typehandle_class;
11773 } else {
11774 g_print ("%s\n", obj->vtable->klass->name);
11775 g_assert_not_reached ();
11777 return result;
11780 #else /* DISABLE_REFLECTION_EMIT */
11782 MonoArray*
11783 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
11785 g_assert_not_reached ();
11786 return NULL;
11789 void
11790 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
11792 g_assert_not_reached ();
11795 void
11796 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11798 g_assert_not_reached ();
11801 void
11802 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
11804 g_assert_not_reached ();
11807 void
11808 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11810 g_assert_not_reached ();
11813 void
11814 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
11816 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
11819 void
11820 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
11822 g_assert_not_reached ();
11825 void
11826 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
11828 g_assert_not_reached ();
11831 MonoReflectionModule *
11832 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
11834 g_assert_not_reached ();
11835 return NULL;
11838 guint32
11839 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
11841 g_assert_not_reached ();
11842 return 0;
11845 guint32
11846 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
11848 g_assert_not_reached ();
11849 return 0;
11852 guint32
11853 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
11854 gboolean create_methodspec, gboolean register_token)
11856 g_assert_not_reached ();
11857 return 0;
11860 void
11861 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
11865 void
11866 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
11867 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
11868 MonoArray *events)
11870 g_assert_not_reached ();
11873 void
11874 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
11876 *overrides = NULL;
11877 *num_overrides = 0;
11880 MonoReflectionEvent *
11881 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11883 g_assert_not_reached ();
11884 return NULL;
11887 MonoReflectionType*
11888 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11890 g_assert_not_reached ();
11891 return NULL;
11894 void
11895 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
11897 g_assert_not_reached ();
11900 MonoArray *
11901 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
11903 g_assert_not_reached ();
11904 return NULL;
11907 MonoArray *
11908 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
11910 g_assert_not_reached ();
11911 return NULL;
11914 void
11915 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
11919 gpointer
11920 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
11922 return NULL;
11925 MonoType*
11926 mono_reflection_type_get_handle (MonoReflectionType* ref)
11928 if (!ref)
11929 return NULL;
11930 return ref->type;
11933 #endif /* DISABLE_REFLECTION_EMIT */
11935 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
11936 const static guint32 declsec_flags_map[] = {
11937 0x00000000, /* empty */
11938 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
11939 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
11940 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
11941 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
11942 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
11943 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
11944 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
11945 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
11946 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
11947 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
11948 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
11949 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
11950 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
11951 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
11952 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
11953 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
11954 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
11955 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
11959 * Returns flags that includes all available security action associated to the handle.
11960 * @token: metadata token (either for a class or a method)
11961 * @image: image where resides the metadata.
11963 static guint32
11964 mono_declsec_get_flags (MonoImage *image, guint32 token)
11966 int index = mono_metadata_declsec_from_index (image, token);
11967 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
11968 guint32 result = 0;
11969 guint32 action;
11970 int i;
11972 /* HasSecurity can be present for other, not specially encoded, attributes,
11973 e.g. SuppressUnmanagedCodeSecurityAttribute */
11974 if (index < 0)
11975 return 0;
11977 for (i = index; i < t->rows; i++) {
11978 guint32 cols [MONO_DECL_SECURITY_SIZE];
11980 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
11981 if (cols [MONO_DECL_SECURITY_PARENT] != token)
11982 break;
11984 action = cols [MONO_DECL_SECURITY_ACTION];
11985 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
11986 result |= declsec_flags_map [action];
11987 } else {
11988 g_assert_not_reached ();
11991 return result;
11995 * Get the security actions (in the form of flags) associated with the specified method.
11997 * @method: The method for which we want the declarative security flags.
11998 * Return the declarative security flags for the method (only).
12000 * Note: To keep MonoMethod size down we do not cache the declarative security flags
12001 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
12003 guint32
12004 mono_declsec_flags_from_method (MonoMethod *method)
12006 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12007 /* FIXME: No cache (for the moment) */
12008 guint32 idx = mono_method_get_index (method);
12009 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12010 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12011 return mono_declsec_get_flags (method->klass->image, idx);
12013 return 0;
12017 * Get the security actions (in the form of flags) associated with the specified class.
12019 * @klass: The class for which we want the declarative security flags.
12020 * Return the declarative security flags for the class.
12022 * Note: We cache the flags inside the MonoClass structure as this will get
12023 * called very often (at least for each method).
12025 guint32
12026 mono_declsec_flags_from_class (MonoClass *klass)
12028 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
12029 if (!klass->ext || !klass->ext->declsec_flags) {
12030 guint32 idx;
12032 idx = mono_metadata_token_index (klass->type_token);
12033 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12034 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12035 mono_loader_lock ();
12036 mono_class_alloc_ext (klass);
12037 mono_loader_unlock ();
12038 /* we cache the flags on classes */
12039 klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
12041 return klass->ext->declsec_flags;
12043 return 0;
12047 * Get the security actions (in the form of flags) associated with the specified assembly.
12049 * @assembly: The assembly for which we want the declarative security flags.
12050 * Return the declarative security flags for the assembly.
12052 guint32
12053 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
12055 guint32 idx = 1; /* there is only one assembly */
12056 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12057 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12058 return mono_declsec_get_flags (assembly->image, idx);
12063 * Fill actions for the specific index (which may either be an encoded class token or
12064 * an encoded method token) from the metadata image.
12065 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
12067 static MonoBoolean
12068 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
12069 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12071 MonoBoolean result = FALSE;
12072 MonoTableInfo *t;
12073 guint32 cols [MONO_DECL_SECURITY_SIZE];
12074 int index = mono_metadata_declsec_from_index (image, token);
12075 int i;
12077 t = &image->tables [MONO_TABLE_DECLSECURITY];
12078 for (i = index; i < t->rows; i++) {
12079 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12081 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12082 return result;
12084 /* if present only replace (class) permissions with method permissions */
12085 /* if empty accept either class or method permissions */
12086 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
12087 if (!actions->demand.blob) {
12088 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12089 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12090 actions->demand.blob = (char*) (blob + 2);
12091 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
12092 result = TRUE;
12094 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
12095 if (!actions->noncasdemand.blob) {
12096 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12097 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12098 actions->noncasdemand.blob = (char*) (blob + 2);
12099 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
12100 result = TRUE;
12102 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
12103 if (!actions->demandchoice.blob) {
12104 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12105 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12106 actions->demandchoice.blob = (char*) (blob + 2);
12107 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
12108 result = TRUE;
12113 return result;
12116 static MonoBoolean
12117 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
12118 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12120 guint32 idx = mono_metadata_token_index (klass->type_token);
12121 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12122 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12123 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
12126 static MonoBoolean
12127 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
12128 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12130 guint32 idx = mono_method_get_index (method);
12131 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12132 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12133 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
12137 * Collect all actions (that requires to generate code in mini) assigned for
12138 * the specified method.
12139 * Note: Don't use the content of actions if the function return FALSE.
12141 MonoBoolean
12142 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
12144 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
12145 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
12146 MonoBoolean result = FALSE;
12147 guint32 flags;
12149 /* quick exit if no declarative security is present in the metadata */
12150 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12151 return FALSE;
12153 /* we want the original as the wrapper is "free" of the security informations */
12154 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12155 method = mono_marshal_method_from_wrapper (method);
12156 if (!method)
12157 return FALSE;
12160 /* First we look for method-level attributes */
12161 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12162 mono_class_init (method->klass);
12163 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12165 result = mono_declsec_get_method_demands_params (method, demands,
12166 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12169 /* Here we use (or create) the class declarative cache to look for demands */
12170 flags = mono_declsec_flags_from_class (method->klass);
12171 if (flags & mask) {
12172 if (!result) {
12173 mono_class_init (method->klass);
12174 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12176 result |= mono_declsec_get_class_demands_params (method->klass, demands,
12177 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12180 /* The boolean return value is used as a shortcut in case nothing needs to
12181 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
12182 return result;
12187 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
12189 * Note: Don't use the content of actions if the function return FALSE.
12191 MonoBoolean
12192 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
12194 MonoBoolean result = FALSE;
12195 guint32 flags;
12197 /* quick exit if no declarative security is present in the metadata */
12198 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12199 return FALSE;
12201 /* we want the original as the wrapper is "free" of the security informations */
12202 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12203 method = mono_marshal_method_from_wrapper (method);
12204 if (!method)
12205 return FALSE;
12208 /* results are independant - zeroize both */
12209 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
12210 memset (klass, 0, sizeof (MonoDeclSecurityActions));
12212 /* First we look for method-level attributes */
12213 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12214 mono_class_init (method->klass);
12216 result = mono_declsec_get_method_demands_params (method, cmethod,
12217 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12220 /* Here we use (or create) the class declarative cache to look for demands */
12221 flags = mono_declsec_flags_from_class (method->klass);
12222 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
12223 mono_class_init (method->klass);
12225 result |= mono_declsec_get_class_demands_params (method->klass, klass,
12226 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12229 return result;
12233 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12235 * @klass The inherited class - this is the class that provides the security check (attributes)
12236 * @demans
12237 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
12239 * Note: Don't use the content of actions if the function return FALSE.
12241 MonoBoolean
12242 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
12244 MonoBoolean result = FALSE;
12245 guint32 flags;
12247 /* quick exit if no declarative security is present in the metadata */
12248 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12249 return FALSE;
12251 /* Here we use (or create) the class declarative cache to look for demands */
12252 flags = mono_declsec_flags_from_class (klass);
12253 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
12254 mono_class_init (klass);
12255 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12257 result |= mono_declsec_get_class_demands_params (klass, demands,
12258 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12261 return result;
12265 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12267 * Note: Don't use the content of actions if the function return FALSE.
12269 MonoBoolean
12270 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
12272 /* quick exit if no declarative security is present in the metadata */
12273 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12274 return FALSE;
12276 /* we want the original as the wrapper is "free" of the security informations */
12277 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12278 method = mono_marshal_method_from_wrapper (method);
12279 if (!method)
12280 return FALSE;
12283 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12284 mono_class_init (method->klass);
12285 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12287 return mono_declsec_get_method_demands_params (method, demands,
12288 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12290 return FALSE;
12294 static MonoBoolean
12295 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
12297 guint32 cols [MONO_DECL_SECURITY_SIZE];
12298 MonoTableInfo *t;
12299 int i;
12301 int index = mono_metadata_declsec_from_index (image, token);
12302 if (index == -1)
12303 return FALSE;
12305 t = &image->tables [MONO_TABLE_DECLSECURITY];
12306 for (i = index; i < t->rows; i++) {
12307 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12309 /* shortcut - index are ordered */
12310 if (token != cols [MONO_DECL_SECURITY_PARENT])
12311 return FALSE;
12313 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
12314 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12315 entry->blob = (char*) (metadata + 2);
12316 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
12317 return TRUE;
12321 return FALSE;
12324 MonoBoolean
12325 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
12327 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12328 guint32 idx = mono_method_get_index (method);
12329 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12330 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12331 return get_declsec_action (method->klass->image, idx, action, entry);
12333 return FALSE;
12336 MonoBoolean
12337 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
12339 /* use cache */
12340 guint32 flags = mono_declsec_flags_from_class (klass);
12341 if (declsec_flags_map [action] & flags) {
12342 guint32 idx = mono_metadata_token_index (klass->type_token);
12343 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12344 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12345 return get_declsec_action (klass->image, idx, action, entry);
12347 return FALSE;
12350 MonoBoolean
12351 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
12353 guint32 idx = 1; /* there is only one assembly */
12354 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12355 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12357 return get_declsec_action (assembly->image, idx, action, entry);
12360 gboolean
12361 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
12363 MonoObject *res, *exc;
12364 void *params [1];
12365 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
12366 static MonoMethod *method = NULL;
12368 if (!System_Reflection_Emit_TypeBuilder) {
12369 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
12370 g_assert (System_Reflection_Emit_TypeBuilder);
12372 if (method == NULL) {
12373 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
12374 g_assert (method);
12378 * The result of mono_type_get_object () might be a System.MonoType but we
12379 * need a TypeBuilder so use mono_class_get_ref_info (klass).
12381 g_assert (mono_class_get_ref_info (klass));
12382 g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
12384 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
12386 res = mono_runtime_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc);
12387 if (exc)
12388 return FALSE;
12389 else
12390 return *(MonoBoolean*)mono_object_unbox (res);