2009-06-11 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mono / metadata / reflection.c
blob1e8fe1234bbcb83da788b143b1ea2386a1298b87
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>
41 #if HAVE_SGEN_GC
42 static void* reflection_info_desc = NULL;
43 #define MOVING_GC_REGISTER(addr) do { \
44 if (!reflection_info_desc) { \
45 gsize bmap = 1; \
46 reflection_info_desc = mono_gc_make_descr_from_bitmap (&bmap, 1); \
47 } \
48 mono_gc_register_root ((char*)(addr), sizeof (gpointer), reflection_info_desc); \
49 } while (0)
50 #else
51 #define MOVING_GC_REGISTER(addr)
52 #endif
54 typedef struct {
55 char *p;
56 char *buf;
57 char *end;
58 } SigBuffer;
60 #define TEXT_OFFSET 512
61 #define CLI_H_SIZE 136
62 #define FILE_ALIGN 512
63 #define VIRT_ALIGN 8192
64 #define START_TEXT_RVA 0x00002000
66 typedef struct {
67 MonoReflectionILGen *ilgen;
68 MonoReflectionType *rtype;
69 MonoArray *parameters;
70 MonoArray *generic_params;
71 MonoGenericContainer *generic_container;
72 MonoArray *pinfo;
73 MonoArray *opt_types;
74 guint32 attrs;
75 guint32 iattrs;
76 guint32 call_conv;
77 guint32 *table_idx; /* note: it's a pointer */
78 MonoArray *code;
79 MonoObject *type;
80 MonoString *name;
81 MonoBoolean init_locals;
82 MonoBoolean skip_visibility;
83 MonoArray *return_modreq;
84 MonoArray *return_modopt;
85 MonoArray *param_modreq;
86 MonoArray *param_modopt;
87 MonoArray *permissions;
88 MonoMethod *mhandle;
89 guint32 nrefs;
90 gpointer *refs;
91 /* for PInvoke */
92 int charset, extra_flags, native_cc;
93 MonoString *dll, *dllentry;
94 } ReflectionMethodBuilder;
96 typedef struct {
97 guint32 owner;
98 MonoReflectionGenericParam *gparam;
99 } GenericParamTableEntry;
101 const unsigned char table_sizes [MONO_TABLE_NUM] = {
102 MONO_MODULE_SIZE,
103 MONO_TYPEREF_SIZE,
104 MONO_TYPEDEF_SIZE,
106 MONO_FIELD_SIZE,
108 MONO_METHOD_SIZE,
110 MONO_PARAM_SIZE,
111 MONO_INTERFACEIMPL_SIZE,
112 MONO_MEMBERREF_SIZE, /* 0x0A */
113 MONO_CONSTANT_SIZE,
114 MONO_CUSTOM_ATTR_SIZE,
115 MONO_FIELD_MARSHAL_SIZE,
116 MONO_DECL_SECURITY_SIZE,
117 MONO_CLASS_LAYOUT_SIZE,
118 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
119 MONO_STAND_ALONE_SIGNATURE_SIZE,
120 MONO_EVENT_MAP_SIZE,
122 MONO_EVENT_SIZE,
123 MONO_PROPERTY_MAP_SIZE,
125 MONO_PROPERTY_SIZE,
126 MONO_METHOD_SEMA_SIZE,
127 MONO_METHODIMPL_SIZE,
128 MONO_MODULEREF_SIZE, /* 0x1A */
129 MONO_TYPESPEC_SIZE,
130 MONO_IMPLMAP_SIZE,
131 MONO_FIELD_RVA_SIZE,
134 MONO_ASSEMBLY_SIZE, /* 0x20 */
135 MONO_ASSEMBLY_PROCESSOR_SIZE,
136 MONO_ASSEMBLYOS_SIZE,
137 MONO_ASSEMBLYREF_SIZE,
138 MONO_ASSEMBLYREFPROC_SIZE,
139 MONO_ASSEMBLYREFOS_SIZE,
140 MONO_FILE_SIZE,
141 MONO_EXP_TYPE_SIZE,
142 MONO_MANIFEST_SIZE,
143 MONO_NESTED_CLASS_SIZE,
145 MONO_GENERICPARAM_SIZE, /* 0x2A */
146 MONO_METHODSPEC_SIZE,
147 MONO_GENPARCONSTRAINT_SIZE
151 #ifndef DISABLE_REFLECTION_EMIT
152 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
153 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec);
154 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
155 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
156 static void ensure_runtime_vtable (MonoClass *klass);
157 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
158 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method);
159 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
160 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
161 #endif
163 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
164 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
165 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
166 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
167 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
168 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
169 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
170 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
171 static void encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
172 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
173 static MonoObject *mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob);
174 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t);
175 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
177 void
178 mono_reflection_init (void)
182 static void
183 sigbuffer_init (SigBuffer *buf, int size)
185 buf->buf = g_malloc (size);
186 buf->p = buf->buf;
187 buf->end = buf->buf + size;
190 static void
191 sigbuffer_make_room (SigBuffer *buf, int size)
193 if (buf->end - buf->p < size) {
194 int new_size = buf->end - buf->buf + size + 32;
195 char *p = g_realloc (buf->buf, new_size);
196 size = buf->p - buf->buf;
197 buf->buf = p;
198 buf->p = p + size;
199 buf->end = buf->buf + new_size;
203 static void
204 sigbuffer_add_value (SigBuffer *buf, guint32 val)
206 sigbuffer_make_room (buf, 6);
207 mono_metadata_encode_value (val, buf->p, &buf->p);
210 static void
211 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
213 sigbuffer_make_room (buf, 1);
214 buf->p [0] = val;
215 buf->p++;
218 static void
219 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
221 sigbuffer_make_room (buf, size);
222 memcpy (buf->p, p, size);
223 buf->p += size;
226 static void
227 sigbuffer_free (SigBuffer *buf)
229 g_free (buf->buf);
232 #ifndef DISABLE_REFLECTION_EMIT
234 * mp_g_alloc:
236 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
237 * from the C heap.
239 static gpointer
240 image_g_malloc (MonoImage *image, guint size)
242 if (image)
243 return mono_image_alloc (image, size);
244 else
245 return g_malloc (size);
247 #endif /* !DISABLE_REFLECTION_EMIT */
250 * image_g_alloc0:
252 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
253 * from the C heap.
255 static gpointer
256 image_g_malloc0 (MonoImage *image, guint size)
258 if (image)
259 return mono_image_alloc0 (image, size);
260 else
261 return g_malloc0 (size);
264 #ifndef DISABLE_REFLECTION_EMIT
265 static char*
266 image_strdup (MonoImage *image, const char *s)
268 if (image)
269 return mono_image_strdup (image, s);
270 else
271 return g_strdup (s);
273 #endif
275 #define image_g_new(image,struct_type, n_structs) \
276 ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
278 #define image_g_new0(image,struct_type, n_structs) \
279 ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
282 static void
283 alloc_table (MonoDynamicTable *table, guint nrows)
285 table->rows = nrows;
286 g_assert (table->columns);
287 if (nrows + 1 >= table->alloc_rows) {
288 while (nrows + 1 >= table->alloc_rows) {
289 if (table->alloc_rows == 0)
290 table->alloc_rows = 16;
291 else
292 table->alloc_rows *= 2;
295 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
299 static void
300 make_room_in_stream (MonoDynamicStream *stream, int size)
302 if (size <= stream->alloc_size)
303 return;
305 while (stream->alloc_size <= size) {
306 if (stream->alloc_size < 4096)
307 stream->alloc_size = 4096;
308 else
309 stream->alloc_size *= 2;
312 stream->data = g_realloc (stream->data, stream->alloc_size);
315 static guint32
316 string_heap_insert (MonoDynamicStream *sh, const char *str)
318 guint32 idx;
319 guint32 len;
320 gpointer oldkey, oldval;
322 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
323 return GPOINTER_TO_UINT (oldval);
325 len = strlen (str) + 1;
326 idx = sh->index;
328 make_room_in_stream (sh, idx + len);
331 * We strdup the string even if we already copy them in sh->data
332 * so that the string pointers in the hash remain valid even if
333 * we need to realloc sh->data. We may want to avoid that later.
335 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
336 memcpy (sh->data + idx, str, len);
337 sh->index += len;
338 return idx;
341 static guint32
342 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
344 char *name = mono_string_to_utf8 (str);
345 guint32 idx;
346 idx = string_heap_insert (sh, name);
347 g_free (name);
348 return idx;
351 #ifndef DISABLE_REFLECTION_EMIT
352 static void
353 string_heap_init (MonoDynamicStream *sh)
355 sh->index = 0;
356 sh->alloc_size = 4096;
357 sh->data = g_malloc (4096);
358 sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
359 string_heap_insert (sh, "");
361 #endif
363 static guint32
364 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
366 guint32 idx;
368 make_room_in_stream (stream, stream->index + len);
369 memcpy (stream->data + stream->index, data, len);
370 idx = stream->index;
371 stream->index += len;
373 * align index? Not without adding an additional param that controls it since
374 * we may store a blob value in pieces.
376 return idx;
379 static guint32
380 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
382 guint32 idx;
384 make_room_in_stream (stream, stream->index + len);
385 memset (stream->data + stream->index, 0, len);
386 idx = stream->index;
387 stream->index += len;
388 return idx;
391 static void
392 stream_data_align (MonoDynamicStream *stream)
394 char buf [4] = {0};
395 guint32 count = stream->index % 4;
397 /* we assume the stream data will be aligned */
398 if (count)
399 mono_image_add_stream_data (stream, buf, 4 - count);
402 #ifndef DISABLE_REFLECTION_EMIT
403 static int
404 mono_blob_entry_hash (const char* str)
406 guint len, h;
407 const char *end;
408 len = mono_metadata_decode_blob_size (str, &str);
409 if (len > 0) {
410 end = str + len;
411 h = *str;
412 for (str += 1; str < end; str++)
413 h = (h << 5) - h + *str;
414 return h;
415 } else {
416 return 0;
420 static gboolean
421 mono_blob_entry_equal (const char *str1, const char *str2) {
422 int len, len2;
423 const char *end1;
424 const char *end2;
425 len = mono_metadata_decode_blob_size (str1, &end1);
426 len2 = mono_metadata_decode_blob_size (str2, &end2);
427 if (len != len2)
428 return 0;
429 return memcmp (end1, end2, len) == 0;
431 #endif
432 static guint32
433 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
435 guint32 idx;
436 char *copy;
437 gpointer oldkey, oldval;
439 copy = g_malloc (s1+s2);
440 memcpy (copy, b1, s1);
441 memcpy (copy + s1, b2, s2);
442 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
443 g_free (copy);
444 idx = GPOINTER_TO_UINT (oldval);
445 } else {
446 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
447 mono_image_add_stream_data (&assembly->blob, b2, s2);
448 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
450 return idx;
453 static guint32
454 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
456 char blob_size [8];
457 char *b = blob_size;
458 guint32 size = buf->p - buf->buf;
459 /* store length */
460 g_assert (size <= (buf->end - buf->buf));
461 mono_metadata_encode_value (size, b, &b);
462 return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
466 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
467 * dest may be misaligned.
469 static void
470 swap_with_size (char *dest, const char* val, int len, int nelem) {
471 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
472 int elem;
474 for (elem = 0; elem < nelem; ++elem) {
475 switch (len) {
476 case 1:
477 *dest = *val;
478 break;
479 case 2:
480 dest [0] = val [1];
481 dest [1] = val [0];
482 break;
483 case 4:
484 dest [0] = val [3];
485 dest [1] = val [2];
486 dest [2] = val [1];
487 dest [3] = val [0];
488 break;
489 case 8:
490 dest [0] = val [7];
491 dest [1] = val [6];
492 dest [2] = val [5];
493 dest [3] = val [4];
494 dest [4] = val [3];
495 dest [5] = val [2];
496 dest [6] = val [1];
497 dest [7] = val [0];
498 break;
499 default:
500 g_assert_not_reached ();
502 dest += len;
503 val += len;
505 #else
506 memcpy (dest, val, len * nelem);
507 #endif
510 static guint32
511 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
513 char blob_size [64];
514 char *b = blob_size;
515 guint32 idx = 0, len;
517 len = str->length * 2;
518 mono_metadata_encode_value (len, b, &b);
519 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
521 char *swapped = g_malloc (2 * mono_string_length (str));
522 const char *p = (const char*)mono_string_chars (str);
524 swap_with_size (swapped, p, 2, mono_string_length (str));
525 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
526 g_free (swapped);
528 #else
529 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
530 #endif
531 return idx;
534 #ifndef DISABLE_REFLECTION_EMIT
535 static MonoClass *
536 default_class_from_mono_type (MonoType *type)
538 switch (type->type) {
539 case MONO_TYPE_OBJECT:
540 return mono_defaults.object_class;
541 case MONO_TYPE_VOID:
542 return mono_defaults.void_class;
543 case MONO_TYPE_BOOLEAN:
544 return mono_defaults.boolean_class;
545 case MONO_TYPE_CHAR:
546 return mono_defaults.char_class;
547 case MONO_TYPE_I1:
548 return mono_defaults.sbyte_class;
549 case MONO_TYPE_U1:
550 return mono_defaults.byte_class;
551 case MONO_TYPE_I2:
552 return mono_defaults.int16_class;
553 case MONO_TYPE_U2:
554 return mono_defaults.uint16_class;
555 case MONO_TYPE_I4:
556 return mono_defaults.int32_class;
557 case MONO_TYPE_U4:
558 return mono_defaults.uint32_class;
559 case MONO_TYPE_I:
560 return mono_defaults.int_class;
561 case MONO_TYPE_U:
562 return mono_defaults.uint_class;
563 case MONO_TYPE_I8:
564 return mono_defaults.int64_class;
565 case MONO_TYPE_U8:
566 return mono_defaults.uint64_class;
567 case MONO_TYPE_R4:
568 return mono_defaults.single_class;
569 case MONO_TYPE_R8:
570 return mono_defaults.double_class;
571 case MONO_TYPE_STRING:
572 return mono_defaults.string_class;
573 default:
574 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
575 g_assert_not_reached ();
578 return NULL;
580 #endif
582 static void
583 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
585 int i;
586 MonoGenericInst *class_inst;
587 MonoClass *klass;
589 g_assert (gclass);
591 class_inst = gclass->context.class_inst;
593 sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
594 klass = gclass->container_class;
595 sigbuffer_add_value (buf, klass->byval_arg.type);
596 sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
598 sigbuffer_add_value (buf, class_inst->type_argc);
599 for (i = 0; i < class_inst->type_argc; ++i)
600 encode_type (assembly, class_inst->type_argv [i], buf);
604 static void
605 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
607 if (!type) {
608 g_assert_not_reached ();
609 return;
612 if (type->byref)
613 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
615 switch (type->type){
616 case MONO_TYPE_VOID:
617 case MONO_TYPE_BOOLEAN:
618 case MONO_TYPE_CHAR:
619 case MONO_TYPE_I1:
620 case MONO_TYPE_U1:
621 case MONO_TYPE_I2:
622 case MONO_TYPE_U2:
623 case MONO_TYPE_I4:
624 case MONO_TYPE_U4:
625 case MONO_TYPE_I8:
626 case MONO_TYPE_U8:
627 case MONO_TYPE_R4:
628 case MONO_TYPE_R8:
629 case MONO_TYPE_I:
630 case MONO_TYPE_U:
631 case MONO_TYPE_STRING:
632 case MONO_TYPE_OBJECT:
633 case MONO_TYPE_TYPEDBYREF:
634 sigbuffer_add_value (buf, type->type);
635 break;
636 case MONO_TYPE_PTR:
637 sigbuffer_add_value (buf, type->type);
638 encode_type (assembly, type->data.type, buf);
639 break;
640 case MONO_TYPE_SZARRAY:
641 sigbuffer_add_value (buf, type->type);
642 encode_type (assembly, &type->data.klass->byval_arg, buf);
643 break;
644 case MONO_TYPE_VALUETYPE:
645 case MONO_TYPE_CLASS: {
646 MonoClass *k = mono_class_from_mono_type (type);
648 if (k->generic_container) {
649 MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
650 encode_generic_class (assembly, gclass, buf);
651 } else {
653 * Make sure we use the correct type.
655 sigbuffer_add_value (buf, k->byval_arg.type);
657 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
658 * otherwise two typerefs could point to the same type, leading to
659 * verification errors.
661 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
663 break;
665 case MONO_TYPE_ARRAY:
666 sigbuffer_add_value (buf, type->type);
667 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
668 sigbuffer_add_value (buf, type->data.array->rank);
669 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
670 sigbuffer_add_value (buf, 0);
671 break;
672 case MONO_TYPE_GENERICINST:
673 encode_generic_class (assembly, type->data.generic_class, buf);
674 break;
675 case MONO_TYPE_VAR:
676 case MONO_TYPE_MVAR:
677 sigbuffer_add_value (buf, type->type);
678 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
679 break;
680 default:
681 g_error ("need to encode type %x", type->type);
685 static void
686 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
688 if (!type) {
689 sigbuffer_add_value (buf, MONO_TYPE_VOID);
690 return;
693 if (type->type ||
694 ((type = mono_reflection_type_get_underlying_system_type (type)) && type->type)) {
695 encode_type (assembly, type->type, buf);
696 return;
699 g_assert_not_reached ();
703 static void
704 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
706 int i;
708 if (modreq) {
709 for (i = 0; i < mono_array_length (modreq); ++i) {
710 MonoReflectionType *mod = mono_type_array_get (modreq, i);
711 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
712 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod->type));
715 if (modopt) {
716 for (i = 0; i < mono_array_length (modopt); ++i) {
717 MonoReflectionType *mod = mono_type_array_get (modopt, i);
718 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
719 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod->type));
724 #ifndef DISABLE_REFLECTION_EMIT
725 static guint32
726 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
728 SigBuffer buf;
729 int i;
730 guint32 nparams = sig->param_count;
731 guint32 idx;
733 if (!assembly->save)
734 return 0;
736 sigbuffer_init (&buf, 32);
738 * FIXME: vararg, explicit_this, differenc call_conv values...
740 idx = sig->call_convention;
741 if (sig->hasthis)
742 idx |= 0x20; /* hasthis */
743 if (sig->generic_param_count)
744 idx |= 0x10; /* generic */
745 sigbuffer_add_byte (&buf, idx);
746 if (sig->generic_param_count)
747 sigbuffer_add_value (&buf, sig->generic_param_count);
748 sigbuffer_add_value (&buf, nparams);
749 encode_type (assembly, sig->ret, &buf);
750 for (i = 0; i < nparams; ++i) {
751 if (i == sig->sentinelpos)
752 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
753 encode_type (assembly, sig->params [i], &buf);
755 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
756 sigbuffer_free (&buf);
757 return idx;
759 #endif
761 static guint32
762 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
765 * FIXME: reuse code from method_encode_signature().
767 SigBuffer buf;
768 int i;
769 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
770 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
771 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
772 guint32 idx;
774 sigbuffer_init (&buf, 32);
775 /* LAMESPEC: all the call conv spec is foobared */
776 idx = mb->call_conv & 0x60; /* has-this, explicit-this */
777 if (mb->call_conv & 2)
778 idx |= 0x5; /* vararg */
779 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
780 idx |= 0x20; /* hasthis */
781 if (ngparams)
782 idx |= 0x10; /* generic */
783 sigbuffer_add_byte (&buf, idx);
784 if (ngparams)
785 sigbuffer_add_value (&buf, ngparams);
786 sigbuffer_add_value (&buf, nparams + notypes);
787 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
788 encode_reflection_type (assembly, mb->rtype, &buf);
789 for (i = 0; i < nparams; ++i) {
790 MonoArray *modreq = NULL;
791 MonoArray *modopt = NULL;
792 MonoReflectionType *pt;
794 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
795 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
796 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
797 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
798 encode_custom_modifiers (assembly, modreq, modopt, &buf);
799 pt = mono_type_array_get (mb->parameters, i);
800 encode_reflection_type (assembly, pt, &buf);
802 if (notypes)
803 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
804 for (i = 0; i < notypes; ++i) {
805 MonoReflectionType *pt;
807 pt = mono_type_array_get (mb->opt_types, i);
808 encode_reflection_type (assembly, pt, &buf);
811 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
812 sigbuffer_free (&buf);
813 return idx;
816 static guint32
817 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
819 MonoDynamicTable *table;
820 guint32 *values;
821 guint32 idx, sig_idx;
822 guint nl = mono_array_length (ilgen->locals);
823 SigBuffer buf;
824 int i;
826 sigbuffer_init (&buf, 32);
827 sigbuffer_add_value (&buf, 0x07);
828 sigbuffer_add_value (&buf, nl);
829 for (i = 0; i < nl; ++i) {
830 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
832 if (lb->is_pinned)
833 sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
835 encode_reflection_type (assembly, monotype_cast (lb->type), &buf);
837 sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
838 sigbuffer_free (&buf);
840 if (assembly->standalonesig_cache == NULL)
841 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
842 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
843 if (idx)
844 return idx;
846 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
847 idx = table->next_idx ++;
848 table->rows ++;
849 alloc_table (table, table->rows);
850 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
852 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
854 g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
856 return idx;
859 static guint32
860 method_count_clauses (MonoReflectionILGen *ilgen)
862 guint32 num_clauses = 0;
863 int i;
865 MonoILExceptionInfo *ex_info;
866 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
867 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
868 if (ex_info->handlers)
869 num_clauses += mono_array_length (ex_info->handlers);
870 else
871 num_clauses++;
874 return num_clauses;
877 #ifndef DISABLE_REFLECTION_EMIT
878 static MonoExceptionClause*
879 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
881 MonoExceptionClause *clauses;
882 MonoExceptionClause *clause;
883 MonoILExceptionInfo *ex_info;
884 MonoILExceptionBlock *ex_block;
885 guint32 finally_start;
886 int i, j, clause_index;;
888 clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
890 clause_index = 0;
891 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
892 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
893 finally_start = ex_info->start + ex_info->len;
894 if (!ex_info->handlers)
895 continue;
896 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
897 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
898 clause = &(clauses [clause_index]);
900 clause->flags = ex_block->type;
901 clause->try_offset = ex_info->start;
903 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
904 clause->try_len = finally_start - ex_info->start;
905 else
906 clause->try_len = ex_info->len;
907 clause->handler_offset = ex_block->start;
908 clause->handler_len = ex_block->len;
909 if (ex_block->extype) {
910 clause->data.catch_class = mono_class_from_mono_type (monotype_cast (ex_block->extype)->type);
911 } else {
912 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
913 clause->data.filter_offset = ex_block->filter_offset;
914 else
915 clause->data.filter_offset = 0;
917 finally_start = ex_block->start + ex_block->len;
919 clause_index ++;
923 return clauses;
925 #endif /* !DISABLE_REFLECTION_EMIT */
927 static guint32
928 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
930 char flags = 0;
931 guint32 idx;
932 guint32 code_size;
933 gint32 max_stack, i;
934 gint32 num_locals = 0;
935 gint32 num_exception = 0;
936 gint maybe_small;
937 guint32 fat_flags;
938 char fat_header [12];
939 guint32 int_value;
940 guint16 short_value;
941 guint32 local_sig = 0;
942 guint32 header_size = 12;
943 MonoArray *code;
945 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
946 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
947 return 0;
949 /*if (mb->name)
950 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
951 if (mb->ilgen) {
952 code = mb->ilgen->code;
953 code_size = mb->ilgen->code_len;
954 max_stack = mb->ilgen->max_stack;
955 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
956 if (mb->ilgen->ex_handlers)
957 num_exception = method_count_clauses (mb->ilgen);
958 } else {
959 code = mb->code;
960 if (code == NULL){
961 char *name = mono_string_to_utf8 (mb->name);
962 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
963 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
964 g_free (str);
965 g_free (name);
966 mono_raise_exception (exception);
969 code_size = mono_array_length (code);
970 max_stack = 8; /* we probably need to run a verifier on the code... */
973 stream_data_align (&assembly->code);
975 /* check for exceptions, maxstack, locals */
976 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
977 if (maybe_small) {
978 if (code_size < 64 && !(code_size & 1)) {
979 flags = (code_size << 2) | 0x2;
980 } else if (code_size < 32 && (code_size & 1)) {
981 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
982 } else {
983 goto fat_header;
985 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
986 /* add to the fixup todo list */
987 if (mb->ilgen && mb->ilgen->num_token_fixups)
988 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
989 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
990 return assembly->text_rva + idx;
992 fat_header:
993 if (num_locals)
994 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
996 * FIXME: need to set also the header size in fat_flags.
997 * (and more sects and init locals flags)
999 fat_flags = 0x03;
1000 if (num_exception)
1001 fat_flags |= METHOD_HEADER_MORE_SECTS;
1002 if (mb->init_locals)
1003 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1004 fat_header [0] = fat_flags;
1005 fat_header [1] = (header_size / 4 ) << 4;
1006 short_value = GUINT16_TO_LE (max_stack);
1007 memcpy (fat_header + 2, &short_value, 2);
1008 int_value = GUINT32_TO_LE (code_size);
1009 memcpy (fat_header + 4, &int_value, 4);
1010 int_value = GUINT32_TO_LE (local_sig);
1011 memcpy (fat_header + 8, &int_value, 4);
1012 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1013 /* add to the fixup todo list */
1014 if (mb->ilgen && mb->ilgen->num_token_fixups)
1015 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1017 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1018 if (num_exception) {
1019 unsigned char sheader [4];
1020 MonoILExceptionInfo * ex_info;
1021 MonoILExceptionBlock * ex_block;
1022 int j;
1024 stream_data_align (&assembly->code);
1025 /* always use fat format for now */
1026 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1027 num_exception *= 6 * sizeof (guint32);
1028 num_exception += 4; /* include the size of the header */
1029 sheader [1] = num_exception & 0xff;
1030 sheader [2] = (num_exception >> 8) & 0xff;
1031 sheader [3] = (num_exception >> 16) & 0xff;
1032 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1033 /* fat header, so we are already aligned */
1034 /* reverse order */
1035 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1036 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1037 if (ex_info->handlers) {
1038 int finally_start = ex_info->start + ex_info->len;
1039 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1040 guint32 val;
1041 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1042 /* the flags */
1043 val = GUINT32_TO_LE (ex_block->type);
1044 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1045 /* try offset */
1046 val = GUINT32_TO_LE (ex_info->start);
1047 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1048 /* need fault, too, probably */
1049 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1050 val = GUINT32_TO_LE (finally_start - ex_info->start);
1051 else
1052 val = GUINT32_TO_LE (ex_info->len);
1053 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1054 /* handler offset */
1055 val = GUINT32_TO_LE (ex_block->start);
1056 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1057 /* handler len */
1058 val = GUINT32_TO_LE (ex_block->len);
1059 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1060 finally_start = ex_block->start + ex_block->len;
1061 if (ex_block->extype) {
1062 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, monotype_cast (ex_block->extype)->type));
1063 } else {
1064 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1065 val = ex_block->filter_offset;
1066 else
1067 val = 0;
1069 val = GUINT32_TO_LE (val);
1070 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1071 /*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",
1072 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);*/
1074 } else {
1075 g_error ("No clauses for ex info block %d", i);
1079 return assembly->text_rva + idx;
1082 static guint32
1083 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1085 int i;
1086 MonoDynamicTable *table;
1087 guint32 *values;
1089 table = &assembly->tables [table_idx];
1091 g_assert (col < table->columns);
1093 values = table->values + table->columns;
1094 for (i = 1; i <= table->rows; ++i) {
1095 if (values [col] == token)
1096 return i;
1097 values += table->columns;
1099 return 0;
1103 * LOCKING: Acquires the loader lock.
1105 static MonoCustomAttrInfo*
1106 lookup_custom_attr (MonoImage *image, gpointer member)
1108 MonoCustomAttrInfo* res;
1110 res = mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1112 if (!res)
1113 return NULL;
1115 return g_memdup (res, sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (res->num_attrs - MONO_ZERO_LEN_ARRAY));
1118 static gboolean
1119 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1121 /* FIXME: Need to do more checks */
1122 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1123 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1125 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1126 return FALSE;
1129 return TRUE;
1132 static MonoCustomAttrInfo*
1133 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1135 int i, index, count, not_visible;
1136 MonoCustomAttrInfo *ainfo;
1137 MonoReflectionCustomAttr *cattr;
1139 if (!cattrs)
1140 return NULL;
1141 /* FIXME: check in assembly the Run flag is set */
1143 count = mono_array_length (cattrs);
1145 /* Skip nonpublic attributes since MS.NET seems to do the same */
1146 /* FIXME: This needs to be done more globally */
1147 not_visible = 0;
1148 for (i = 0; i < count; ++i) {
1149 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1150 if (!custom_attr_visible (image, cattr))
1151 not_visible ++;
1153 count -= not_visible;
1155 ainfo = image_g_malloc0 (alloc_img, sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
1157 ainfo->image = image;
1158 ainfo->num_attrs = count;
1159 ainfo->cached = alloc_img != NULL;
1160 index = 0;
1161 for (i = 0; i < count; ++i) {
1162 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1163 if (custom_attr_visible (image, cattr)) {
1164 unsigned char *saved = mono_image_alloc (image, mono_array_length (cattr->data));
1165 memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1166 ainfo->attrs [index].ctor = cattr->ctor->method;
1167 ainfo->attrs [index].data = saved;
1168 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1169 index ++;
1173 return ainfo;
1176 #ifndef DISABLE_REFLECTION_EMIT
1178 * LOCKING: Acquires the loader lock.
1180 static void
1181 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1183 MonoCustomAttrInfo *ainfo, *tmp;
1185 if (!cattrs || !mono_array_length (cattrs))
1186 return;
1188 ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1190 mono_loader_lock ();
1191 tmp = mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1192 if (tmp)
1193 mono_custom_attrs_free (tmp);
1194 mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1195 mono_loader_unlock ();
1198 #endif
1200 void
1201 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1203 if (!ainfo->cached)
1204 g_free (ainfo);
1208 * idx is the table index of the object
1209 * type is one of MONO_CUSTOM_ATTR_*
1211 static void
1212 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1214 MonoDynamicTable *table;
1215 MonoReflectionCustomAttr *cattr;
1216 guint32 *values;
1217 guint32 count, i, token;
1218 char blob_size [6];
1219 char *p = blob_size;
1221 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1222 if (!cattrs)
1223 return;
1224 count = mono_array_length (cattrs);
1225 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1226 table->rows += count;
1227 alloc_table (table, table->rows);
1228 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1229 idx <<= MONO_CUSTOM_ATTR_BITS;
1230 idx |= type;
1231 for (i = 0; i < count; ++i) {
1232 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1233 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1234 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE);
1235 type = mono_metadata_token_index (token);
1236 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1237 switch (mono_metadata_token_table (token)) {
1238 case MONO_TABLE_METHOD:
1239 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1240 break;
1241 case MONO_TABLE_MEMBERREF:
1242 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1243 break;
1244 default:
1245 g_warning ("got wrong token in custom attr");
1246 continue;
1248 values [MONO_CUSTOM_ATTR_TYPE] = type;
1249 p = blob_size;
1250 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1251 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1252 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1253 values += MONO_CUSTOM_ATTR_SIZE;
1254 ++table->next_idx;
1258 static void
1259 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1261 MonoDynamicTable *table;
1262 guint32 *values;
1263 guint32 count, i, idx;
1264 MonoReflectionPermissionSet *perm;
1266 if (!permissions)
1267 return;
1269 count = mono_array_length (permissions);
1270 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1271 table->rows += count;
1272 alloc_table (table, table->rows);
1274 for (i = 0; i < mono_array_length (permissions); ++i) {
1275 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1277 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1279 idx = mono_metadata_token_index (parent_token);
1280 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1281 switch (mono_metadata_token_table (parent_token)) {
1282 case MONO_TABLE_TYPEDEF:
1283 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1284 break;
1285 case MONO_TABLE_METHOD:
1286 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1287 break;
1288 case MONO_TABLE_ASSEMBLY:
1289 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1290 break;
1291 default:
1292 g_assert_not_reached ();
1295 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1296 values [MONO_DECL_SECURITY_PARENT] = idx;
1297 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1299 ++table->next_idx;
1304 * Fill in the MethodDef and ParamDef tables for a method.
1305 * This is used for both normal methods and constructors.
1307 static void
1308 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1310 MonoDynamicTable *table;
1311 guint32 *values;
1312 guint i, count;
1314 /* room in this table is already allocated */
1315 table = &assembly->tables [MONO_TABLE_METHOD];
1316 *mb->table_idx = table->next_idx ++;
1317 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1318 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1319 values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1320 values [MONO_METHOD_FLAGS] = mb->attrs;
1321 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1322 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1323 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1325 table = &assembly->tables [MONO_TABLE_PARAM];
1326 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1328 mono_image_add_decl_security (assembly,
1329 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1331 if (mb->pinfo) {
1332 MonoDynamicTable *mtable;
1333 guint32 *mvalues;
1335 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1336 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1338 count = 0;
1339 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1340 if (mono_array_get (mb->pinfo, gpointer, i))
1341 count++;
1343 table->rows += count;
1344 alloc_table (table, table->rows);
1345 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1346 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1347 MonoReflectionParamBuilder *pb;
1348 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1349 values [MONO_PARAM_FLAGS] = pb->attrs;
1350 values [MONO_PARAM_SEQUENCE] = i;
1351 if (pb->name != NULL) {
1352 values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1353 } else {
1354 values [MONO_PARAM_NAME] = 0;
1356 values += MONO_PARAM_SIZE;
1357 if (pb->marshal_info) {
1358 mtable->rows++;
1359 alloc_table (mtable, mtable->rows);
1360 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1361 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1362 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1364 pb->table_idx = table->next_idx++;
1365 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1366 guint32 field_type = 0;
1367 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1368 mtable->rows ++;
1369 alloc_table (mtable, mtable->rows);
1370 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1371 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1372 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1373 mvalues [MONO_CONSTANT_TYPE] = field_type;
1374 mvalues [MONO_CONSTANT_PADDING] = 0;
1381 static void
1382 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1384 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1386 rmb->ilgen = mb->ilgen;
1387 rmb->rtype = monotype_cast (mb->rtype);
1388 rmb->parameters = mb->parameters;
1389 rmb->generic_params = mb->generic_params;
1390 rmb->generic_container = mb->generic_container;
1391 rmb->opt_types = NULL;
1392 rmb->pinfo = mb->pinfo;
1393 rmb->attrs = mb->attrs;
1394 rmb->iattrs = mb->iattrs;
1395 rmb->call_conv = mb->call_conv;
1396 rmb->code = mb->code;
1397 rmb->type = mb->type;
1398 rmb->name = mb->name;
1399 rmb->table_idx = &mb->table_idx;
1400 rmb->init_locals = mb->init_locals;
1401 rmb->skip_visibility = FALSE;
1402 rmb->return_modreq = mb->return_modreq;
1403 rmb->return_modopt = mb->return_modopt;
1404 rmb->param_modreq = mb->param_modreq;
1405 rmb->param_modopt = mb->param_modopt;
1406 rmb->permissions = mb->permissions;
1407 rmb->mhandle = mb->mhandle;
1408 rmb->nrefs = 0;
1409 rmb->refs = NULL;
1411 if (mb->dll) {
1412 rmb->charset = mb->charset;
1413 rmb->extra_flags = mb->extra_flags;
1414 rmb->native_cc = mb->native_cc;
1415 rmb->dllentry = mb->dllentry;
1416 rmb->dll = mb->dll;
1420 static void
1421 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1423 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1425 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1427 rmb->ilgen = mb->ilgen;
1428 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1429 rmb->parameters = mb->parameters;
1430 rmb->generic_params = NULL;
1431 rmb->generic_container = NULL;
1432 rmb->opt_types = NULL;
1433 rmb->pinfo = mb->pinfo;
1434 rmb->attrs = mb->attrs;
1435 rmb->iattrs = mb->iattrs;
1436 rmb->call_conv = mb->call_conv;
1437 rmb->code = NULL;
1438 rmb->type = mb->type;
1439 rmb->name = mono_string_new (mono_domain_get (), name);
1440 rmb->table_idx = &mb->table_idx;
1441 rmb->init_locals = mb->init_locals;
1442 rmb->skip_visibility = FALSE;
1443 rmb->return_modreq = NULL;
1444 rmb->return_modopt = NULL;
1445 rmb->param_modreq = mb->param_modreq;
1446 rmb->param_modopt = mb->param_modopt;
1447 rmb->permissions = mb->permissions;
1448 rmb->mhandle = mb->mhandle;
1449 rmb->nrefs = 0;
1450 rmb->refs = NULL;
1453 #ifndef DISABLE_REFLECTION_EMIT
1454 static void
1455 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1457 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1459 rmb->ilgen = mb->ilgen;
1460 rmb->rtype = mb->rtype;
1461 rmb->parameters = mb->parameters;
1462 rmb->generic_params = NULL;
1463 rmb->generic_container = NULL;
1464 rmb->opt_types = NULL;
1465 rmb->pinfo = NULL;
1466 rmb->attrs = mb->attrs;
1467 rmb->iattrs = 0;
1468 rmb->call_conv = mb->call_conv;
1469 rmb->code = NULL;
1470 rmb->type = (MonoObject *) mb->owner;
1471 rmb->name = mb->name;
1472 rmb->table_idx = NULL;
1473 rmb->init_locals = mb->init_locals;
1474 rmb->skip_visibility = mb->skip_visibility;
1475 rmb->return_modreq = NULL;
1476 rmb->return_modopt = NULL;
1477 rmb->param_modreq = NULL;
1478 rmb->param_modopt = NULL;
1479 rmb->permissions = NULL;
1480 rmb->mhandle = mb->mhandle;
1481 rmb->nrefs = 0;
1482 rmb->refs = NULL;
1484 #endif
1486 static void
1487 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1489 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1490 MonoDynamicTable *table;
1491 guint32 *values;
1492 guint32 tok;
1494 if (!mb->override_method)
1495 return;
1497 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1498 table->rows ++;
1499 alloc_table (table, table->rows);
1500 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1501 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1502 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1504 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE, FALSE);
1505 switch (mono_metadata_token_table (tok)) {
1506 case MONO_TABLE_MEMBERREF:
1507 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1508 break;
1509 case MONO_TABLE_METHOD:
1510 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1511 break;
1512 default:
1513 g_assert_not_reached ();
1515 values [MONO_METHODIMPL_DECLARATION] = tok;
1518 static void
1519 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1521 MonoDynamicTable *table;
1522 guint32 *values;
1523 ReflectionMethodBuilder rmb;
1524 int i;
1526 reflection_methodbuilder_from_method_builder (&rmb, mb);
1528 mono_image_basic_method (&rmb, assembly);
1529 mb->table_idx = *rmb.table_idx;
1531 if (mb->dll) { /* It's a P/Invoke method */
1532 guint32 moduleref;
1533 /* map CharSet values to on-disk values */
1534 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1535 int extra_flags = mb->extra_flags;
1536 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1537 table->rows ++;
1538 alloc_table (table, table->rows);
1539 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1541 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1542 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1543 if (mb->dllentry)
1544 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1545 else
1546 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1547 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1548 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1549 table = &assembly->tables [MONO_TABLE_MODULEREF];
1550 table->rows ++;
1551 alloc_table (table, table->rows);
1552 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1553 values [MONO_IMPLMAP_SCOPE] = table->rows;
1557 if (mb->generic_params) {
1558 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1559 table->rows += mono_array_length (mb->generic_params);
1560 alloc_table (table, table->rows);
1561 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1562 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1564 mono_image_get_generic_param_info (
1565 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1571 static void
1572 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1574 ReflectionMethodBuilder rmb;
1576 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1578 mono_image_basic_method (&rmb, assembly);
1579 mb->table_idx = *rmb.table_idx;
1582 static char*
1583 type_get_fully_qualified_name (MonoType *type)
1585 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1588 static char*
1589 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1590 MonoClass *klass;
1591 MonoAssembly *ta;
1593 klass = mono_class_from_mono_type (type);
1594 if (!klass)
1595 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1596 ta = klass->image->assembly;
1597 if (ta->dynamic || (ta == ass)) {
1598 if (klass->generic_class || klass->generic_container)
1599 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1600 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1601 else
1602 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1605 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1608 #ifndef DISABLE_REFLECTION_EMIT
1609 static guint32
1610 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
1612 SigBuffer buf;
1613 guint32 idx, i;
1615 if (!assembly->save)
1616 return 0;
1618 sigbuffer_init (&buf, 32);
1620 sigbuffer_add_value (&buf, 0x06);
1621 /* encode custom attributes before the type */
1622 /* FIXME: This should probably go in encode_type () */
1623 if (type->num_mods) {
1624 for (i = 0; i < type->num_mods; ++i) {
1625 if (type->modifiers [i].required)
1626 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1627 else
1628 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1629 sigbuffer_add_value (&buf, type->modifiers [i].token);
1632 encode_type (assembly, type, &buf);
1633 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1634 sigbuffer_free (&buf);
1635 return idx;
1637 #endif
1639 static guint32
1640 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1642 SigBuffer buf;
1643 guint32 idx;
1645 sigbuffer_init (&buf, 32);
1647 sigbuffer_add_value (&buf, 0x06);
1648 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1649 /* encode custom attributes before the type */
1650 encode_reflection_type (assembly, monotype_cast (fb->type), &buf);
1651 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1652 sigbuffer_free (&buf);
1653 return idx;
1656 static guint32
1657 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1658 char blob_size [64];
1659 char *b = blob_size;
1660 char *p, *box_val;
1661 char* buf;
1662 guint32 idx = 0, len = 0, dummy = 0;
1663 #ifdef ARM_FPU_FPA
1664 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1665 guint32 fpa_double [2];
1666 guint32 *fpa_p;
1667 #endif
1668 #endif
1670 p = buf = g_malloc (64);
1671 if (!val) {
1672 *ret_type = MONO_TYPE_CLASS;
1673 len = 4;
1674 box_val = (char*)&dummy;
1675 } else {
1676 box_val = ((char*)val) + sizeof (MonoObject);
1677 *ret_type = val->vtable->klass->byval_arg.type;
1679 handle_enum:
1680 switch (*ret_type) {
1681 case MONO_TYPE_BOOLEAN:
1682 case MONO_TYPE_U1:
1683 case MONO_TYPE_I1:
1684 len = 1;
1685 break;
1686 case MONO_TYPE_CHAR:
1687 case MONO_TYPE_U2:
1688 case MONO_TYPE_I2:
1689 len = 2;
1690 break;
1691 case MONO_TYPE_U4:
1692 case MONO_TYPE_I4:
1693 case MONO_TYPE_R4:
1694 len = 4;
1695 break;
1696 case MONO_TYPE_U8:
1697 case MONO_TYPE_I8:
1698 len = 8;
1699 break;
1700 case MONO_TYPE_R8:
1701 len = 8;
1702 #ifdef ARM_FPU_FPA
1703 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1704 fpa_p = (guint32*)box_val;
1705 fpa_double [0] = fpa_p [1];
1706 fpa_double [1] = fpa_p [0];
1707 box_val = (char*)fpa_double;
1708 #endif
1709 #endif
1710 break;
1711 case MONO_TYPE_VALUETYPE:
1712 if (val->vtable->klass->enumtype) {
1713 *ret_type = mono_class_enum_basetype (val->vtable->klass)->type;
1714 goto handle_enum;
1715 } else
1716 g_error ("we can't encode valuetypes");
1717 case MONO_TYPE_CLASS:
1718 break;
1719 case MONO_TYPE_STRING: {
1720 MonoString *str = (MonoString*)val;
1721 /* there is no signature */
1722 len = str->length * 2;
1723 mono_metadata_encode_value (len, b, &b);
1724 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1726 char *swapped = g_malloc (2 * mono_string_length (str));
1727 const char *p = (const char*)mono_string_chars (str);
1729 swap_with_size (swapped, p, 2, mono_string_length (str));
1730 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1731 g_free (swapped);
1733 #else
1734 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1735 #endif
1737 g_free (buf);
1738 return idx;
1740 case MONO_TYPE_GENERICINST:
1741 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
1742 goto handle_enum;
1743 default:
1744 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1747 /* there is no signature */
1748 mono_metadata_encode_value (len, b, &b);
1749 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1750 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1751 swap_with_size (blob_size, box_val, len, 1);
1752 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1753 #else
1754 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1755 #endif
1757 g_free (buf);
1758 return idx;
1761 static guint32
1762 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1763 char *str;
1764 SigBuffer buf;
1765 guint32 idx, len;
1767 sigbuffer_init (&buf, 32);
1769 sigbuffer_add_value (&buf, minfo->type);
1771 switch (minfo->type) {
1772 case MONO_NATIVE_BYVALTSTR:
1773 case MONO_NATIVE_BYVALARRAY:
1774 sigbuffer_add_value (&buf, minfo->count);
1775 break;
1776 case MONO_NATIVE_LPARRAY:
1777 if (minfo->eltype || minfo->has_size) {
1778 sigbuffer_add_value (&buf, minfo->eltype);
1779 if (minfo->has_size) {
1780 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
1781 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
1783 /* LAMESPEC: ElemMult is undocumented */
1784 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1787 break;
1788 case MONO_NATIVE_CUSTOM:
1789 if (minfo->guid) {
1790 str = mono_string_to_utf8 (minfo->guid);
1791 len = strlen (str);
1792 sigbuffer_add_value (&buf, len);
1793 sigbuffer_add_mem (&buf, str, len);
1794 g_free (str);
1795 } else {
1796 sigbuffer_add_value (&buf, 0);
1798 /* native type name */
1799 sigbuffer_add_value (&buf, 0);
1800 /* custom marshaler type name */
1801 if (minfo->marshaltype || minfo->marshaltyperef) {
1802 if (minfo->marshaltyperef)
1803 str = type_get_fully_qualified_name (monotype_cast (minfo->marshaltyperef)->type);
1804 else
1805 str = mono_string_to_utf8 (minfo->marshaltype);
1806 len = strlen (str);
1807 sigbuffer_add_value (&buf, len);
1808 sigbuffer_add_mem (&buf, str, len);
1809 g_free (str);
1810 } else {
1811 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
1812 sigbuffer_add_value (&buf, 0);
1814 if (minfo->mcookie) {
1815 str = mono_string_to_utf8 (minfo->mcookie);
1816 len = strlen (str);
1817 sigbuffer_add_value (&buf, len);
1818 sigbuffer_add_mem (&buf, str, len);
1819 g_free (str);
1820 } else {
1821 sigbuffer_add_value (&buf, 0);
1823 break;
1824 default:
1825 break;
1827 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1828 sigbuffer_free (&buf);
1829 return idx;
1832 static void
1833 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1835 MonoDynamicTable *table;
1836 guint32 *values;
1838 /* maybe this fixup should be done in the C# code */
1839 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1840 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1841 table = &assembly->tables [MONO_TABLE_FIELD];
1842 fb->table_idx = table->next_idx ++;
1843 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1844 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1845 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
1846 values [MONO_FIELD_FLAGS] = fb->attrs;
1847 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1849 if (fb->offset != -1) {
1850 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1851 table->rows ++;
1852 alloc_table (table, table->rows);
1853 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1854 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1855 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1857 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1858 guint32 field_type = 0;
1859 table = &assembly->tables [MONO_TABLE_CONSTANT];
1860 table->rows ++;
1861 alloc_table (table, table->rows);
1862 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1863 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1864 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1865 values [MONO_CONSTANT_TYPE] = field_type;
1866 values [MONO_CONSTANT_PADDING] = 0;
1868 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1869 guint32 rva_idx;
1870 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1871 table->rows ++;
1872 alloc_table (table, table->rows);
1873 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1874 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1876 * We store it in the code section because it's simpler for now.
1878 if (fb->rva_data) {
1879 if (mono_array_length (fb->rva_data) >= 10)
1880 stream_data_align (&assembly->code);
1881 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1882 } else
1883 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1884 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1886 if (fb->marshal_info) {
1887 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1888 table->rows ++;
1889 alloc_table (table, table->rows);
1890 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1891 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1892 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1896 static guint32
1897 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1899 SigBuffer buf;
1900 guint32 nparams = 0;
1901 MonoReflectionMethodBuilder *mb = fb->get_method;
1902 MonoReflectionMethodBuilder *smb = fb->set_method;
1903 guint32 idx, i;
1905 if (mb && mb->parameters)
1906 nparams = mono_array_length (mb->parameters);
1907 if (!mb && smb && smb->parameters)
1908 nparams = mono_array_length (smb->parameters) - 1;
1909 sigbuffer_init (&buf, 32);
1910 sigbuffer_add_byte (&buf, 0x08);
1911 sigbuffer_add_value (&buf, nparams);
1912 if (mb) {
1913 encode_reflection_type (assembly, monotype_cast (mb->rtype), &buf);
1914 for (i = 0; i < nparams; ++i) {
1915 MonoReflectionType *pt = mono_type_array_get (mb->parameters, i);
1916 encode_reflection_type (assembly, pt, &buf);
1918 } else if (smb && smb->parameters) {
1919 /* the property type is the last param */
1920 encode_reflection_type (assembly, mono_type_array_get (smb->parameters, nparams), &buf);
1921 for (i = 0; i < nparams; ++i) {
1922 MonoReflectionType *pt = mono_type_array_get (smb->parameters, i);
1923 encode_reflection_type (assembly, pt, &buf);
1925 } else {
1926 encode_reflection_type (assembly, monotype_cast (fb->type), &buf);
1929 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1930 sigbuffer_free (&buf);
1931 return idx;
1934 static void
1935 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1937 MonoDynamicTable *table;
1938 guint32 *values;
1939 guint num_methods = 0;
1940 guint32 semaidx;
1943 * we need to set things in the following tables:
1944 * PROPERTYMAP (info already filled in _get_type_info ())
1945 * PROPERTY (rows already preallocated in _get_type_info ())
1946 * METHOD (method info already done with the generic method code)
1947 * METHODSEMANTICS
1949 table = &assembly->tables [MONO_TABLE_PROPERTY];
1950 pb->table_idx = table->next_idx ++;
1951 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1952 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1953 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1954 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1956 /* FIXME: we still don't handle 'other' methods */
1957 if (pb->get_method) num_methods ++;
1958 if (pb->set_method) num_methods ++;
1960 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1961 table->rows += num_methods;
1962 alloc_table (table, table->rows);
1964 if (pb->get_method) {
1965 semaidx = table->next_idx ++;
1966 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1967 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1968 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1969 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1971 if (pb->set_method) {
1972 semaidx = table->next_idx ++;
1973 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1974 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1975 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1976 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1980 static void
1981 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1983 MonoDynamicTable *table;
1984 guint32 *values;
1985 guint num_methods = 0;
1986 guint32 semaidx;
1989 * we need to set things in the following tables:
1990 * EVENTMAP (info already filled in _get_type_info ())
1991 * EVENT (rows already preallocated in _get_type_info ())
1992 * METHOD (method info already done with the generic method code)
1993 * METHODSEMANTICS
1995 table = &assembly->tables [MONO_TABLE_EVENT];
1996 eb->table_idx = table->next_idx ++;
1997 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1998 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
1999 values [MONO_EVENT_FLAGS] = eb->attrs;
2000 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
2003 * FIXME: we still don't handle 'other' methods
2005 if (eb->add_method) num_methods ++;
2006 if (eb->remove_method) num_methods ++;
2007 if (eb->raise_method) num_methods ++;
2009 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2010 table->rows += num_methods;
2011 alloc_table (table, table->rows);
2013 if (eb->add_method) {
2014 semaidx = table->next_idx ++;
2015 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2016 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2017 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2018 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2020 if (eb->remove_method) {
2021 semaidx = table->next_idx ++;
2022 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2023 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2024 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2025 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2027 if (eb->raise_method) {
2028 semaidx = table->next_idx ++;
2029 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2030 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2031 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2032 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2036 static void
2037 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2039 MonoDynamicTable *table;
2040 guint32 num_constraints, i;
2041 guint32 *values;
2042 guint32 table_idx;
2044 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2045 num_constraints = gparam->iface_constraints ?
2046 mono_array_length (gparam->iface_constraints) : 0;
2047 table->rows += num_constraints;
2048 if (gparam->base_type)
2049 table->rows++;
2050 alloc_table (table, table->rows);
2052 if (gparam->base_type) {
2053 table_idx = table->next_idx ++;
2054 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2056 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2057 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2058 assembly, gparam->base_type->type);
2061 for (i = 0; i < num_constraints; i++) {
2062 MonoReflectionType *constraint = mono_array_get (
2063 gparam->iface_constraints, gpointer, i);
2065 table_idx = table->next_idx ++;
2066 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2068 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2069 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2070 assembly, constraint->type);
2074 static void
2075 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2077 GenericParamTableEntry *entry;
2080 * The GenericParam table must be sorted according to the `owner' field.
2081 * We need to do this sorting prior to writing the GenericParamConstraint
2082 * table, since we have to use the final GenericParam table indices there
2083 * and they must also be sorted.
2086 entry = g_new0 (GenericParamTableEntry, 1);
2087 entry->owner = owner;
2088 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2089 MOVING_GC_REGISTER (&entry->gparam);
2090 entry->gparam = gparam;
2092 g_ptr_array_add (assembly->gen_params, entry);
2095 static void
2096 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2098 MonoDynamicTable *table;
2099 MonoGenericParam *param;
2100 guint32 *values;
2101 guint32 table_idx;
2103 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2104 table_idx = table->next_idx ++;
2105 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2107 param = entry->gparam->type.type->data.generic_param;
2109 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2110 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2111 values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2112 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2114 mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2116 encode_constraints (entry->gparam, table_idx, assembly);
2119 static guint32
2120 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2122 MonoDynamicTable *table;
2123 guint32 token;
2124 guint32 *values;
2125 guint32 cols [MONO_ASSEMBLY_SIZE];
2126 const char *pubkey;
2127 guint32 publen;
2129 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2130 return token;
2132 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2133 table = &assembly->tables [MONO_TABLE_MODULEREF];
2134 token = table->next_idx ++;
2135 table->rows ++;
2136 alloc_table (table, table->rows);
2137 values = table->values + token * MONO_MODULEREF_SIZE;
2138 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2140 token <<= MONO_RESOLTION_SCOPE_BITS;
2141 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2142 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2144 return token;
2147 if (image->assembly->dynamic)
2148 /* FIXME: */
2149 memset (cols, 0, sizeof (cols));
2150 else {
2151 /* image->assembly->image is the manifest module */
2152 image = image->assembly->image;
2153 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2156 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2157 token = table->next_idx ++;
2158 table->rows ++;
2159 alloc_table (table, table->rows);
2160 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2161 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2162 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2163 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2164 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2165 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2166 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2167 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2168 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2170 if (strcmp ("", image->assembly->aname.culture)) {
2171 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2172 image->assembly->aname.culture);
2175 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2176 guchar pubtoken [9];
2177 pubtoken [0] = 8;
2178 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2179 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2180 } else {
2181 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2183 token <<= MONO_RESOLTION_SCOPE_BITS;
2184 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2185 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2186 return token;
2189 static guint32
2190 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2192 MonoDynamicTable *table;
2193 guint32 *values;
2194 guint32 token;
2195 SigBuffer buf;
2197 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2198 return token;
2200 sigbuffer_init (&buf, 32);
2201 switch (type->type) {
2202 case MONO_TYPE_FNPTR:
2203 case MONO_TYPE_PTR:
2204 case MONO_TYPE_SZARRAY:
2205 case MONO_TYPE_ARRAY:
2206 case MONO_TYPE_VAR:
2207 case MONO_TYPE_MVAR:
2208 case MONO_TYPE_GENERICINST:
2209 encode_type (assembly, type, &buf);
2210 break;
2211 case MONO_TYPE_CLASS:
2212 case MONO_TYPE_VALUETYPE: {
2213 MonoClass *k = mono_class_from_mono_type (type);
2214 if (!k || !k->generic_container) {
2215 sigbuffer_free (&buf);
2216 return 0;
2218 encode_type (assembly, type, &buf);
2219 break;
2221 default:
2222 sigbuffer_free (&buf);
2223 return 0;
2226 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2227 if (assembly->save) {
2228 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2229 alloc_table (table, table->rows + 1);
2230 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2231 values [MONO_TYPESPEC_SIGNATURE] = token;
2233 sigbuffer_free (&buf);
2235 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2236 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2237 table->next_idx ++;
2238 return token;
2241 static guint32
2242 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2244 MonoDynamicTable *table;
2245 guint32 *values;
2246 guint32 token, scope, enclosing;
2247 MonoClass *klass;
2249 /* if the type requires a typespec, we must try that first*/
2250 if (try_typespec && (token = create_typespec (assembly, type)))
2251 return token;
2252 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2253 if (token)
2254 return token;
2255 klass = mono_class_from_mono_type (type);
2256 if (!klass)
2257 klass = mono_class_from_mono_type (type);
2260 * If it's in the same module and not a generic type parameter:
2262 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2263 (type->type != MONO_TYPE_MVAR)) {
2264 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2265 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2266 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2267 return token;
2270 if (klass->nested_in) {
2271 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2272 /* get the typeref idx of the enclosing type */
2273 enclosing >>= MONO_TYPEDEFORREF_BITS;
2274 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2275 } else {
2276 scope = resolution_scope_from_image (assembly, klass->image);
2278 table = &assembly->tables [MONO_TABLE_TYPEREF];
2279 if (assembly->save) {
2280 alloc_table (table, table->rows + 1);
2281 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2282 values [MONO_TYPEREF_SCOPE] = scope;
2283 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2284 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2286 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2287 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2288 table->next_idx ++;
2289 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2290 return token;
2294 * Despite the name, we handle also TypeSpec (with the above helper).
2296 static guint32
2297 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2299 return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2302 #ifndef DISABLE_REFLECTION_EMIT
2304 * Insert a memberef row into the metadata: the token that point to the memberref
2305 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2306 * mono_image_get_fieldref_token()).
2307 * The sig param is an index to an already built signature.
2309 static guint32
2310 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2312 MonoDynamicTable *table;
2313 guint32 *values;
2314 guint32 token, pclass;
2315 guint32 parent;
2317 parent = mono_image_typedef_or_ref (assembly, type);
2318 switch (parent & MONO_TYPEDEFORREF_MASK) {
2319 case MONO_TYPEDEFORREF_TYPEREF:
2320 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2321 break;
2322 case MONO_TYPEDEFORREF_TYPESPEC:
2323 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2324 break;
2325 case MONO_TYPEDEFORREF_TYPEDEF:
2326 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2327 break;
2328 default:
2329 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2330 return 0;
2332 /* extract the index */
2333 parent >>= MONO_TYPEDEFORREF_BITS;
2335 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2337 if (assembly->save) {
2338 alloc_table (table, table->rows + 1);
2339 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2340 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2341 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2342 values [MONO_MEMBERREF_SIGNATURE] = sig;
2345 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2346 table->next_idx ++;
2348 return token;
2351 static guint32
2352 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2354 guint32 token;
2355 MonoMethodSignature *sig;
2357 create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2359 if (create_typespec) {
2360 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2361 if (token)
2362 return token;
2365 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2366 if (token && !create_typespec)
2367 return token;
2369 g_assert (!method->is_inflated);
2370 if (!token) {
2372 * A methodref signature can't contain an unmanaged calling convention.
2374 sig = mono_metadata_signature_dup (mono_method_signature (method));
2375 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2376 sig->call_convention = MONO_CALL_DEFAULT;
2377 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2378 method->name, method_encode_signature (assembly, sig));
2379 g_free (sig);
2380 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2383 if (create_typespec) {
2384 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2385 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2386 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2388 if (assembly->save) {
2389 guint32 *values;
2391 alloc_table (table, table->rows + 1);
2392 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2393 values [MONO_METHODSPEC_METHOD] = token;
2394 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2397 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2398 table->next_idx ++;
2399 /*methodspec and memberef tokens are diferent, */
2400 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2401 return token;
2403 return token;
2406 static guint32
2407 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2409 guint32 token;
2410 ReflectionMethodBuilder rmb;
2411 char *name;
2413 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2414 if (token)
2415 return token;
2417 name = mono_string_to_utf8 (method->name);
2418 reflection_methodbuilder_from_method_builder (&rmb, method);
2421 * A methodref signature can't contain an unmanaged calling convention.
2422 * Since some flags are encoded as part of call_conv, we need to check against it.
2424 if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2425 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2426 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2427 name, method_builder_encode_signature (assembly, &rmb));
2429 g_free (name);
2430 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2431 return token;
2434 static guint32
2435 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2436 const gchar *name, guint32 sig)
2438 MonoDynamicTable *table;
2439 guint32 token;
2440 guint32 *values;
2442 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2444 if (assembly->save) {
2445 alloc_table (table, table->rows + 1);
2446 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2447 values [MONO_MEMBERREF_CLASS] = original;
2448 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2449 values [MONO_MEMBERREF_SIGNATURE] = sig;
2452 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2453 table->next_idx ++;
2455 return token;
2458 static guint32
2459 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2461 SigBuffer buf;
2462 int i;
2463 guint32 nparams = mono_array_length (mb->generic_params);
2464 guint32 idx;
2466 if (!assembly->save)
2467 return 0;
2469 sigbuffer_init (&buf, 32);
2471 sigbuffer_add_value (&buf, 0xa);
2472 sigbuffer_add_value (&buf, nparams);
2474 for (i = 0; i < nparams; i++) {
2475 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2476 sigbuffer_add_value (&buf, i);
2479 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2480 sigbuffer_free (&buf);
2481 return idx;
2484 static guint32
2485 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2487 MonoDynamicTable *table;
2488 guint32 *values;
2489 guint32 token, mtoken = 0;
2491 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2492 if (token)
2493 return token;
2495 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2497 mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2498 switch (mono_metadata_token_table (mtoken)) {
2499 case MONO_TABLE_MEMBERREF:
2500 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2501 break;
2502 case MONO_TABLE_METHOD:
2503 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2504 break;
2505 default:
2506 g_assert_not_reached ();
2509 if (assembly->save) {
2510 alloc_table (table, table->rows + 1);
2511 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2512 values [MONO_METHODSPEC_METHOD] = mtoken;
2513 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2516 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2517 table->next_idx ++;
2519 mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2520 return token;
2523 static guint32
2524 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2526 guint32 token;
2528 if (mb->generic_params && create_methodspec)
2529 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2531 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2532 if (token)
2533 return token;
2535 token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2536 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2537 return token;
2540 static guint32
2541 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2543 guint32 token;
2544 ReflectionMethodBuilder rmb;
2545 char *name;
2547 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2548 if (token)
2549 return token;
2551 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2553 name = mono_string_to_utf8 (rmb.name);
2554 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2555 name, method_builder_encode_signature (assembly, &rmb));
2557 g_free (name);
2558 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2559 return token;
2561 #endif
2563 static gboolean
2564 is_field_on_inst (MonoClassField *field)
2566 return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2570 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2572 static MonoType*
2573 get_field_on_inst_generic_type (MonoClassField *field)
2575 MonoDynamicGenericClass *dgclass;
2576 int field_index;
2578 g_assert (is_field_on_inst (field));
2580 dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2581 field_index = field - dgclass->fields;
2583 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
2584 return dgclass->field_generic_types [field_index];
2587 #ifndef DISABLE_REFLECTION_EMIT
2588 static guint32
2589 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2591 MonoType *type;
2592 guint32 token;
2593 MonoClassField *field;
2595 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2596 if (token)
2597 return token;
2598 g_assert (f->field->parent);
2600 field = f->field;
2601 if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2602 int index = field - field->parent->fields;
2603 type = field->parent->generic_class->container_class->fields [index].type;
2604 } else {
2605 if (is_field_on_inst (f->field))
2606 type = get_field_on_inst_generic_type (f->field);
2607 else
2608 type = f->field->type;
2610 token = mono_image_get_memberref_token (assembly, &f->field->parent->byval_arg,
2611 mono_field_get_name (f->field),
2612 fieldref_encode_signature (assembly, type));
2613 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2614 return token;
2617 static guint32
2618 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
2620 guint32 token;
2621 MonoClass *klass;
2622 MonoGenericClass *gclass;
2623 MonoDynamicGenericClass *dgclass;
2624 MonoReflectionFieldBuilder *fb = f->fb;
2625 char *name;
2627 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2628 if (token)
2629 return token;
2630 klass = mono_class_from_mono_type (f->inst->type.type);
2631 gclass = f->inst->type.type->data.generic_class;
2632 g_assert (gclass->is_dynamic);
2633 dgclass = (MonoDynamicGenericClass *) gclass;
2635 name = mono_string_to_utf8 (fb->name);
2636 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name,
2637 field_encode_signature (assembly, fb));
2638 g_free (name);
2639 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER (token));
2640 return token;
2643 static guint32
2644 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
2646 guint32 sig, token;
2647 MonoClass *klass;
2648 MonoGenericClass *gclass;
2649 MonoDynamicGenericClass *dgclass;
2650 MonoReflectionCtorBuilder *cb = c->cb;
2651 ReflectionMethodBuilder rmb;
2652 char *name;
2654 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
2656 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, c));
2657 if (token)
2658 return token;
2659 klass = mono_class_from_mono_type (c->inst->type.type);
2660 gclass = c->inst->type.type->data.generic_class;
2661 g_assert (gclass->is_dynamic);
2662 dgclass = (MonoDynamicGenericClass *) gclass;
2664 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
2666 name = mono_string_to_utf8 (rmb.name);
2668 sig = method_builder_encode_signature (assembly, &rmb);
2670 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2671 g_free (name);
2673 g_hash_table_insert (assembly->handleref, c, GUINT_TO_POINTER (token));
2674 return token;
2677 static guint32
2678 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
2680 guint32 sig, token;
2681 MonoClass *klass;
2682 MonoGenericClass *gclass;
2683 MonoReflectionMethodBuilder *mb = m->mb;
2684 ReflectionMethodBuilder rmb;
2685 char *name;
2687 if (create_methodspec && mb->generic_params)
2688 // FIXME:
2689 g_assert_not_reached ();
2691 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
2692 if (token)
2693 return token;
2694 klass = mono_class_from_mono_type (m->inst->type.type);
2695 gclass = m->inst->type.type->data.generic_class;
2696 g_assert (gclass->is_dynamic);
2698 reflection_methodbuilder_from_method_builder (&rmb, mb);
2700 name = mono_string_to_utf8 (rmb.name);
2702 sig = method_builder_encode_signature (assembly, &rmb);
2704 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2705 g_free (name);
2707 g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER (token));
2708 return token;
2711 static guint32
2712 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
2714 SigBuffer buf;
2715 int i;
2716 guint32 nparams = context->method_inst->type_argc;
2717 guint32 idx;
2719 if (!assembly->save)
2720 return 0;
2722 sigbuffer_init (&buf, 32);
2724 * FIXME: vararg, explicit_this, differenc call_conv values...
2726 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
2727 sigbuffer_add_value (&buf, nparams);
2729 for (i = 0; i < nparams; i++)
2730 encode_type (assembly, context->method_inst->type_argv [i], &buf);
2732 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2733 sigbuffer_free (&buf);
2734 return idx;
2737 static guint32
2738 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2740 MonoDynamicTable *table;
2741 guint32 *values;
2742 guint32 token, mtoken = 0, sig;
2743 MonoMethodInflated *imethod;
2744 MonoMethod *declaring;
2746 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2748 g_assert (method->is_inflated);
2749 imethod = (MonoMethodInflated *) method;
2750 declaring = imethod->declaring;
2752 sig = method_encode_signature (assembly, mono_method_signature (declaring));
2753 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2755 if (!mono_method_signature (declaring)->generic_param_count)
2756 return mtoken;
2758 switch (mono_metadata_token_table (mtoken)) {
2759 case MONO_TABLE_MEMBERREF:
2760 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2761 break;
2762 case MONO_TABLE_METHOD:
2763 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2764 break;
2765 default:
2766 g_assert_not_reached ();
2769 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
2771 if (assembly->save) {
2772 alloc_table (table, table->rows + 1);
2773 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2774 values [MONO_METHODSPEC_METHOD] = mtoken;
2775 values [MONO_METHODSPEC_SIGNATURE] = sig;
2778 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2779 table->next_idx ++;
2781 return token;
2784 static guint32
2785 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
2787 MonoMethodInflated *imethod;
2788 guint32 token;
2790 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2791 if (token)
2792 return token;
2794 g_assert (method->is_inflated);
2795 imethod = (MonoMethodInflated *) method;
2797 if (mono_method_signature (imethod->declaring)->generic_param_count) {
2798 token = method_encode_methodspec (assembly, method);
2799 } else {
2800 guint32 sig = method_encode_signature (
2801 assembly, mono_method_signature (imethod->declaring));
2802 token = mono_image_get_memberref_token (
2803 assembly, &method->klass->byval_arg, method->name, sig);
2806 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2807 return token;
2810 static guint32
2811 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
2813 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
2814 guint32 sig, token;
2816 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
2817 token = mono_image_get_memberref_token (
2818 assembly, &m->klass->byval_arg, m->name, sig);
2820 return token;
2823 static guint32
2824 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2826 MonoDynamicTable *table;
2827 MonoClass *klass;
2828 guint32 *values;
2829 guint32 token;
2830 SigBuffer buf;
2831 int count, i;
2834 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2835 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2836 * Because of this, we must not insert it into the `typeref' hash table.
2839 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2840 if (token)
2841 return token;
2843 sigbuffer_init (&buf, 32);
2845 g_assert (tb->generic_params);
2846 klass = mono_class_from_mono_type (tb->type.type);
2848 if (tb->generic_container)
2849 mono_reflection_create_generic_class (tb);
2851 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
2852 g_assert (klass->generic_container);
2853 sigbuffer_add_value (&buf, klass->byval_arg.type);
2854 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
2856 count = mono_array_length (tb->generic_params);
2857 sigbuffer_add_value (&buf, count);
2858 for (i = 0; i < count; i++) {
2859 MonoReflectionGenericParam *gparam;
2861 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2863 encode_type (assembly, gparam->type.type, &buf);
2866 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2868 if (assembly->save) {
2869 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2870 alloc_table (table, table->rows + 1);
2871 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2872 values [MONO_TYPESPEC_SIGNATURE] = token;
2874 sigbuffer_free (&buf);
2876 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2877 g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2878 table->next_idx ++;
2879 return token;
2883 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
2885 static MonoType*
2886 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
2888 int i, count, len, pos;
2889 MonoType *t;
2891 count = 0;
2892 if (modreq)
2893 count += mono_array_length (modreq);
2894 if (modopt)
2895 count += mono_array_length (modopt);
2897 if (count == 0)
2898 return mono_metadata_type_dup (NULL, type);
2900 len = sizeof (MonoType) + ((gint32)count - MONO_ZERO_LEN_ARRAY) * sizeof (MonoCustomMod);
2901 t = g_malloc (len);
2902 memcpy (t, type, sizeof (MonoType));
2904 t->num_mods = count;
2905 pos = 0;
2906 if (modreq) {
2907 for (i = 0; i < mono_array_length (modreq); ++i) {
2908 MonoReflectionType *mod = mono_type_array_get (modreq, i);
2909 t->modifiers [pos].required = 1;
2910 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod->type);
2911 pos ++;
2914 if (modopt) {
2915 for (i = 0; i < mono_array_length (modopt); ++i) {
2916 MonoReflectionType *mod = mono_type_array_get (modopt, i);
2917 t->modifiers [pos].required = 0;
2918 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod->type);
2919 pos ++;
2923 return t;
2926 static guint32
2927 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2929 MonoDynamicTable *table;
2930 MonoClass *klass;
2931 MonoType *custom = NULL;
2932 guint32 *values;
2933 guint32 token, pclass, parent, sig;
2934 gchar *name;
2936 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2937 if (token)
2938 return token;
2940 klass = mono_class_from_mono_type (fb->typeb->type);
2941 name = mono_string_to_utf8 (fb->name);
2943 /* fb->type does not include the custom modifiers */
2944 /* FIXME: We should do this in one place when a fieldbuilder is created */
2945 if (fb->modreq || fb->modopt) {
2946 custom = add_custom_modifiers (assembly, monotype_cast (fb->type)->type, fb->modreq, fb->modopt);
2947 sig = fieldref_encode_signature (assembly, custom);
2948 g_free (custom);
2949 } else {
2950 sig = fieldref_encode_signature (assembly, monotype_cast (fb->type)->type);
2953 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2954 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
2956 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2957 parent >>= MONO_TYPEDEFORREF_BITS;
2959 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2961 if (assembly->save) {
2962 alloc_table (table, table->rows + 1);
2963 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2964 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2965 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2966 values [MONO_MEMBERREF_SIGNATURE] = sig;
2969 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2970 table->next_idx ++;
2971 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2972 g_free (name);
2973 return token;
2976 static guint32
2977 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2979 SigBuffer buf;
2980 guint32 nargs;
2981 guint32 size;
2982 guint32 i, idx;
2984 if (!assembly->save)
2985 return 0;
2987 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
2988 g_assert (helper->type == 2);
2990 if (helper->arguments)
2991 nargs = mono_array_length (helper->arguments);
2992 else
2993 nargs = 0;
2995 size = 10 + (nargs * 10);
2997 sigbuffer_init (&buf, 32);
2999 /* Encode calling convention */
3000 /* Change Any to Standard */
3001 if ((helper->call_conv & 0x03) == 0x03)
3002 helper->call_conv = 0x01;
3003 /* explicit_this implies has_this */
3004 if (helper->call_conv & 0x40)
3005 helper->call_conv &= 0x20;
3007 if (helper->call_conv == 0) { /* Unmanaged */
3008 idx = helper->unmanaged_call_conv - 1;
3009 } else {
3010 /* Managed */
3011 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3012 if (helper->call_conv & 0x02) /* varargs */
3013 idx += 0x05;
3016 sigbuffer_add_byte (&buf, idx);
3017 sigbuffer_add_value (&buf, nargs);
3018 encode_reflection_type (assembly, helper->return_type, &buf);
3019 for (i = 0; i < nargs; ++i) {
3020 MonoArray *modreqs = NULL;
3021 MonoArray *modopts = NULL;
3022 MonoReflectionType *pt;
3024 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3025 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3026 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3027 modopts = mono_array_get (helper->modopts, MonoArray*, i);
3029 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3030 pt = mono_type_array_get (helper->arguments, i);
3031 encode_reflection_type (assembly, pt, &buf);
3033 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3034 sigbuffer_free (&buf);
3036 return idx;
3039 static guint32
3040 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3042 guint32 idx;
3043 MonoDynamicTable *table;
3044 guint32 *values;
3046 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3047 idx = table->next_idx ++;
3048 table->rows ++;
3049 alloc_table (table, table->rows);
3050 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3052 values [MONO_STAND_ALONE_SIGNATURE] =
3053 mono_reflection_encode_sighelper (assembly, helper);
3055 return idx;
3058 static int
3059 reflection_cc_to_file (int call_conv) {
3060 switch (call_conv & 0x3) {
3061 case 0:
3062 case 1: return MONO_CALL_DEFAULT;
3063 case 2: return MONO_CALL_VARARG;
3064 default:
3065 g_assert_not_reached ();
3067 return 0;
3069 #endif /* !DISABLE_REFLECTION_EMIT */
3071 typedef struct {
3072 MonoType *parent;
3073 MonoMethodSignature *sig;
3074 char *name;
3075 guint32 token;
3076 } ArrayMethod;
3078 #ifndef DISABLE_REFLECTION_EMIT
3079 static guint32
3080 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3082 guint32 nparams, i;
3083 GList *tmp;
3084 char *name;
3085 MonoMethodSignature *sig;
3086 ArrayMethod *am;
3088 name = mono_string_to_utf8 (m->name);
3089 nparams = mono_array_length (m->parameters);
3090 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
3091 sig->hasthis = 1;
3092 sig->sentinelpos = -1;
3093 sig->call_convention = reflection_cc_to_file (m->call_conv);
3094 sig->param_count = nparams;
3095 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
3096 for (i = 0; i < nparams; ++i) {
3097 MonoReflectionType *t = mono_type_array_get (m->parameters, i);
3098 sig->params [i] = t->type;
3101 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3102 am = tmp->data;
3103 if (strcmp (name, am->name) == 0 &&
3104 mono_metadata_type_equal (am->parent, m->parent->type) &&
3105 mono_metadata_signature_equal (am->sig, sig)) {
3106 g_free (name);
3107 g_free (sig);
3108 m->table_idx = am->token & 0xffffff;
3109 return am->token;
3112 am = g_new0 (ArrayMethod, 1);
3113 am->name = name;
3114 am->sig = sig;
3115 am->parent = m->parent->type;
3116 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3117 method_encode_signature (assembly, sig));
3118 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3119 m->table_idx = am->token & 0xffffff;
3120 return am->token;
3122 #endif
3125 * Insert into the metadata tables all the info about the TypeBuilder tb.
3126 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3128 static void
3129 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3131 MonoDynamicTable *table;
3132 guint *values;
3133 int i, is_object = 0, is_system = 0;
3134 char *n;
3136 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3137 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3138 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3139 n = mono_string_to_utf8 (tb->name);
3140 if (strcmp (n, "Object") == 0)
3141 is_object++;
3142 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3143 g_free (n);
3144 n = mono_string_to_utf8 (tb->nspace);
3145 if (strcmp (n, "System") == 0)
3146 is_system++;
3147 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3148 g_free (n);
3149 if (tb->parent && !(is_system && is_object) &&
3150 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3151 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, monotype_cast (tb->parent)->type);
3152 } else {
3153 values [MONO_TYPEDEF_EXTENDS] = 0;
3155 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3156 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3159 * if we have explicitlayout or sequentiallayouts, output data in the
3160 * ClassLayout table.
3162 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3163 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3164 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3165 table->rows++;
3166 alloc_table (table, table->rows);
3167 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3168 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3169 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3170 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3173 /* handle interfaces */
3174 if (tb->interfaces) {
3175 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3176 i = table->rows;
3177 table->rows += mono_array_length (tb->interfaces);
3178 alloc_table (table, table->rows);
3179 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3180 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3181 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3182 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3183 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
3184 values += MONO_INTERFACEIMPL_SIZE;
3188 /* handle fields */
3189 if (tb->fields) {
3190 table = &assembly->tables [MONO_TABLE_FIELD];
3191 table->rows += tb->num_fields;
3192 alloc_table (table, table->rows);
3193 for (i = 0; i < tb->num_fields; ++i)
3194 mono_image_get_field_info (
3195 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3198 /* handle constructors */
3199 if (tb->ctors) {
3200 table = &assembly->tables [MONO_TABLE_METHOD];
3201 table->rows += mono_array_length (tb->ctors);
3202 alloc_table (table, table->rows);
3203 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3204 mono_image_get_ctor_info (domain,
3205 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3208 /* handle methods */
3209 if (tb->methods) {
3210 table = &assembly->tables [MONO_TABLE_METHOD];
3211 table->rows += tb->num_methods;
3212 alloc_table (table, table->rows);
3213 for (i = 0; i < tb->num_methods; ++i)
3214 mono_image_get_method_info (
3215 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3218 /* Do the same with properties etc.. */
3219 if (tb->events && mono_array_length (tb->events)) {
3220 table = &assembly->tables [MONO_TABLE_EVENT];
3221 table->rows += mono_array_length (tb->events);
3222 alloc_table (table, table->rows);
3223 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3224 table->rows ++;
3225 alloc_table (table, table->rows);
3226 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3227 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3228 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3229 for (i = 0; i < mono_array_length (tb->events); ++i)
3230 mono_image_get_event_info (
3231 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3233 if (tb->properties && mono_array_length (tb->properties)) {
3234 table = &assembly->tables [MONO_TABLE_PROPERTY];
3235 table->rows += mono_array_length (tb->properties);
3236 alloc_table (table, table->rows);
3237 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3238 table->rows ++;
3239 alloc_table (table, table->rows);
3240 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3241 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3242 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3243 for (i = 0; i < mono_array_length (tb->properties); ++i)
3244 mono_image_get_property_info (
3245 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3248 /* handle generic parameters */
3249 if (tb->generic_params) {
3250 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3251 table->rows += mono_array_length (tb->generic_params);
3252 alloc_table (table, table->rows);
3253 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3254 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3256 mono_image_get_generic_param_info (
3257 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3261 mono_image_add_decl_security (assembly,
3262 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3264 if (tb->subtypes) {
3265 MonoDynamicTable *ntable;
3267 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3268 ntable->rows += mono_array_length (tb->subtypes);
3269 alloc_table (ntable, ntable->rows);
3270 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3272 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3273 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3275 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3276 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3277 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3278 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3279 mono_string_to_utf8 (tb->name), tb->table_idx,
3280 ntable->next_idx, ntable->rows);*/
3281 values += MONO_NESTED_CLASS_SIZE;
3282 ntable->next_idx++;
3287 static void
3288 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
3290 int i;
3292 g_ptr_array_add (types, type); /* FIXME: GC object added to unmanaged memory */
3294 if (!type->subtypes)
3295 return;
3297 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3298 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3299 collect_types (types, subtype);
3303 static gint
3304 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3306 if ((*type1)->table_idx < (*type2)->table_idx)
3307 return -1;
3308 else
3309 if ((*type1)->table_idx > (*type2)->table_idx)
3310 return 1;
3311 else
3312 return 0;
3315 static void
3316 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3317 int i;
3319 if (!pinfo)
3320 return;
3321 for (i = 0; i < mono_array_length (pinfo); ++i) {
3322 MonoReflectionParamBuilder *pb;
3323 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3324 if (!pb)
3325 continue;
3326 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3330 static void
3331 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3332 int i;
3334 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3335 if (tb->fields) {
3336 for (i = 0; i < tb->num_fields; ++i) {
3337 MonoReflectionFieldBuilder* fb;
3338 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3339 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3342 if (tb->events) {
3343 for (i = 0; i < mono_array_length (tb->events); ++i) {
3344 MonoReflectionEventBuilder* eb;
3345 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3346 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3349 if (tb->properties) {
3350 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3351 MonoReflectionPropertyBuilder* pb;
3352 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3353 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3356 if (tb->ctors) {
3357 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3358 MonoReflectionCtorBuilder* cb;
3359 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3360 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3361 params_add_cattrs (assembly, cb->pinfo);
3365 if (tb->methods) {
3366 for (i = 0; i < tb->num_methods; ++i) {
3367 MonoReflectionMethodBuilder* mb;
3368 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3369 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3370 params_add_cattrs (assembly, mb->pinfo);
3374 if (tb->subtypes) {
3375 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3376 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3380 static void
3381 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3383 int i;
3385 mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3387 if (moduleb->global_methods) {
3388 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3389 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3390 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3391 params_add_cattrs (assembly, mb->pinfo);
3395 if (moduleb->global_fields) {
3396 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3397 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3398 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3402 if (moduleb->types) {
3403 for (i = 0; i < moduleb->num_types; ++i)
3404 type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3408 static void
3409 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3411 MonoDynamicTable *table;
3412 guint32 *values;
3413 char blob_size [6];
3414 guchar hash [20];
3415 char *b = blob_size;
3416 char *dir, *path;
3418 table = &assembly->tables [MONO_TABLE_FILE];
3419 table->rows++;
3420 alloc_table (table, table->rows);
3421 values = table->values + table->next_idx * MONO_FILE_SIZE;
3422 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3423 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3424 if (module->image->dynamic) {
3425 /* This depends on the fact that the main module is emitted last */
3426 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3427 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3428 } else {
3429 dir = NULL;
3430 path = g_strdup (module->image->name);
3432 mono_sha1_get_digest_from_file (path, hash);
3433 g_free (dir);
3434 g_free (path);
3435 mono_metadata_encode_value (20, b, &b);
3436 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3437 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3438 table->next_idx ++;
3441 static void
3442 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3444 MonoDynamicTable *table;
3445 int i;
3447 table = &assembly->tables [MONO_TABLE_MODULE];
3448 mb->table_idx = table->next_idx ++;
3449 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3450 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3451 i /= 16;
3452 ++i;
3453 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3454 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3455 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3456 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3459 static guint32
3460 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3461 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3463 MonoDynamicTable *table;
3464 guint32 *values;
3465 guint32 visib, res;
3467 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3468 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3469 return 0;
3471 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3472 table->rows++;
3473 alloc_table (table, table->rows);
3474 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3476 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3477 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3478 if (klass->nested_in)
3479 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3480 else
3481 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3482 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3483 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3485 res = table->next_idx;
3487 table->next_idx ++;
3489 /* Emit nested types */
3490 if (klass->ext && klass->ext->nested_classes) {
3491 GList *tmp;
3493 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
3494 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3497 return res;
3500 static void
3501 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3502 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3504 MonoClass *klass;
3505 guint32 idx, i;
3507 klass = mono_class_from_mono_type (tb->type.type);
3509 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3511 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3512 parent_index, assembly);
3515 * Emit nested types
3516 * We need to do this ourselves since klass->nested_classes is not set up.
3518 if (tb->subtypes) {
3519 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3520 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3524 static void
3525 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3526 guint32 module_index, MonoDynamicImage *assembly)
3528 MonoImage *image = module->image;
3529 MonoTableInfo *t;
3530 guint32 i;
3532 t = &image->tables [MONO_TABLE_TYPEDEF];
3534 for (i = 0; i < t->rows; ++i) {
3535 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3537 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3538 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3542 static guint32
3543 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass)
3545 MonoDynamicTable *table;
3546 guint32 *values;
3547 guint32 scope, idx, res, impl;
3548 gboolean forwarder = TRUE;
3550 if (klass->nested_in) {
3551 impl = add_exported_type (assemblyb, assembly, klass->nested_in);
3552 forwarder = FALSE;
3553 } else {
3554 scope = resolution_scope_from_image (assembly, klass->image);
3555 g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3556 idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3557 impl = (idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3560 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3562 table->rows++;
3563 alloc_table (table, table->rows);
3564 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3566 values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
3567 values [MONO_EXP_TYPE_TYPEDEF] = 0;
3568 values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
3569 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3570 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3572 res = (table->next_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3574 table->next_idx++;
3576 return res;
3579 static void
3580 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3582 MonoClass *klass;
3583 int i;
3585 if (!assemblyb->type_forwarders)
3586 return;
3588 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3589 MonoReflectionType *t = mono_type_array_get (assemblyb->type_forwarders, i);
3590 if (!t)
3591 continue;
3593 g_assert (t->type);
3595 klass = mono_class_from_mono_type (t->type);
3597 add_exported_type (assemblyb, assembly, klass);
3601 #define align_pointer(base,p)\
3602 do {\
3603 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3604 if (__diff & 3)\
3605 (p) += 4 - (__diff & 3);\
3606 } while (0)
3608 static int
3609 compare_constants (const void *a, const void *b)
3611 const guint32 *a_values = a;
3612 const guint32 *b_values = b;
3613 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3616 static int
3617 compare_semantics (const void *a, const void *b)
3619 const guint32 *a_values = a;
3620 const guint32 *b_values = b;
3621 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3622 if (assoc)
3623 return assoc;
3624 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3627 static int
3628 compare_custom_attrs (const void *a, const void *b)
3630 const guint32 *a_values = a;
3631 const guint32 *b_values = b;
3633 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3636 static int
3637 compare_field_marshal (const void *a, const void *b)
3639 const guint32 *a_values = a;
3640 const guint32 *b_values = b;
3642 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3645 static int
3646 compare_nested (const void *a, const void *b)
3648 const guint32 *a_values = a;
3649 const guint32 *b_values = b;
3651 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3654 static int
3655 compare_genericparam (const void *a, const void *b)
3657 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3658 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3660 if ((*b_entry)->owner == (*a_entry)->owner)
3661 return
3662 mono_type_get_generic_param_num ((*a_entry)->gparam->type.type) -
3663 mono_type_get_generic_param_num ((*b_entry)->gparam->type.type);
3664 else
3665 return (*a_entry)->owner - (*b_entry)->owner;
3668 static int
3669 compare_declsecurity_attrs (const void *a, const void *b)
3671 const guint32 *a_values = a;
3672 const guint32 *b_values = b;
3674 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3677 static int
3678 compare_interface_impl (const void *a, const void *b)
3680 const guint32 *a_values = a;
3681 const guint32 *b_values = b;
3683 int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
3684 if (klass)
3685 return klass;
3687 return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
3690 static void
3691 pad_heap (MonoDynamicStream *sh)
3693 if (sh->index & 3) {
3694 int sz = 4 - (sh->index & 3);
3695 memset (sh->data + sh->index, 0, sz);
3696 sh->index += sz;
3700 struct StreamDesc {
3701 const char *name;
3702 MonoDynamicStream *stream;
3706 * build_compressed_metadata() fills in the blob of data that represents the
3707 * raw metadata as it will be saved in the PE file. The five streams are output
3708 * and the metadata tables are comnpressed from the guint32 array representation,
3709 * to the compressed on-disk format.
3711 static void
3712 build_compressed_metadata (MonoDynamicImage *assembly)
3714 MonoDynamicTable *table;
3715 int i;
3716 guint64 valid_mask = 0;
3717 guint64 sorted_mask;
3718 guint32 heapt_size = 0;
3719 guint32 meta_size = 256; /* allow for header and other stuff */
3720 guint32 table_offset;
3721 guint32 ntables = 0;
3722 guint64 *int64val;
3723 guint32 *int32val;
3724 guint16 *int16val;
3725 MonoImage *meta;
3726 unsigned char *p;
3727 struct StreamDesc stream_desc [5];
3729 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3730 for (i = 0; i < assembly->gen_params->len; i++){
3731 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3732 write_generic_param_entry (assembly, entry);
3735 stream_desc [0].name = "#~";
3736 stream_desc [0].stream = &assembly->tstream;
3737 stream_desc [1].name = "#Strings";
3738 stream_desc [1].stream = &assembly->sheap;
3739 stream_desc [2].name = "#US";
3740 stream_desc [2].stream = &assembly->us;
3741 stream_desc [3].name = "#Blob";
3742 stream_desc [3].stream = &assembly->blob;
3743 stream_desc [4].name = "#GUID";
3744 stream_desc [4].stream = &assembly->guid;
3746 /* tables that are sorted */
3747 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3748 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3749 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3750 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3751 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3752 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
3753 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
3755 /* Compute table sizes */
3756 /* the MonoImage has already been created in mono_image_basic_init() */
3757 meta = &assembly->image;
3759 /* sizes should be multiple of 4 */
3760 pad_heap (&assembly->blob);
3761 pad_heap (&assembly->guid);
3762 pad_heap (&assembly->sheap);
3763 pad_heap (&assembly->us);
3765 /* Setup the info used by compute_sizes () */
3766 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3767 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3768 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3770 meta_size += assembly->blob.index;
3771 meta_size += assembly->guid.index;
3772 meta_size += assembly->sheap.index;
3773 meta_size += assembly->us.index;
3775 for (i=0; i < MONO_TABLE_NUM; ++i)
3776 meta->tables [i].rows = assembly->tables [i].rows;
3778 for (i = 0; i < MONO_TABLE_NUM; i++){
3779 if (meta->tables [i].rows == 0)
3780 continue;
3781 valid_mask |= (guint64)1 << i;
3782 ntables ++;
3783 meta->tables [i].row_size = mono_metadata_compute_size (
3784 meta, i, &meta->tables [i].size_bitfield);
3785 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3787 heapt_size += 24; /* #~ header size */
3788 heapt_size += ntables * 4;
3789 /* make multiple of 4 */
3790 heapt_size += 3;
3791 heapt_size &= ~3;
3792 meta_size += heapt_size;
3793 meta->raw_metadata = g_malloc0 (meta_size);
3794 p = (unsigned char*)meta->raw_metadata;
3795 /* the metadata signature */
3796 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3797 /* version numbers and 4 bytes reserved */
3798 int16val = (guint16*)p;
3799 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
3800 *int16val = GUINT16_TO_LE (meta->md_version_minor);
3801 p += 8;
3802 /* version string */
3803 int32val = (guint32*)p;
3804 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3805 p += 4;
3806 memcpy (p, meta->version, strlen (meta->version));
3807 p += GUINT32_FROM_LE (*int32val);
3808 align_pointer (meta->raw_metadata, p);
3809 int16val = (guint16*)p;
3810 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3811 *int16val = GUINT16_TO_LE (5); /* number of streams */
3812 p += 4;
3815 * write the stream info.
3817 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3818 table_offset += 3; table_offset &= ~3;
3820 assembly->tstream.index = heapt_size;
3821 for (i = 0; i < 5; ++i) {
3822 int32val = (guint32*)p;
3823 stream_desc [i].stream->offset = table_offset;
3824 *int32val++ = GUINT32_TO_LE (table_offset);
3825 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3826 table_offset += GUINT32_FROM_LE (*int32val);
3827 table_offset += 3; table_offset &= ~3;
3828 p += 8;
3829 strcpy ((char*)p, stream_desc [i].name);
3830 p += strlen (stream_desc [i].name) + 1;
3831 align_pointer (meta->raw_metadata, p);
3834 * now copy the data, the table stream header and contents goes first.
3836 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3837 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
3838 int32val = (guint32*)p;
3839 *int32val = GUINT32_TO_LE (0); /* reserved */
3840 p += 4;
3842 if (mono_framework_version () > 1) {
3843 *p++ = 2; /* version */
3844 *p++ = 0;
3845 } else {
3846 *p++ = 1; /* version */
3847 *p++ = 0;
3850 if (meta->idx_string_wide)
3851 *p |= 0x01;
3852 if (meta->idx_guid_wide)
3853 *p |= 0x02;
3854 if (meta->idx_blob_wide)
3855 *p |= 0x04;
3856 ++p;
3857 *p++ = 1; /* reserved */
3858 int64val = (guint64*)p;
3859 *int64val++ = GUINT64_TO_LE (valid_mask);
3860 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3861 p += 16;
3862 int32val = (guint32*)p;
3863 for (i = 0; i < MONO_TABLE_NUM; i++){
3864 if (meta->tables [i].rows == 0)
3865 continue;
3866 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3868 p = (unsigned char*)int32val;
3870 /* sort the tables that still need sorting */
3871 table = &assembly->tables [MONO_TABLE_CONSTANT];
3872 if (table->rows)
3873 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
3874 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3875 if (table->rows)
3876 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3877 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3878 if (table->rows)
3879 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3880 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3881 if (table->rows)
3882 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3883 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3884 if (table->rows)
3885 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3886 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3887 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
3888 if (table->rows)
3889 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
3890 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3891 if (table->rows)
3892 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
3894 /* compress the tables */
3895 for (i = 0; i < MONO_TABLE_NUM; i++){
3896 int row, col;
3897 guint32 *values;
3898 guint32 bitfield = meta->tables [i].size_bitfield;
3899 if (!meta->tables [i].rows)
3900 continue;
3901 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3902 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3903 meta->tables [i].base = (char*)p;
3904 for (row = 1; row <= meta->tables [i].rows; ++row) {
3905 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3906 for (col = 0; col < assembly->tables [i].columns; ++col) {
3907 switch (mono_metadata_table_size (bitfield, col)) {
3908 case 1:
3909 *p++ = values [col];
3910 break;
3911 case 2:
3912 *p++ = values [col] & 0xff;
3913 *p++ = (values [col] >> 8) & 0xff;
3914 break;
3915 case 4:
3916 *p++ = values [col] & 0xff;
3917 *p++ = (values [col] >> 8) & 0xff;
3918 *p++ = (values [col] >> 16) & 0xff;
3919 *p++ = (values [col] >> 24) & 0xff;
3920 break;
3921 default:
3922 g_assert_not_reached ();
3926 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3929 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3930 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3931 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3932 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3933 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3935 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3939 * Some tables in metadata need to be sorted according to some criteria, but
3940 * when methods and fields are first created with reflection, they may be assigned a token
3941 * that doesn't correspond to the final token they will get assigned after the sorting.
3942 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3943 * with the reflection objects that represent them. Once all the tables are set up, the
3944 * reflection objects will contains the correct table index. fixup_method() will fixup the
3945 * tokens for the method with ILGenerator @ilgen.
3947 static void
3948 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
3950 guint32 code_idx = GPOINTER_TO_UINT (value);
3951 MonoReflectionILTokenInfo *iltoken;
3952 MonoReflectionFieldBuilder *field;
3953 MonoReflectionCtorBuilder *ctor;
3954 MonoReflectionMethodBuilder *method;
3955 MonoReflectionTypeBuilder *tb;
3956 MonoReflectionArrayMethod *am;
3957 guint32 i, idx = 0;
3958 unsigned char *target;
3960 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3961 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3962 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
3963 switch (target [3]) {
3964 case MONO_TABLE_FIELD:
3965 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3966 field = (MonoReflectionFieldBuilder *)iltoken->member;
3967 idx = field->table_idx;
3968 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3969 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3970 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
3971 } else {
3972 g_assert_not_reached ();
3974 break;
3975 case MONO_TABLE_METHOD:
3976 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3977 method = (MonoReflectionMethodBuilder *)iltoken->member;
3978 idx = method->table_idx;
3979 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3980 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3981 idx = ctor->table_idx;
3982 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3983 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3984 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3985 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3986 } else {
3987 g_assert_not_reached ();
3989 break;
3990 case MONO_TABLE_TYPEDEF:
3991 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3992 g_assert_not_reached ();
3993 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3994 idx = tb->table_idx;
3995 break;
3996 case MONO_TABLE_MEMBERREF:
3997 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3998 am = (MonoReflectionArrayMethod*)iltoken->member;
3999 idx = am->table_idx;
4000 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4001 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4002 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4003 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4004 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4005 g_assert (m->klass->generic_class || m->klass->generic_container);
4006 continue;
4007 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4008 continue;
4009 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4010 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4011 g_assert (is_field_on_inst (f));
4012 continue;
4013 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4014 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4015 continue;
4016 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4017 continue;
4018 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4019 continue;
4020 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4021 continue;
4022 } else {
4023 g_assert_not_reached ();
4025 break;
4026 case MONO_TABLE_METHODSPEC:
4027 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4028 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4029 g_assert (mono_method_signature (m)->generic_param_count);
4030 continue;
4031 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4032 continue;
4033 } else {
4034 g_assert_not_reached ();
4036 break;
4037 default:
4038 g_error ("got unexpected table 0x%02x in fixup", target [3]);
4040 target [0] = idx & 0xff;
4041 target [1] = (idx >> 8) & 0xff;
4042 target [2] = (idx >> 16) & 0xff;
4047 * fixup_cattrs:
4049 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4050 * value is not known when the table is emitted.
4052 static void
4053 fixup_cattrs (MonoDynamicImage *assembly)
4055 MonoDynamicTable *table;
4056 guint32 *values;
4057 guint32 type, i, idx, token;
4058 MonoObject *ctor;
4060 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4062 for (i = 0; i < table->rows; ++i) {
4063 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4065 type = values [MONO_CUSTOM_ATTR_TYPE];
4066 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4067 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4068 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4069 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4070 g_assert (ctor);
4072 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4073 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4074 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4075 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4081 static void
4082 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4084 MonoDynamicTable *table;
4085 guint32 *values;
4087 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4088 table->rows++;
4089 alloc_table (table, table->rows);
4090 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4091 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4092 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4093 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4094 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4095 table->next_idx++;
4098 static void
4099 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4101 MonoDynamicTable *table;
4102 guint32 *values;
4103 char blob_size [6];
4104 guchar hash [20];
4105 char *b = blob_size;
4106 char *name, *sname;
4107 guint32 idx, offset;
4109 if (rsrc->filename) {
4110 name = mono_string_to_utf8 (rsrc->filename);
4111 sname = g_path_get_basename (name);
4113 table = &assembly->tables [MONO_TABLE_FILE];
4114 table->rows++;
4115 alloc_table (table, table->rows);
4116 values = table->values + table->next_idx * MONO_FILE_SIZE;
4117 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4118 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4119 g_free (sname);
4121 mono_sha1_get_digest_from_file (name, hash);
4122 mono_metadata_encode_value (20, b, &b);
4123 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4124 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4125 g_free (name);
4126 idx = table->next_idx++;
4127 rsrc->offset = 0;
4128 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4129 } else {
4130 char sizebuf [4];
4131 char *data;
4132 guint len;
4133 if (rsrc->data) {
4134 data = mono_array_addr (rsrc->data, char, 0);
4135 len = mono_array_length (rsrc->data);
4136 } else {
4137 data = NULL;
4138 len = 0;
4140 offset = len;
4141 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4142 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4143 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4144 mono_image_add_stream_data (&assembly->resources, data, len);
4146 if (!mb->is_main)
4148 * The entry should be emitted into the MANIFESTRESOURCE table of
4149 * the main module, but that needs to reference the FILE table
4150 * which isn't emitted yet.
4152 return;
4153 else
4154 idx = 0;
4157 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4160 static void
4161 set_version_from_string (MonoString *version, guint32 *values)
4163 gchar *ver, *p, *str;
4164 guint32 i;
4166 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4167 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4168 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4169 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4170 if (!version)
4171 return;
4172 ver = str = mono_string_to_utf8 (version);
4173 for (i = 0; i < 4; ++i) {
4174 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4175 switch (*p) {
4176 case '.':
4177 p++;
4178 break;
4179 case '*':
4180 /* handle Revision and Build */
4181 p++;
4182 break;
4184 ver = p;
4186 g_free (str);
4189 static guint32
4190 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4191 gsize len;
4192 guint32 token = 0;
4193 char blob_size [6];
4194 char *b = blob_size;
4196 if (!pkey)
4197 return token;
4199 len = mono_array_length (pkey);
4200 mono_metadata_encode_value (len, b, &b);
4201 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4202 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4204 assembly->public_key = g_malloc (len);
4205 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4206 assembly->public_key_len = len;
4208 /* Special case: check for ECMA key (16 bytes) */
4209 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4210 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4211 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4212 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4213 /* minimum key size (in 2.0) is 384 bits */
4214 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4215 } else {
4216 /* FIXME - verifier */
4217 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4218 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4220 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
4222 return token;
4225 static void
4226 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4228 MonoDynamicTable *table;
4229 MonoDynamicImage *assembly;
4230 MonoReflectionAssemblyBuilder *assemblyb;
4231 MonoDomain *domain;
4232 guint32 *values;
4233 int i;
4234 guint32 module_index;
4236 assemblyb = moduleb->assemblyb;
4237 assembly = moduleb->dynamic_image;
4238 domain = mono_object_domain (assemblyb);
4240 /* Emit ASSEMBLY table */
4241 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4242 alloc_table (table, 1);
4243 values = table->values + MONO_ASSEMBLY_SIZE;
4244 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4245 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4246 if (assemblyb->culture) {
4247 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4248 } else {
4249 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4251 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4252 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4253 set_version_from_string (assemblyb->version, values);
4255 /* Emit FILE + EXPORTED_TYPE table */
4256 module_index = 0;
4257 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4258 int j;
4259 MonoReflectionModuleBuilder *file_module =
4260 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4261 if (file_module != moduleb) {
4262 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4263 module_index ++;
4264 if (file_module->types) {
4265 for (j = 0; j < file_module->num_types; ++j) {
4266 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4267 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4272 if (assemblyb->loaded_modules) {
4273 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4274 MonoReflectionModule *file_module =
4275 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4276 mono_image_fill_file_table (domain, file_module, assembly);
4277 module_index ++;
4278 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4281 if (assemblyb->type_forwarders)
4282 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4284 /* Emit MANIFESTRESOURCE table */
4285 module_index = 0;
4286 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4287 int j;
4288 MonoReflectionModuleBuilder *file_module =
4289 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4290 /* The table for the main module is emitted later */
4291 if (file_module != moduleb) {
4292 module_index ++;
4293 if (file_module->resources) {
4294 int len = mono_array_length (file_module->resources);
4295 for (j = 0; j < len; ++j) {
4296 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4297 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4304 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4307 * mono_image_build_metadata() will fill the info in all the needed metadata tables
4308 * for the modulebuilder @moduleb.
4309 * At the end of the process, method and field tokens are fixed up and the
4310 * on-disk compressed metadata representation is created.
4312 void
4313 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4315 MonoDynamicTable *table;
4316 MonoDynamicImage *assembly;
4317 MonoReflectionAssemblyBuilder *assemblyb;
4318 MonoDomain *domain;
4319 GPtrArray *types;
4320 guint32 *values;
4321 int i, j;
4323 assemblyb = moduleb->assemblyb;
4324 assembly = moduleb->dynamic_image;
4325 domain = mono_object_domain (assemblyb);
4327 if (assembly->text_rva)
4328 return;
4330 assembly->text_rva = START_TEXT_RVA;
4332 if (moduleb->is_main) {
4333 mono_image_emit_manifest (moduleb);
4336 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4337 table->rows = 1; /* .<Module> */
4338 table->next_idx++;
4339 alloc_table (table, table->rows);
4341 * Set the first entry.
4343 values = table->values + table->columns;
4344 values [MONO_TYPEDEF_FLAGS] = 0;
4345 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4346 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4347 values [MONO_TYPEDEF_EXTENDS] = 0;
4348 values [MONO_TYPEDEF_FIELD_LIST] = 1;
4349 values [MONO_TYPEDEF_METHOD_LIST] = 1;
4352 * handle global methods
4353 * FIXME: test what to do when global methods are defined in multiple modules.
4355 if (moduleb->global_methods) {
4356 table = &assembly->tables [MONO_TABLE_METHOD];
4357 table->rows += mono_array_length (moduleb->global_methods);
4358 alloc_table (table, table->rows);
4359 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4360 mono_image_get_method_info (
4361 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4363 if (moduleb->global_fields) {
4364 table = &assembly->tables [MONO_TABLE_FIELD];
4365 table->rows += mono_array_length (moduleb->global_fields);
4366 alloc_table (table, table->rows);
4367 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4368 mono_image_get_field_info (
4369 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4372 table = &assembly->tables [MONO_TABLE_MODULE];
4373 alloc_table (table, 1);
4374 mono_image_fill_module_table (domain, moduleb, assembly);
4376 /* Collect all types into a list sorted by their table_idx */
4377 types = g_ptr_array_new ();
4379 if (moduleb->types)
4380 for (i = 0; i < moduleb->num_types; ++i) {
4381 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4382 collect_types (types, type);
4385 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
4386 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4387 table->rows += types->len;
4388 alloc_table (table, table->rows);
4391 * Emit type names + namespaces at one place inside the string heap,
4392 * so load_class_names () needs to touch fewer pages.
4394 for (i = 0; i < types->len; ++i) {
4395 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4396 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4398 for (i = 0; i < types->len; ++i) {
4399 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4400 string_heap_insert_mstring (&assembly->sheap, tb->name);
4403 for (i = 0; i < types->len; ++i) {
4404 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4405 mono_image_get_type_info (domain, type, assembly);
4409 * table->rows is already set above and in mono_image_fill_module_table.
4411 /* add all the custom attributes at the end, once all the indexes are stable */
4412 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4414 /* CAS assembly permissions */
4415 if (assemblyb->permissions_minimum)
4416 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4417 if (assemblyb->permissions_optional)
4418 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4419 if (assemblyb->permissions_refused)
4420 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4422 module_add_cattrs (assembly, moduleb);
4424 /* fixup tokens */
4425 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4427 /* Create the MethodImpl table. We do this after emitting all methods so we already know
4428 * the final tokens and don't need another fixup pass. */
4430 if (moduleb->global_methods) {
4431 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4432 MonoReflectionMethodBuilder *mb = mono_array_get (
4433 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4434 mono_image_add_methodimpl (assembly, mb);
4438 for (i = 0; i < types->len; ++i) {
4439 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4440 if (type->methods) {
4441 for (j = 0; j < type->num_methods; ++j) {
4442 MonoReflectionMethodBuilder *mb = mono_array_get (
4443 type->methods, MonoReflectionMethodBuilder*, j);
4445 mono_image_add_methodimpl (assembly, mb);
4450 g_ptr_array_free (types, TRUE);
4452 fixup_cattrs (assembly);
4455 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4457 void
4458 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4460 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4463 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4466 typedef struct {
4467 guint32 import_lookup_table;
4468 guint32 timestamp;
4469 guint32 forwarder;
4470 guint32 name_rva;
4471 guint32 import_address_table_rva;
4472 } MonoIDT;
4474 typedef struct {
4475 guint32 name_rva;
4476 guint32 flags;
4477 } MonoILT;
4479 #ifndef DISABLE_REFLECTION_EMIT
4482 * mono_image_insert_string:
4483 * @module: module builder object
4484 * @str: a string
4486 * Insert @str into the user string stream of @module.
4488 guint32
4489 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4491 MonoDynamicImage *assembly;
4492 guint32 idx;
4493 char buf [16];
4494 char *b = buf;
4496 MONO_ARCH_SAVE_REGS;
4498 if (!module->dynamic_image)
4499 mono_image_module_basic_init (module);
4501 assembly = module->dynamic_image;
4503 if (assembly->save) {
4504 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4505 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4506 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4508 char *swapped = g_malloc (2 * mono_string_length (str));
4509 const char *p = (const char*)mono_string_chars (str);
4511 swap_with_size (swapped, p, 2, mono_string_length (str));
4512 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4513 g_free (swapped);
4515 #else
4516 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4517 #endif
4518 mono_image_add_stream_data (&assembly->us, "", 1);
4519 } else {
4520 idx = assembly->us.index ++;
4523 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4525 return MONO_TOKEN_STRING | idx;
4528 guint32
4529 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4531 MonoClass *klass;
4532 guint32 token = 0;
4534 klass = obj->vtable->klass;
4535 if (strcmp (klass->name, "MonoMethod") == 0) {
4536 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4537 MonoMethodSignature *sig, *old;
4538 guint32 sig_token, parent;
4539 int nargs, i;
4541 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4543 nargs = mono_array_length (opt_param_types);
4544 old = mono_method_signature (method);
4545 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4547 sig->hasthis = old->hasthis;
4548 sig->explicit_this = old->explicit_this;
4549 sig->call_convention = old->call_convention;
4550 sig->generic_param_count = old->generic_param_count;
4551 sig->param_count = old->param_count + nargs;
4552 sig->sentinelpos = old->param_count;
4553 sig->ret = old->ret;
4555 for (i = 0; i < old->param_count; i++)
4556 sig->params [i] = old->params [i];
4558 for (i = 0; i < nargs; i++) {
4559 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4560 sig->params [old->param_count + i] = rt->type;
4563 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4564 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4565 parent >>= MONO_TYPEDEFORREF_BITS;
4567 parent <<= MONO_MEMBERREF_PARENT_BITS;
4568 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4570 sig_token = method_encode_signature (assembly, sig);
4571 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4572 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4573 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4574 ReflectionMethodBuilder rmb;
4575 guint32 parent, sig;
4576 char *name;
4578 reflection_methodbuilder_from_method_builder (&rmb, mb);
4579 rmb.opt_types = opt_param_types;
4581 sig = method_builder_encode_signature (assembly, &rmb);
4583 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
4584 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4586 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4587 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4589 name = mono_string_to_utf8 (rmb.name);
4590 token = mono_image_get_varargs_method_token (
4591 assembly, parent, name, sig);
4592 g_free (name);
4593 } else {
4594 g_error ("requested method token for %s\n", klass->name);
4597 return token;
4601 * mono_image_create_token:
4602 * @assembly: a dynamic assembly
4603 * @obj:
4604 * @register_token: Whenever to register the token in the assembly->tokens hash.
4606 * Get a token to insert in the IL code stream for the given MemberInfo.
4607 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
4608 * the table_idx-es were recomputed, so registering the token would overwrite an existing
4609 * entry.
4611 guint32
4612 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
4613 gboolean create_methodspec, gboolean register_token)
4615 MonoClass *klass;
4616 guint32 token = 0;
4618 klass = obj->vtable->klass;
4620 /* Check for user defined reflection objects */
4621 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
4622 if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0))
4623 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported")); \
4625 if (strcmp (klass->name, "MethodBuilder") == 0) {
4626 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4627 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4629 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
4630 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4631 else
4632 token = mono_image_get_methodbuilder_token (assembly, mb, create_methodspec);
4633 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4634 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4635 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4636 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4638 if (tb->module->dynamic_image == assembly && !tb->generic_params)
4639 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4640 else
4641 token = mono_image_get_ctorbuilder_token (assembly, mb);
4642 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4643 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4644 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4645 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4646 if (tb->generic_params) {
4647 token = mono_image_get_generic_field_token (assembly, fb);
4648 } else {
4649 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4651 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4652 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4653 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4654 } else if (strcmp (klass->name, "MonoType") == 0) {
4655 MonoReflectionType *tb = (MonoReflectionType *)obj;
4656 MonoClass *mc = mono_class_from_mono_type (tb->type);
4657 token = mono_metadata_token_from_dor (
4658 mono_image_typedef_or_ref_full (assembly, tb->type, mc->generic_container == NULL));
4659 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4660 MonoReflectionType *tb = (MonoReflectionType *)obj;
4661 token = mono_metadata_token_from_dor (
4662 mono_image_typedef_or_ref (assembly, tb->type));
4663 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4664 MonoReflectionType *tb = (MonoReflectionType *)obj;
4665 token = mono_metadata_token_from_dor (
4666 mono_image_typedef_or_ref (assembly, tb->type));
4667 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4668 strcmp (klass->name, "MonoMethod") == 0 ||
4669 strcmp (klass->name, "MonoGenericMethod") == 0 ||
4670 strcmp (klass->name, "MonoGenericCMethod") == 0) {
4671 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4672 if (m->method->is_inflated) {
4673 if (create_methodspec)
4674 token = mono_image_get_methodspec_token (assembly, m->method);
4675 else
4676 token = mono_image_get_inflated_method_token (assembly, m->method);
4677 } else if ((m->method->klass->image == &assembly->image) &&
4678 !m->method->klass->generic_class) {
4679 static guint32 method_table_idx = 0xffffff;
4680 if (m->method->klass->wastypebuilder) {
4681 /* we use the same token as the one that was assigned
4682 * to the Methodbuilder.
4683 * FIXME: do the equivalent for Fields.
4685 token = m->method->token;
4686 } else {
4688 * Each token should have a unique index, but the indexes are
4689 * assigned by managed code, so we don't know about them. An
4690 * easy solution is to count backwards...
4692 method_table_idx --;
4693 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4695 } else {
4696 token = mono_image_get_methodref_token (assembly, m->method, create_methodspec);
4698 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4699 } else if (strcmp (klass->name, "MonoField") == 0) {
4700 MonoReflectionField *f = (MonoReflectionField *)obj;
4701 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
4702 static guint32 field_table_idx = 0xffffff;
4703 field_table_idx --;
4704 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4705 } else {
4706 token = mono_image_get_fieldref_token (assembly, f);
4708 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4709 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4710 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4711 token = mono_image_get_array_token (assembly, m);
4712 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4713 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4714 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4715 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
4716 MonoReflectionType *tb = (MonoReflectionType *)obj;
4717 token = mono_metadata_token_from_dor (
4718 mono_image_typedef_or_ref (assembly, tb->type));
4719 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
4720 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
4721 token = mono_image_get_field_on_inst_token (assembly, f);
4722 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
4723 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
4724 token = mono_image_get_ctor_on_inst_token (assembly, c, create_methodspec);
4725 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
4726 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
4727 token = mono_image_get_method_on_inst_token (assembly, m, create_methodspec);
4728 } else {
4729 g_error ("requested token for %s\n", klass->name);
4732 if (register_token)
4733 mono_image_register_token (assembly, token, obj);
4735 return token;
4739 * mono_image_register_token:
4741 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
4742 * the Module.ResolveXXXToken () methods to work.
4744 void
4745 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
4747 MonoObject *prev = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4748 if (prev) {
4749 /* There could be multiple MethodInfo objects with the same token */
4750 //g_assert (prev == obj);
4751 } else {
4752 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4756 static MonoDynamicImage*
4757 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4759 static const guchar entrycode [16] = {0xff, 0x25, 0};
4760 MonoDynamicImage *image;
4761 int i;
4763 const char *version;
4765 if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
4766 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
4767 else
4768 version = mono_get_runtime_info ()->runtime_version;
4770 #if HAVE_BOEHM_GC
4771 image = GC_MALLOC (sizeof (MonoDynamicImage));
4772 #else
4773 image = g_new0 (MonoDynamicImage, 1);
4774 #endif
4776 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
4778 /*g_print ("created image %p\n", image);*/
4779 /* keep in sync with image.c */
4780 image->image.name = assembly_name;
4781 image->image.assembly_name = image->image.name; /* they may be different */
4782 image->image.module_name = module_name;
4783 image->image.version = g_strdup (version);
4784 image->image.md_version_major = 1;
4785 image->image.md_version_minor = 1;
4786 image->image.dynamic = TRUE;
4788 image->image.references = g_new0 (MonoAssembly*, 1);
4789 image->image.references [0] = NULL;
4791 mono_image_init (&image->image);
4793 image->token_fixups = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
4794 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
4795 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
4796 image->method_aux_hash = g_hash_table_new (NULL, NULL);
4797 image->handleref = g_hash_table_new (NULL, NULL);
4798 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4799 image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4800 image->methodspec = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
4801 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4802 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4803 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4804 image->gen_params = g_ptr_array_new ();
4806 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
4807 string_heap_init (&image->sheap);
4808 mono_image_add_stream_data (&image->us, "", 1);
4809 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4810 /* import tables... */
4811 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
4812 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4813 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4814 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4815 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4816 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4817 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4818 stream_data_align (&image->code);
4820 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4822 for (i=0; i < MONO_TABLE_NUM; ++i) {
4823 image->tables [i].next_idx = 1;
4824 image->tables [i].columns = table_sizes [i];
4827 image->image.assembly = (MonoAssembly*)assembly;
4828 image->run = assembly->run;
4829 image->save = assembly->save;
4830 image->pe_kind = 0x1; /* ILOnly */
4831 image->machine = 0x14c; /* I386 */
4833 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
4835 return image;
4837 #endif
4839 static void
4840 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
4842 g_free (key);
4845 void
4846 mono_dynamic_image_free (MonoDynamicImage *image)
4848 MonoDynamicImage *di = image;
4849 GList *list;
4850 int i;
4852 if (di->methodspec)
4853 mono_g_hash_table_destroy (di->methodspec);
4854 if (di->typespec)
4855 g_hash_table_destroy (di->typespec);
4856 if (di->typeref)
4857 g_hash_table_destroy (di->typeref);
4858 if (di->handleref)
4859 g_hash_table_destroy (di->handleref);
4860 if (di->tokens)
4861 mono_g_hash_table_destroy (di->tokens);
4862 if (di->generic_def_objects)
4863 mono_g_hash_table_destroy (di->generic_def_objects);
4864 if (di->blob_cache) {
4865 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
4866 g_hash_table_destroy (di->blob_cache);
4868 if (di->standalonesig_cache)
4869 g_hash_table_destroy (di->standalonesig_cache);
4870 for (list = di->array_methods; list; list = list->next) {
4871 ArrayMethod *am = (ArrayMethod *)list->data;
4872 g_free (am->sig);
4873 g_free (am->name);
4874 g_free (am);
4876 g_list_free (di->array_methods);
4877 if (di->gen_params) {
4878 for (i = 0; i < di->gen_params->len; i++) {
4879 GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
4880 if (entry->gparam->type.type) {
4881 MonoGenericParam *param = entry->gparam->type.type->data.generic_param;
4882 g_free ((char*)mono_generic_param_info (param)->name);
4883 g_free (param);
4885 g_free (entry);
4887 g_ptr_array_free (di->gen_params, TRUE);
4889 if (di->token_fixups)
4890 mono_g_hash_table_destroy (di->token_fixups);
4891 if (di->method_to_table_idx)
4892 g_hash_table_destroy (di->method_to_table_idx);
4893 if (di->field_to_table_idx)
4894 g_hash_table_destroy (di->field_to_table_idx);
4895 if (di->method_aux_hash)
4896 g_hash_table_destroy (di->method_aux_hash);
4897 g_free (di->strong_name);
4898 g_free (di->win32_res);
4899 if (di->public_key)
4900 g_free (di->public_key);
4902 /*g_print ("string heap destroy for image %p\n", di);*/
4903 mono_dynamic_stream_reset (&di->sheap);
4904 mono_dynamic_stream_reset (&di->code);
4905 mono_dynamic_stream_reset (&di->resources);
4906 mono_dynamic_stream_reset (&di->us);
4907 mono_dynamic_stream_reset (&di->blob);
4908 mono_dynamic_stream_reset (&di->tstream);
4909 mono_dynamic_stream_reset (&di->guid);
4910 for (i = 0; i < MONO_TABLE_NUM; ++i) {
4911 g_free (di->tables [i].values);
4915 #ifndef DISABLE_REFLECTION_EMIT
4918 * mono_image_basic_init:
4919 * @assembly: an assembly builder object
4921 * Create the MonoImage that represents the assembly builder and setup some
4922 * of the helper hash table and the basic metadata streams.
4924 void
4925 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4927 MonoDynamicAssembly *assembly;
4928 MonoDynamicImage *image;
4929 MonoDomain *domain = mono_object_domain (assemblyb);
4931 MONO_ARCH_SAVE_REGS;
4933 if (assemblyb->dynamic_assembly)
4934 return;
4936 #if HAVE_BOEHM_GC
4937 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4938 #else
4939 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
4940 #endif
4942 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
4944 assembly->assembly.ref_count = 1;
4945 assembly->assembly.dynamic = TRUE;
4946 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
4947 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4948 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4949 if (assemblyb->culture)
4950 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4951 else
4952 assembly->assembly.aname.culture = g_strdup ("");
4954 if (assemblyb->version) {
4955 char *vstr = mono_string_to_utf8 (assemblyb->version);
4956 char **version = g_strsplit (vstr, ".", 4);
4957 char **parts = version;
4958 assembly->assembly.aname.major = atoi (*parts++);
4959 assembly->assembly.aname.minor = atoi (*parts++);
4960 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
4961 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
4963 g_strfreev (version);
4964 g_free (vstr);
4965 } else {
4966 assembly->assembly.aname.major = 0;
4967 assembly->assembly.aname.minor = 0;
4968 assembly->assembly.aname.build = 0;
4969 assembly->assembly.aname.revision = 0;
4972 assembly->run = assemblyb->access != 2;
4973 assembly->save = assemblyb->access != 1;
4975 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4976 image->initial_image = TRUE;
4977 assembly->assembly.aname.name = image->image.name;
4978 assembly->assembly.image = &image->image;
4980 mono_domain_assemblies_lock (domain);
4981 domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
4982 mono_domain_assemblies_unlock (domain);
4984 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4986 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
4988 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4991 #endif /* !DISABLE_REFLECTION_EMIT */
4993 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4995 static int
4996 calc_section_size (MonoDynamicImage *assembly)
4998 int nsections = 0;
5000 /* alignment constraints */
5001 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5002 g_assert ((assembly->code.index % 4) == 0);
5003 assembly->meta_size += 3;
5004 assembly->meta_size &= ~3;
5005 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5006 g_assert ((assembly->resources.index % 4) == 0);
5008 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5009 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5010 nsections++;
5012 if (assembly->win32_res) {
5013 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5015 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5016 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5017 nsections++;
5020 assembly->sections [MONO_SECTION_RELOC].size = 12;
5021 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5022 nsections++;
5024 return nsections;
5027 typedef struct {
5028 guint32 id;
5029 guint32 offset;
5030 GSList *children;
5031 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5032 } ResTreeNode;
5034 static int
5035 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5037 ResTreeNode *t1 = (ResTreeNode*)a;
5038 ResTreeNode *t2 = (ResTreeNode*)b;
5040 return t1->id - t2->id;
5044 * resource_tree_create:
5046 * Organize the resources into a resource tree.
5048 static ResTreeNode *
5049 resource_tree_create (MonoArray *win32_resources)
5051 ResTreeNode *tree, *res_node, *type_node, *lang_node;
5052 GSList *l;
5053 int i;
5055 tree = g_new0 (ResTreeNode, 1);
5057 for (i = 0; i < mono_array_length (win32_resources); ++i) {
5058 MonoReflectionWin32Resource *win32_res =
5059 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5061 /* Create node */
5063 /* FIXME: BUG: this stores managed references in unmanaged memory */
5064 lang_node = g_new0 (ResTreeNode, 1);
5065 lang_node->id = win32_res->lang_id;
5066 lang_node->win32_res = win32_res;
5068 /* Create type node if neccesary */
5069 type_node = NULL;
5070 for (l = tree->children; l; l = l->next)
5071 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5072 type_node = (ResTreeNode*)l->data;
5073 break;
5076 if (!type_node) {
5077 type_node = g_new0 (ResTreeNode, 1);
5078 type_node->id = win32_res->res_type;
5081 * The resource types have to be sorted otherwise
5082 * Windows Explorer can't display the version information.
5084 tree->children = g_slist_insert_sorted (tree->children,
5085 type_node, resource_tree_compare_by_id);
5088 /* Create res node if neccesary */
5089 res_node = NULL;
5090 for (l = type_node->children; l; l = l->next)
5091 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5092 res_node = (ResTreeNode*)l->data;
5093 break;
5096 if (!res_node) {
5097 res_node = g_new0 (ResTreeNode, 1);
5098 res_node->id = win32_res->res_id;
5099 type_node->children = g_slist_append (type_node->children, res_node);
5102 res_node->children = g_slist_append (res_node->children, lang_node);
5105 return tree;
5109 * resource_tree_encode:
5111 * Encode the resource tree into the format used in the PE file.
5113 static void
5114 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5116 char *entries;
5117 MonoPEResourceDir dir;
5118 MonoPEResourceDirEntry dir_entry;
5119 MonoPEResourceDataEntry data_entry;
5120 GSList *l;
5121 guint32 res_id_entries;
5124 * For the format of the resource directory, see the article
5125 * "An In-Depth Look into the Win32 Portable Executable File Format" by
5126 * Matt Pietrek
5129 memset (&dir, 0, sizeof (dir));
5130 memset (&dir_entry, 0, sizeof (dir_entry));
5131 memset (&data_entry, 0, sizeof (data_entry));
5133 g_assert (sizeof (dir) == 16);
5134 g_assert (sizeof (dir_entry) == 8);
5135 g_assert (sizeof (data_entry) == 16);
5137 node->offset = p - begin;
5139 /* IMAGE_RESOURCE_DIRECTORY */
5140 res_id_entries = g_slist_length (node->children);
5141 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5143 memcpy (p, &dir, sizeof (dir));
5144 p += sizeof (dir);
5146 /* Reserve space for entries */
5147 entries = p;
5148 p += sizeof (dir_entry) * res_id_entries;
5150 /* Write children */
5151 for (l = node->children; l; l = l->next) {
5152 ResTreeNode *child = (ResTreeNode*)l->data;
5154 if (child->win32_res) {
5155 guint32 size;
5157 child->offset = p - begin;
5159 /* IMAGE_RESOURCE_DATA_ENTRY */
5160 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5161 size = mono_array_length (child->win32_res->res_data);
5162 data_entry.rde_size = GUINT32_TO_LE (size);
5164 memcpy (p, &data_entry, sizeof (data_entry));
5165 p += sizeof (data_entry);
5167 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5168 p += size;
5169 } else {
5170 resource_tree_encode (child, begin, p, &p);
5174 /* IMAGE_RESOURCE_ENTRY */
5175 for (l = node->children; l; l = l->next) {
5176 ResTreeNode *child = (ResTreeNode*)l->data;
5178 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5179 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5181 memcpy (entries, &dir_entry, sizeof (dir_entry));
5182 entries += sizeof (dir_entry);
5185 *endbuf = p;
5188 static void
5189 resource_tree_free (ResTreeNode * node)
5191 GSList * list;
5192 for (list = node->children; list; list = list->next)
5193 resource_tree_free ((ResTreeNode*)list->data);
5194 g_slist_free(node->children);
5195 g_free (node);
5198 static void
5199 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5201 char *buf;
5202 char *p;
5203 guint32 size, i;
5204 MonoReflectionWin32Resource *win32_res;
5205 ResTreeNode *tree;
5207 if (!assemblyb->win32_resources)
5208 return;
5211 * Resources are stored in a three level tree inside the PE file.
5212 * - level one contains a node for each type of resource
5213 * - level two contains a node for each resource
5214 * - level three contains a node for each instance of a resource for a
5215 * specific language.
5218 tree = resource_tree_create (assemblyb->win32_resources);
5220 /* Estimate the size of the encoded tree */
5221 size = 0;
5222 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5223 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5224 size += mono_array_length (win32_res->res_data);
5226 /* Directory structure */
5227 size += mono_array_length (assemblyb->win32_resources) * 256;
5228 p = buf = g_malloc (size);
5230 resource_tree_encode (tree, p, p, &p);
5232 g_assert (p - buf <= size);
5234 assembly->win32_res = g_malloc (p - buf);
5235 assembly->win32_res_size = p - buf;
5236 memcpy (assembly->win32_res, buf, p - buf);
5238 g_free (buf);
5239 resource_tree_free (tree);
5242 static void
5243 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5245 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5246 int i;
5248 p += sizeof (MonoPEResourceDir);
5249 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5250 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5251 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5252 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5253 fixup_resource_directory (res_section, child, rva);
5254 } else {
5255 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5256 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5259 p += sizeof (MonoPEResourceDirEntry);
5263 static void
5264 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5266 guint32 dummy;
5267 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5268 g_error ("WriteFile returned %d\n", GetLastError ());
5272 * mono_image_create_pefile:
5273 * @mb: a module builder object
5275 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
5276 * assembly->pefile where it can be easily retrieved later in chunks.
5278 void
5279 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5281 MonoMSDOSHeader *msdos;
5282 MonoDotNetHeader *header;
5283 MonoSectionTable *section;
5284 MonoCLIHeader *cli_header;
5285 guint32 size, image_size, virtual_base, text_offset;
5286 guint32 header_start, section_start, file_offset, virtual_offset;
5287 MonoDynamicImage *assembly;
5288 MonoReflectionAssemblyBuilder *assemblyb;
5289 MonoDynamicStream pefile_stream = {0};
5290 MonoDynamicStream *pefile = &pefile_stream;
5291 int i, nsections;
5292 guint32 *rva, value;
5293 guchar *p;
5294 static const unsigned char msheader[] = {
5295 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5296 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5297 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5298 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5299 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5300 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5301 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5302 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5305 assemblyb = mb->assemblyb;
5307 mono_image_basic_init (assemblyb);
5308 assembly = mb->dynamic_image;
5310 assembly->pe_kind = assemblyb->pe_kind;
5311 assembly->machine = assemblyb->machine;
5312 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5313 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5315 mono_image_build_metadata (mb);
5317 if (mb->is_main && assemblyb->resources) {
5318 int len = mono_array_length (assemblyb->resources);
5319 for (i = 0; i < len; ++i)
5320 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5323 if (mb->resources) {
5324 int len = mono_array_length (mb->resources);
5325 for (i = 0; i < len; ++i)
5326 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5329 build_compressed_metadata (assembly);
5331 if (mb->is_main)
5332 assembly_add_win32_resources (assembly, assemblyb);
5334 nsections = calc_section_size (assembly);
5336 /* The DOS header and stub */
5337 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5338 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5340 /* the dotnet header */
5341 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5343 /* the section tables */
5344 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5346 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5347 virtual_offset = VIRT_ALIGN;
5348 image_size = 0;
5350 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5351 if (!assembly->sections [i].size)
5352 continue;
5353 /* align offsets */
5354 file_offset += FILE_ALIGN - 1;
5355 file_offset &= ~(FILE_ALIGN - 1);
5356 virtual_offset += VIRT_ALIGN - 1;
5357 virtual_offset &= ~(VIRT_ALIGN - 1);
5359 assembly->sections [i].offset = file_offset;
5360 assembly->sections [i].rva = virtual_offset;
5362 file_offset += assembly->sections [i].size;
5363 virtual_offset += assembly->sections [i].size;
5364 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5367 file_offset += FILE_ALIGN - 1;
5368 file_offset &= ~(FILE_ALIGN - 1);
5370 image_size += section_start + sizeof (MonoSectionTable) * nsections;
5372 /* back-patch info */
5373 msdos = (MonoMSDOSHeader*)pefile->data;
5374 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5376 header = (MonoDotNetHeader*)(pefile->data + header_start);
5377 header->pesig [0] = 'P';
5378 header->pesig [1] = 'E';
5380 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5381 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5382 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5383 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5384 if (assemblyb->pekind == 1) {
5385 /* it's a dll */
5386 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5387 } else {
5388 /* it's an exe */
5389 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5392 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5394 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5395 header->pe.pe_major = 6;
5396 header->pe.pe_minor = 0;
5397 size = assembly->sections [MONO_SECTION_TEXT].size;
5398 size += FILE_ALIGN - 1;
5399 size &= ~(FILE_ALIGN - 1);
5400 header->pe.pe_code_size = GUINT32_FROM_LE(size);
5401 size = assembly->sections [MONO_SECTION_RSRC].size;
5402 size += FILE_ALIGN - 1;
5403 size &= ~(FILE_ALIGN - 1);
5404 header->pe.pe_data_size = GUINT32_FROM_LE(size);
5405 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5406 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5407 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5408 /* pe_rva_entry_point always at the beginning of the text section */
5409 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5411 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5412 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5413 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5414 header->nt.pe_os_major = GUINT16_FROM_LE (4);
5415 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5416 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5417 size = section_start;
5418 size += FILE_ALIGN - 1;
5419 size &= ~(FILE_ALIGN - 1);
5420 header->nt.pe_header_size = GUINT32_FROM_LE (size);
5421 size = image_size;
5422 size += VIRT_ALIGN - 1;
5423 size &= ~(VIRT_ALIGN - 1);
5424 header->nt.pe_image_size = GUINT32_FROM_LE (size);
5427 // Translate the PEFileKind value to the value expected by the Windows loader
5430 short kind;
5433 // PEFileKinds.Dll == 1
5434 // PEFileKinds.ConsoleApplication == 2
5435 // PEFileKinds.WindowApplication == 3
5437 // need to get:
5438 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5439 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5441 if (assemblyb->pekind == 3)
5442 kind = 2;
5443 else
5444 kind = 3;
5446 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5448 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5449 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5450 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5451 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5452 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5453 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
5455 /* fill data directory entries */
5457 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
5458 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5460 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
5461 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
5463 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
5464 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
5465 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
5466 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5467 /* patch entrypoint name */
5468 if (assemblyb->pekind == 1)
5469 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
5470 else
5471 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
5472 /* patch imported function RVA name */
5473 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
5474 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
5476 /* the import table */
5477 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
5478 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
5479 /* patch imported dll RVA name and other entries in the dir */
5480 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
5481 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
5482 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
5483 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5484 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
5485 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
5487 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
5488 value = (assembly->text_rva + assembly->imp_names_offset);
5489 *p++ = (value) & 0xff;
5490 *p++ = (value >> 8) & (0xff);
5491 *p++ = (value >> 16) & (0xff);
5492 *p++ = (value >> 24) & (0xff);
5494 /* the CLI header info */
5495 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
5496 cli_header->ch_size = GUINT32_FROM_LE (72);
5497 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
5498 if (mono_framework_version () > 1)
5499 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
5500 else
5501 cli_header->ch_runtime_minor = GUINT16_FROM_LE (0);
5502 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
5503 if (assemblyb->entry_point) {
5504 guint32 table_idx = 0;
5505 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
5506 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
5507 table_idx = methodb->table_idx;
5508 } else {
5509 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
5511 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
5512 } else {
5513 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
5515 /* The embedded managed resources */
5516 text_offset = assembly->text_rva + assembly->code.index;
5517 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
5518 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
5519 text_offset += assembly->resources.index;
5520 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
5521 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
5522 text_offset += assembly->meta_size;
5523 if (assembly->strong_name_size) {
5524 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
5525 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
5526 text_offset += assembly->strong_name_size;
5529 /* write the section tables and section content */
5530 section = (MonoSectionTable*)(pefile->data + section_start);
5531 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5532 static const char section_names [][7] = {
5533 ".text", ".rsrc", ".reloc"
5535 if (!assembly->sections [i].size)
5536 continue;
5537 strcpy (section->st_name, section_names [i]);
5538 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5539 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5540 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5541 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5542 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5543 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5544 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5545 section ++;
5548 checked_write_file (file, pefile->data, pefile->index);
5550 mono_dynamic_stream_reset (pefile);
5552 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5553 if (!assembly->sections [i].size)
5554 continue;
5556 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5557 g_error ("SetFilePointer returned %d\n", GetLastError ());
5559 switch (i) {
5560 case MONO_SECTION_TEXT:
5561 /* patch entry point */
5562 p = (guchar*)(assembly->code.data + 2);
5563 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5564 *p++ = (value) & 0xff;
5565 *p++ = (value >> 8) & 0xff;
5566 *p++ = (value >> 16) & 0xff;
5567 *p++ = (value >> 24) & 0xff;
5569 checked_write_file (file, assembly->code.data, assembly->code.index);
5570 checked_write_file (file, assembly->resources.data, assembly->resources.index);
5571 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5572 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5575 g_free (assembly->image.raw_metadata);
5576 break;
5577 case MONO_SECTION_RELOC: {
5578 struct {
5579 guint32 page_rva;
5580 guint32 block_size;
5581 guint16 type_and_offset;
5582 guint16 term;
5583 } reloc;
5585 g_assert (sizeof (reloc) == 12);
5587 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5588 reloc.block_size = GUINT32_FROM_LE (12);
5591 * the entrypoint is always at the start of the text section
5592 * 3 is IMAGE_REL_BASED_HIGHLOW
5593 * 2 is patch_size_rva - text_rva
5595 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5596 reloc.term = 0;
5598 checked_write_file (file, &reloc, sizeof (reloc));
5600 break;
5602 case MONO_SECTION_RSRC:
5603 if (assembly->win32_res) {
5605 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5606 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5607 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5609 break;
5610 default:
5611 g_assert_not_reached ();
5615 /* check that the file is properly padded */
5616 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5617 g_error ("SetFilePointer returned %d\n", GetLastError ());
5618 if (! SetEndOfFile (file))
5619 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5621 mono_dynamic_stream_reset (&assembly->code);
5622 mono_dynamic_stream_reset (&assembly->us);
5623 mono_dynamic_stream_reset (&assembly->blob);
5624 mono_dynamic_stream_reset (&assembly->guid);
5625 mono_dynamic_stream_reset (&assembly->sheap);
5627 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5628 g_hash_table_destroy (assembly->blob_cache);
5629 assembly->blob_cache = NULL;
5632 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5634 void
5635 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5637 g_assert_not_reached ();
5640 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5642 #ifndef DISABLE_REFLECTION_EMIT
5644 MonoReflectionModule *
5645 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5647 char *name;
5648 MonoImage *image;
5649 MonoImageOpenStatus status;
5650 MonoDynamicAssembly *assembly;
5651 guint32 module_count;
5652 MonoImage **new_modules;
5653 gboolean *new_modules_loaded;
5655 name = mono_string_to_utf8 (fileName);
5657 image = mono_image_open (name, &status);
5658 if (!image) {
5659 MonoException *exc;
5660 if (status == MONO_IMAGE_ERROR_ERRNO)
5661 exc = mono_get_exception_file_not_found (fileName);
5662 else
5663 exc = mono_get_exception_bad_image_format (name);
5664 g_free (name);
5665 mono_raise_exception (exc);
5668 g_free (name);
5670 assembly = ab->dynamic_assembly;
5671 image->assembly = (MonoAssembly*)assembly;
5673 module_count = image->assembly->image->module_count;
5674 new_modules = g_new0 (MonoImage *, module_count + 1);
5675 new_modules_loaded = g_new0 (gboolean, module_count + 1);
5677 if (image->assembly->image->modules)
5678 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5679 if (image->assembly->image->modules_loaded)
5680 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
5681 new_modules [module_count] = image;
5682 new_modules_loaded [module_count] = TRUE;
5683 mono_image_addref (image);
5685 g_free (image->assembly->image->modules);
5686 image->assembly->image->modules = new_modules;
5687 image->assembly->image->modules_loaded = new_modules_loaded;
5688 image->assembly->image->module_count ++;
5690 mono_assembly_load_references (image, &status);
5691 if (status) {
5692 mono_image_close (image);
5693 mono_raise_exception (mono_get_exception_file_not_found (fileName));
5696 return mono_module_get_object (mono_domain_get (), image);
5699 #endif /* DISABLE_REFLECTION_EMIT */
5702 * We need to return always the same object for MethodInfo, FieldInfo etc..
5703 * but we need to consider the reflected type.
5704 * type uses a different hash, since it uses custom hash/equal functions.
5707 typedef struct {
5708 gpointer item;
5709 MonoClass *refclass;
5710 } ReflectedEntry;
5712 static gboolean
5713 reflected_equal (gconstpointer a, gconstpointer b) {
5714 const ReflectedEntry *ea = a;
5715 const ReflectedEntry *eb = b;
5717 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
5720 static guint
5721 reflected_hash (gconstpointer a) {
5722 const ReflectedEntry *ea = a;
5723 return mono_aligned_addr_hash (ea->item);
5726 #define CHECK_OBJECT(t,p,k) \
5727 do { \
5728 t _obj; \
5729 ReflectedEntry e; \
5730 e.item = (p); \
5731 e.refclass = (k); \
5732 mono_domain_lock (domain); \
5733 if (!domain->refobject_hash) \
5734 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5735 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
5736 mono_domain_unlock (domain); \
5737 return _obj; \
5739 mono_domain_unlock (domain); \
5740 } while (0)
5742 #ifdef HAVE_BOEHM_GC
5743 /* ReflectedEntry doesn't need to be GC tracked */
5744 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
5745 #define FREE_REFENTRY(entry) g_free ((entry))
5746 #define REFENTRY_REQUIRES_CLEANUP
5747 #else
5748 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5749 /* FIXME: */
5750 #define FREE_REFENTRY(entry)
5751 #endif
5753 #define CACHE_OBJECT(t,p,o,k) \
5754 do { \
5755 t _obj; \
5756 ReflectedEntry pe; \
5757 pe.item = (p); \
5758 pe.refclass = (k); \
5759 mono_domain_lock (domain); \
5760 if (!domain->refobject_hash) \
5761 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5762 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
5763 if (!_obj) { \
5764 ReflectedEntry *e = ALLOC_REFENTRY; \
5765 e->item = (p); \
5766 e->refclass = (k); \
5767 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
5768 _obj = o; \
5770 mono_domain_unlock (domain); \
5771 return _obj; \
5772 } while (0)
5774 static void
5775 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
5777 mono_domain_lock (domain);
5778 if (domain->refobject_hash) {
5779 ReflectedEntry pe;
5780 gpointer orig_pe, orig_value;
5782 pe.item = o;
5783 pe.refclass = klass;
5784 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
5785 mono_g_hash_table_remove (domain->refobject_hash, &pe);
5786 FREE_REFENTRY (orig_pe);
5789 mono_domain_unlock (domain);
5792 #ifdef REFENTRY_REQUIRES_CLEANUP
5793 static void
5794 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
5796 FREE_REFENTRY (key);
5798 #endif
5800 void
5801 mono_reflection_cleanup_domain (MonoDomain *domain)
5803 if (domain->refobject_hash) {
5804 /*let's avoid scanning the whole hashtable if not needed*/
5805 #ifdef REFENTRY_REQUIRES_CLEANUP
5806 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
5807 #endif
5808 mono_g_hash_table_destroy (domain->refobject_hash);
5809 domain->refobject_hash = NULL;
5813 #ifndef DISABLE_REFLECTION_EMIT
5814 static gpointer
5815 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
5817 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5820 static gpointer
5821 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5823 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
5826 void
5827 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5829 MonoDynamicImage *image = moduleb->dynamic_image;
5830 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5831 if (!image) {
5832 int module_count;
5833 MonoImage **new_modules;
5834 MonoImage *ass;
5836 * FIXME: we already created an image in mono_image_basic_init (), but
5837 * we don't know which module it belongs to, since that is only
5838 * determined at assembly save time.
5840 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5841 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5843 moduleb->module.image = &image->image;
5844 moduleb->dynamic_image = image;
5845 register_module (mono_object_domain (moduleb), moduleb, image);
5847 /* register the module with the assembly */
5848 ass = ab->dynamic_assembly->assembly.image;
5849 module_count = ass->module_count;
5850 new_modules = g_new0 (MonoImage *, module_count + 1);
5852 if (ass->modules)
5853 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
5854 new_modules [module_count] = &image->image;
5855 mono_image_addref (&image->image);
5857 g_free (ass->modules);
5858 ass->modules = new_modules;
5859 ass->module_count ++;
5863 #endif
5866 * mono_assembly_get_object:
5867 * @domain: an app domain
5868 * @assembly: an assembly
5870 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5872 MonoReflectionAssembly*
5873 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5875 static MonoClass *System_Reflection_Assembly;
5876 MonoReflectionAssembly *res;
5878 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5879 if (!System_Reflection_Assembly)
5880 System_Reflection_Assembly = mono_class_from_name (
5881 mono_defaults.corlib, "System.Reflection", "Assembly");
5882 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5883 res->assembly = assembly;
5885 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5890 MonoReflectionModule*
5891 mono_module_get_object (MonoDomain *domain, MonoImage *image)
5893 static MonoClass *System_Reflection_Module;
5894 MonoReflectionModule *res;
5895 char* basename;
5897 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5898 if (!System_Reflection_Module)
5899 System_Reflection_Module = mono_class_from_name (
5900 mono_defaults.corlib, "System.Reflection", "Module");
5901 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5903 res->image = image;
5904 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5906 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
5907 basename = g_path_get_basename (image->name);
5908 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
5909 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
5911 g_free (basename);
5913 if (image->assembly->image == image) {
5914 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5915 } else {
5916 int i;
5917 res->token = 0;
5918 if (image->assembly->image->modules) {
5919 for (i = 0; i < image->assembly->image->module_count; i++) {
5920 if (image->assembly->image->modules [i] == image)
5921 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5923 g_assert (res->token);
5927 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
5930 MonoReflectionModule*
5931 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5933 static MonoClass *System_Reflection_Module;
5934 MonoReflectionModule *res;
5935 MonoTableInfo *table;
5936 guint32 cols [MONO_FILE_SIZE];
5937 const char *name;
5938 guint32 i, name_idx;
5939 const char *val;
5941 if (!System_Reflection_Module)
5942 System_Reflection_Module = mono_class_from_name (
5943 mono_defaults.corlib, "System.Reflection", "Module");
5944 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5946 table = &image->tables [MONO_TABLE_FILE];
5947 g_assert (table_index < table->rows);
5948 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5950 res->image = NULL;
5951 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5952 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5954 /* Check whenever the row has a corresponding row in the moduleref table */
5955 table = &image->tables [MONO_TABLE_MODULEREF];
5956 for (i = 0; i < table->rows; ++i) {
5957 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5958 val = mono_metadata_string_heap (image, name_idx);
5959 if (strcmp (val, name) == 0)
5960 res->image = image->modules [i];
5963 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
5964 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
5965 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
5966 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5967 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5969 return res;
5972 static gboolean
5973 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5975 if ((t1->type != t2->type) ||
5976 (t1->byref != t2->byref))
5977 return FALSE;
5979 switch (t1->type) {
5980 case MONO_TYPE_VOID:
5981 case MONO_TYPE_BOOLEAN:
5982 case MONO_TYPE_CHAR:
5983 case MONO_TYPE_I1:
5984 case MONO_TYPE_U1:
5985 case MONO_TYPE_I2:
5986 case MONO_TYPE_U2:
5987 case MONO_TYPE_I4:
5988 case MONO_TYPE_U4:
5989 case MONO_TYPE_I8:
5990 case MONO_TYPE_U8:
5991 case MONO_TYPE_R4:
5992 case MONO_TYPE_R8:
5993 case MONO_TYPE_STRING:
5994 case MONO_TYPE_I:
5995 case MONO_TYPE_U:
5996 case MONO_TYPE_OBJECT:
5997 case MONO_TYPE_TYPEDBYREF:
5998 return TRUE;
5999 case MONO_TYPE_VALUETYPE:
6000 case MONO_TYPE_CLASS:
6001 case MONO_TYPE_SZARRAY:
6002 return t1->data.klass == t2->data.klass;
6003 case MONO_TYPE_PTR:
6004 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
6005 case MONO_TYPE_ARRAY:
6006 if (t1->data.array->rank != t2->data.array->rank)
6007 return FALSE;
6008 return t1->data.array->eklass == t2->data.array->eklass;
6009 case MONO_TYPE_GENERICINST: {
6010 int i;
6011 MonoGenericInst *i1 = t1->data.generic_class->context.class_inst;
6012 MonoGenericInst *i2 = t2->data.generic_class->context.class_inst;
6013 if (i1->type_argc != i2->type_argc)
6014 return FALSE;
6015 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
6016 &t2->data.generic_class->container_class->byval_arg))
6017 return FALSE;
6018 /* FIXME: we should probably just compare the instance pointers directly. */
6019 for (i = 0; i < i1->type_argc; ++i) {
6020 if (!mono_metadata_type_equal (i1->type_argv [i], i2->type_argv [i]))
6021 return FALSE;
6023 return TRUE;
6025 case MONO_TYPE_VAR:
6026 case MONO_TYPE_MVAR:
6027 return t1->data.generic_param == t2->data.generic_param;
6028 default:
6029 g_error ("implement type compare for %0x!", t1->type);
6030 return FALSE;
6033 return FALSE;
6036 static guint
6037 mymono_metadata_type_hash (MonoType *t1)
6039 guint hash;
6041 hash = t1->type;
6043 hash |= t1->byref << 6; /* do not collide with t1->type values */
6044 switch (t1->type) {
6045 case MONO_TYPE_VALUETYPE:
6046 case MONO_TYPE_CLASS:
6047 case MONO_TYPE_SZARRAY:
6048 /* check if the distribution is good enough */
6049 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
6050 case MONO_TYPE_PTR:
6051 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
6052 case MONO_TYPE_GENERICINST: {
6053 int i;
6054 MonoGenericInst *inst = t1->data.generic_class->context.class_inst;
6055 hash += g_str_hash (t1->data.generic_class->container_class->name);
6056 hash *= 13;
6057 for (i = 0; i < inst->type_argc; ++i) {
6058 hash += mymono_metadata_type_hash (inst->type_argv [i]);
6059 hash *= 13;
6061 return hash;
6064 return hash;
6067 static MonoReflectionGenericClass*
6068 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
6070 static MonoClass *System_Reflection_MonoGenericClass;
6071 MonoReflectionGenericClass *res;
6072 MonoClass *klass, *gklass;
6074 if (!System_Reflection_MonoGenericClass) {
6075 System_Reflection_MonoGenericClass = mono_class_from_name (
6076 mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
6077 g_assert (System_Reflection_MonoGenericClass);
6080 klass = mono_class_from_mono_type (geninst);
6081 gklass = klass->generic_class->container_class;
6083 mono_class_init (klass);
6085 #ifdef HAVE_SGEN_GC
6086 res = (MonoReflectionGenericClass *) mono_gc_alloc_pinned_obj (mono_class_vtable (domain, System_Reflection_MonoGenericClass), mono_class_instance_size (System_Reflection_MonoGenericClass));
6087 #else
6088 res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
6089 #endif
6091 res->type.type = geninst;
6092 g_assert (gklass->reflection_info);
6093 g_assert (!strcmp (((MonoObject*)gklass->reflection_info)->vtable->klass->name, "TypeBuilder"));
6094 MONO_OBJECT_SETREF (res, generic_type, gklass->reflection_info);
6096 return res;
6099 static gboolean
6100 verify_safe_for_managed_space (MonoType *type)
6102 switch (type->type) {
6103 #ifdef DEBUG_HARDER
6104 case MONO_TYPE_ARRAY:
6105 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6106 case MONO_TYPE_PTR:
6107 return verify_safe_for_managed_space (type->data.type);
6108 case MONO_TYPE_SZARRAY:
6109 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6110 case MONO_TYPE_GENERICINST: {
6111 MonoGenericInst *inst = type->data.generic_class->inst;
6112 int i;
6113 if (!inst->is_open)
6114 break;
6115 for (i = 0; i < inst->type_argc; ++i)
6116 if (!verify_safe_for_managed_space (inst->type_argv [i]))
6117 return FALSE;
6118 break;
6120 #endif
6121 case MONO_TYPE_VAR:
6122 case MONO_TYPE_MVAR:
6123 return TRUE;
6125 return TRUE;
6129 * mono_type_get_object:
6130 * @domain: an app domain
6131 * @type: a type
6133 * Return an System.MonoType object representing the type @type.
6135 MonoReflectionType*
6136 mono_type_get_object (MonoDomain *domain, MonoType *type)
6138 MonoReflectionType *res;
6139 MonoClass *klass = mono_class_from_mono_type (type);
6141 /*we must avoid using @type as it might have come
6142 * from a mono_metadata_type_dup and the caller
6143 * expects that is can be freed.
6144 * Using the right type from
6146 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6148 /* void is very common */
6149 if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6150 return (MonoReflectionType*)domain->typeof_void;
6153 * If the vtable of the given class was already created, we can use
6154 * the MonoType from there and avoid all locking and hash table lookups.
6156 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6157 * that the resulting object is diferent.
6159 if (type == &klass->byval_arg && !klass->image->dynamic) {
6160 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6161 if (vtable && vtable->type)
6162 return vtable->type;
6165 mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6166 mono_domain_lock (domain);
6167 if (!domain->type_hash)
6168 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash,
6169 (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
6170 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
6171 mono_domain_unlock (domain);
6172 mono_loader_unlock ();
6173 return res;
6175 /* Create a MonoGenericClass object for instantiations of not finished TypeBuilders */
6176 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder) {
6177 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
6178 mono_g_hash_table_insert (domain->type_hash, type, res);
6179 mono_domain_unlock (domain);
6180 mono_loader_unlock ();
6181 return res;
6184 if (!verify_safe_for_managed_space (type)) {
6185 mono_domain_unlock (domain);
6186 mono_loader_unlock ();
6187 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6190 if (klass->reflection_info && !klass->wastypebuilder) {
6191 /* g_assert_not_reached (); */
6192 /* should this be considered an error condition? */
6193 if (!type->byref) {
6194 mono_domain_unlock (domain);
6195 mono_loader_unlock ();
6196 return klass->reflection_info;
6199 // FIXME: Get rid of this, do it in the icalls for Type
6200 mono_class_init (klass);
6201 #ifdef HAVE_SGEN_GC
6202 res = (MonoReflectionType *)mono_gc_alloc_pinned_obj (mono_class_vtable (domain, mono_defaults.monotype_class), mono_class_instance_size (mono_defaults.monotype_class));
6203 #else
6204 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
6205 #endif
6206 res->type = type;
6207 mono_g_hash_table_insert (domain->type_hash, type, res);
6209 if (type->type == MONO_TYPE_VOID)
6210 MONO_OBJECT_SETREF (domain, typeof_void, res);
6212 mono_domain_unlock (domain);
6213 mono_loader_unlock ();
6214 return res;
6218 * mono_method_get_object:
6219 * @domain: an app domain
6220 * @method: a method
6221 * @refclass: the reflected type (can be NULL)
6223 * Return an System.Reflection.MonoMethod object representing the method @method.
6225 MonoReflectionMethod*
6226 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6229 * We use the same C representation for methods and constructors, but the type
6230 * name in C# is different.
6232 static MonoClass *System_Reflection_MonoMethod = NULL;
6233 static MonoClass *System_Reflection_MonoCMethod = NULL;
6234 static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6235 static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6236 MonoClass *klass;
6237 MonoReflectionMethod *ret;
6239 if (method->is_inflated) {
6240 MonoReflectionGenericMethod *gret;
6242 refclass = method->klass;
6243 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6244 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6245 if (!System_Reflection_MonoGenericCMethod)
6246 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6247 klass = System_Reflection_MonoGenericCMethod;
6248 } else {
6249 if (!System_Reflection_MonoGenericMethod)
6250 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6251 klass = System_Reflection_MonoGenericMethod;
6253 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6254 gret->method.method = method;
6255 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6256 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6257 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6260 if (!refclass)
6261 refclass = method->klass;
6263 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6264 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6265 if (!System_Reflection_MonoCMethod)
6266 System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6267 klass = System_Reflection_MonoCMethod;
6269 else {
6270 if (!System_Reflection_MonoMethod)
6271 System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6272 klass = System_Reflection_MonoMethod;
6274 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6275 ret->method = method;
6276 MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6277 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6281 * mono_method_clear_object:
6283 * Clear the cached reflection objects for the dynamic method METHOD.
6285 void
6286 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
6288 g_assert (method->dynamic);
6290 clear_cached_object (domain, method, method->klass);
6291 /* Added by mono_param_get_objects () */
6292 clear_cached_object (domain, &(method->signature), NULL);
6296 * mono_field_get_object:
6297 * @domain: an app domain
6298 * @klass: a type
6299 * @field: a field
6301 * Return an System.Reflection.MonoField object representing the field @field
6302 * in class @klass.
6304 MonoReflectionField*
6305 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6307 MonoReflectionField *res;
6308 static MonoClass *monofield_klass;
6310 CHECK_OBJECT (MonoReflectionField *, field, klass);
6311 if (!monofield_klass)
6312 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6313 res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6314 res->klass = klass;
6315 res->field = field;
6316 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6317 if (is_field_on_inst (field))
6318 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6319 else
6320 res->attrs = field->type->attrs;
6321 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6322 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6326 * mono_property_get_object:
6327 * @domain: an app domain
6328 * @klass: a type
6329 * @property: a property
6331 * Return an System.Reflection.MonoProperty object representing the property @property
6332 * in class @klass.
6334 MonoReflectionProperty*
6335 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6337 MonoReflectionProperty *res;
6338 static MonoClass *monoproperty_klass;
6340 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6341 if (!monoproperty_klass)
6342 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6343 res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6344 res->klass = klass;
6345 res->property = property;
6346 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6350 * mono_event_get_object:
6351 * @domain: an app domain
6352 * @klass: a type
6353 * @event: a event
6355 * Return an System.Reflection.MonoEvent object representing the event @event
6356 * in class @klass.
6358 MonoReflectionEvent*
6359 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6361 MonoReflectionEvent *res;
6362 MonoReflectionMonoEvent *mono_event;
6363 static MonoClass *monoevent_klass;
6365 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6366 if (!monoevent_klass)
6367 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6368 mono_event = (MonoReflectionMonoEvent *)mono_object_new (domain, monoevent_klass);
6369 mono_event->klass = klass;
6370 mono_event->event = event;
6371 res = (MonoReflectionEvent*)mono_event;
6372 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6376 * mono_get_reflection_missing_object:
6377 * @domain: Domain where the object lives
6379 * Returns the System.Reflection.Missing.Value singleton object
6380 * (of type System.Reflection.Missing).
6382 * Used as the value for ParameterInfo.DefaultValue when Optional
6383 * is present
6385 static MonoObject *
6386 mono_get_reflection_missing_object (MonoDomain *domain)
6388 MonoObject *obj;
6389 static MonoClassField *missing_value_field = NULL;
6391 if (!missing_value_field) {
6392 MonoClass *missing_klass;
6393 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6394 mono_class_init (missing_klass);
6395 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6396 g_assert (missing_value_field);
6398 obj = mono_field_get_value_object (domain, missing_value_field, NULL);
6399 g_assert (obj);
6400 return obj;
6403 static MonoObject*
6404 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6406 if (!*dbnull)
6407 *dbnull = mono_get_dbnull_object (domain);
6408 return *dbnull;
6411 static MonoObject*
6412 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6414 if (!*reflection_missing)
6415 *reflection_missing = mono_get_reflection_missing_object (domain);
6416 return *reflection_missing;
6420 * mono_param_get_objects:
6421 * @domain: an app domain
6422 * @method: a method
6424 * Return an System.Reflection.ParameterInfo array object representing the parameters
6425 * in the method @method.
6427 MonoArray*
6428 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6430 static MonoClass *System_Reflection_ParameterInfo;
6431 static MonoClass *System_Reflection_ParameterInfo_array;
6432 MonoArray *res = NULL;
6433 MonoReflectionMethod *member = NULL;
6434 MonoReflectionParameter *param = NULL;
6435 char **names, **blobs = NULL;
6436 guint32 *types = NULL;
6437 MonoType *type = NULL;
6438 MonoObject *dbnull = NULL;
6439 MonoObject *missing = NULL;
6440 MonoMarshalSpec **mspecs;
6441 MonoMethodSignature *sig;
6442 MonoVTable *pinfo_vtable;
6443 int i;
6445 if (!System_Reflection_ParameterInfo_array) {
6446 MonoClass *klass;
6448 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6449 mono_memory_barrier ();
6450 System_Reflection_ParameterInfo = klass;
6452 klass = mono_array_class_get (klass, 1);
6453 mono_memory_barrier ();
6454 System_Reflection_ParameterInfo_array = klass;
6457 if (!mono_method_signature (method)->param_count)
6458 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6460 /* Note: the cache is based on the address of the signature into the method
6461 * since we already cache MethodInfos with the method as keys.
6463 CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
6465 sig = mono_method_signature (method);
6466 member = mono_method_get_object (domain, method, refclass);
6467 names = g_new (char *, sig->param_count);
6468 mono_method_get_param_names (method, (const char **) names);
6470 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
6471 mono_method_get_marshal_info (method, mspecs);
6473 res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
6474 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
6475 for (i = 0; i < sig->param_count; ++i) {
6476 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
6477 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
6478 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
6479 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
6480 param->PositionImpl = i;
6481 param->AttrsImpl = sig->params [i]->attrs;
6483 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
6484 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6485 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6486 else
6487 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6488 } else {
6490 if (!blobs) {
6491 blobs = g_new0 (char *, sig->param_count);
6492 types = g_new0 (guint32, sig->param_count);
6493 get_default_param_value_blobs (method, blobs, types);
6496 /* Build MonoType for the type from the Constant Table */
6497 if (!type)
6498 type = g_new0 (MonoType, 1);
6499 type->type = types [i];
6500 type->data.klass = NULL;
6501 if (types [i] == MONO_TYPE_CLASS)
6502 type->data.klass = mono_defaults.object_class;
6503 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
6504 /* For enums, types [i] contains the base type */
6506 type->type = MONO_TYPE_VALUETYPE;
6507 type->data.klass = mono_class_from_mono_type (sig->params [i]);
6508 } else
6509 type->data.klass = mono_class_from_mono_type (type);
6511 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
6513 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6514 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
6515 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6516 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6517 else
6518 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6523 if (mspecs [i + 1])
6524 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
6526 mono_array_setref (res, i, param);
6528 g_free (names);
6529 g_free (blobs);
6530 g_free (types);
6531 g_free (type);
6533 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
6534 if (mspecs [i])
6535 mono_metadata_free_marshal_spec (mspecs [i]);
6536 g_free (mspecs);
6538 CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
6541 MonoArray*
6542 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
6544 return mono_param_get_objects_internal (domain, method, NULL);
6548 * mono_method_body_get_object:
6549 * @domain: an app domain
6550 * @method: a method
6552 * Return an System.Reflection.MethodBody object representing the method @method.
6554 MonoReflectionMethodBody*
6555 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
6557 static MonoClass *System_Reflection_MethodBody = NULL;
6558 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
6559 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
6560 MonoReflectionMethodBody *ret;
6561 MonoMethodNormal *mn;
6562 MonoMethodHeader *header;
6563 guint32 method_rva, local_var_sig_token;
6564 char *ptr;
6565 unsigned char format, flags;
6566 int i;
6568 if (!System_Reflection_MethodBody)
6569 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
6570 if (!System_Reflection_LocalVariableInfo)
6571 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
6572 if (!System_Reflection_ExceptionHandlingClause)
6573 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
6575 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
6577 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6578 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
6579 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
6580 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
6581 return NULL;
6582 mn = (MonoMethodNormal *)method;
6583 header = mono_method_get_header (method);
6585 /* Obtain local vars signature token */
6586 method_rva = mono_metadata_decode_row_col (&method->klass->image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
6587 ptr = mono_image_rva_map (method->klass->image, method_rva);
6588 flags = *(const unsigned char *) ptr;
6589 format = flags & METHOD_HEADER_FORMAT_MASK;
6590 switch (format){
6591 case METHOD_HEADER_TINY_FORMAT:
6592 case METHOD_HEADER_TINY_FORMAT1:
6593 local_var_sig_token = 0;
6594 break;
6595 case METHOD_HEADER_FAT_FORMAT:
6596 ptr += 2;
6597 ptr += 2;
6598 ptr += 4;
6599 local_var_sig_token = read32 (ptr);
6600 break;
6601 default:
6602 g_assert_not_reached ();
6605 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
6607 ret->init_locals = header->init_locals;
6608 ret->max_stack = header->max_stack;
6609 ret->local_var_sig_token = local_var_sig_token;
6610 MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
6611 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
6613 /* Locals */
6614 MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
6615 for (i = 0; i < header->num_locals; ++i) {
6616 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
6617 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
6618 info->is_pinned = header->locals [i]->pinned;
6619 info->local_index = i;
6620 mono_array_setref (ret->locals, i, info);
6623 /* Exceptions */
6624 MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
6625 for (i = 0; i < header->num_clauses; ++i) {
6626 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
6627 MonoExceptionClause *clause = &header->clauses [i];
6629 info->flags = clause->flags;
6630 info->try_offset = clause->try_offset;
6631 info->try_length = clause->try_len;
6632 info->handler_offset = clause->handler_offset;
6633 info->handler_length = clause->handler_len;
6634 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
6635 info->filter_offset = clause->data.filter_offset;
6636 else if (clause->data.catch_class)
6637 MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
6639 mono_array_setref (ret->clauses, i, info);
6642 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
6643 return ret;
6647 * mono_get_dbnull_object:
6648 * @domain: Domain where the object lives
6650 * Returns the System.DBNull.Value singleton object
6652 * Used as the value for ParameterInfo.DefaultValue
6654 MonoObject *
6655 mono_get_dbnull_object (MonoDomain *domain)
6657 MonoObject *obj;
6658 static MonoClassField *dbnull_value_field = NULL;
6660 if (!dbnull_value_field) {
6661 MonoClass *dbnull_klass;
6662 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
6663 mono_class_init (dbnull_klass);
6664 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
6665 g_assert (dbnull_value_field);
6667 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
6668 g_assert (obj);
6669 return obj;
6672 static void
6673 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
6675 guint32 param_index, i, lastp, crow = 0;
6676 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
6677 gint32 idx;
6679 MonoClass *klass = method->klass;
6680 MonoImage *image = klass->image;
6681 MonoMethodSignature *methodsig = mono_method_signature (method);
6683 MonoTableInfo *constt;
6684 MonoTableInfo *methodt;
6685 MonoTableInfo *paramt;
6687 if (!methodsig->param_count)
6688 return;
6690 mono_class_init (klass);
6692 if (klass->image->dynamic) {
6693 MonoReflectionMethodAux *aux;
6694 if (method->is_inflated)
6695 method = ((MonoMethodInflated*)method)->declaring;
6696 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6697 if (aux && aux->param_defaults) {
6698 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
6699 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
6701 return;
6704 methodt = &klass->image->tables [MONO_TABLE_METHOD];
6705 paramt = &klass->image->tables [MONO_TABLE_PARAM];
6706 constt = &image->tables [MONO_TABLE_CONSTANT];
6708 idx = mono_method_get_index (method) - 1;
6709 g_assert (idx != -1);
6711 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
6712 if (idx + 1 < methodt->rows)
6713 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
6714 else
6715 lastp = paramt->rows + 1;
6717 for (i = param_index; i < lastp; ++i) {
6718 guint32 paramseq;
6720 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
6721 paramseq = param_cols [MONO_PARAM_SEQUENCE];
6723 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT)
6724 continue;
6726 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
6727 if (!crow) {
6728 continue;
6731 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
6732 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
6733 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
6736 return;
6739 static MonoObject *
6740 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
6742 void *retval;
6743 MonoClass *klass;
6744 MonoObject *object;
6745 MonoType *basetype = type;
6747 if (!blob)
6748 return NULL;
6750 klass = mono_class_from_mono_type (type);
6751 if (klass->valuetype) {
6752 object = mono_object_new (domain, klass);
6753 retval = ((gchar *) object + sizeof (MonoObject));
6754 if (klass->enumtype)
6755 basetype = mono_class_enum_basetype (klass);
6756 } else {
6757 retval = &object;
6760 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
6761 return object;
6762 else
6763 return NULL;
6766 static int
6767 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
6768 int found_sep;
6769 char *s;
6771 memset (assembly, 0, sizeof (MonoAssemblyName));
6772 assembly->name = p;
6773 assembly->culture = "";
6774 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
6776 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
6777 p++;
6778 found_sep = 0;
6779 while (g_ascii_isspace (*p) || *p == ',') {
6780 *p++ = 0;
6781 found_sep = 1;
6782 continue;
6784 /* failed */
6785 if (!found_sep)
6786 return 1;
6787 while (*p) {
6788 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
6789 p += 8;
6790 assembly->major = strtoul (p, &s, 10);
6791 if (s == p || *s != '.')
6792 return 1;
6793 p = ++s;
6794 assembly->minor = strtoul (p, &s, 10);
6795 if (s == p || *s != '.')
6796 return 1;
6797 p = ++s;
6798 assembly->build = strtoul (p, &s, 10);
6799 if (s == p || *s != '.')
6800 return 1;
6801 p = ++s;
6802 assembly->revision = strtoul (p, &s, 10);
6803 if (s == p)
6804 return 1;
6805 p = s;
6806 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
6807 p += 8;
6808 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
6809 assembly->culture = "";
6810 p += 7;
6811 } else {
6812 assembly->culture = p;
6813 while (*p && *p != ',') {
6814 p++;
6817 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
6818 p += 15;
6819 if (strncmp (p, "null", 4) == 0) {
6820 p += 4;
6821 } else {
6822 int len;
6823 gchar *start = p;
6824 while (*p && *p != ',') {
6825 p++;
6827 len = (p - start + 1);
6828 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
6829 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
6830 g_strlcpy ((char*)assembly->public_key_token, start, len);
6832 } else {
6833 while (*p && *p != ',')
6834 p++;
6836 found_sep = 0;
6837 while (g_ascii_isspace (*p) || *p == ',') {
6838 *p++ = 0;
6839 found_sep = 1;
6840 continue;
6842 /* failed */
6843 if (!found_sep)
6844 return 1;
6847 return 0;
6851 * mono_reflection_parse_type:
6852 * @name: type name
6854 * Parse a type name as accepted by the GetType () method and output the info
6855 * extracted in the info structure.
6856 * the name param will be mangled, so, make a copy before passing it to this function.
6857 * The fields in info will be valid until the memory pointed to by name is valid.
6859 * See also mono_type_get_name () below.
6861 * Returns: 0 on parse error.
6863 static int
6864 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
6865 MonoTypeNameParse *info)
6867 char *start, *p, *w, *temp, *last_point, *startn;
6868 int in_modifiers = 0;
6869 int isbyref = 0, rank, arity = 0, i;
6871 start = p = w = name;
6873 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
6874 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
6875 info->name = info->name_space = NULL;
6876 info->nested = NULL;
6877 info->modifiers = NULL;
6878 info->type_arguments = NULL;
6880 /* last_point separates the namespace from the name */
6881 last_point = NULL;
6882 /* Skips spaces */
6883 while (*p == ' ') p++, start++, w++, name++;
6885 while (*p) {
6886 switch (*p) {
6887 case '+':
6888 *p = 0; /* NULL terminate the name */
6889 startn = p + 1;
6890 info->nested = g_list_append (info->nested, startn);
6891 /* we have parsed the nesting namespace + name */
6892 if (info->name)
6893 break;
6894 if (last_point) {
6895 info->name_space = start;
6896 *last_point = 0;
6897 info->name = last_point + 1;
6898 } else {
6899 info->name_space = (char *)"";
6900 info->name = start;
6902 break;
6903 case '.':
6904 last_point = p;
6905 break;
6906 case '\\':
6907 ++p;
6908 break;
6909 case '&':
6910 case '*':
6911 case '[':
6912 case ',':
6913 case ']':
6914 in_modifiers = 1;
6915 break;
6916 case '`':
6917 ++p;
6918 i = strtol (p, &temp, 10);
6919 arity += i;
6920 if (p == temp)
6921 return 0;
6922 p = temp-1;
6923 break;
6924 default:
6925 break;
6927 if (in_modifiers)
6928 break;
6929 // *w++ = *p++;
6930 p++;
6933 if (!info->name) {
6934 if (last_point) {
6935 info->name_space = start;
6936 *last_point = 0;
6937 info->name = last_point + 1;
6938 } else {
6939 info->name_space = (char *)"";
6940 info->name = start;
6943 while (*p) {
6944 switch (*p) {
6945 case '&':
6946 if (isbyref) /* only one level allowed by the spec */
6947 return 0;
6948 isbyref = 1;
6949 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
6950 *p++ = 0;
6951 break;
6952 case '*':
6953 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
6954 *p++ = 0;
6955 break;
6956 case '[':
6957 if (arity != 0) {
6958 *p++ = 0;
6959 info->type_arguments = g_ptr_array_new ();
6960 for (i = 0; i < arity; i++) {
6961 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
6962 gboolean fqname = FALSE;
6964 g_ptr_array_add (info->type_arguments, subinfo);
6966 if (*p == '[') {
6967 p++;
6968 fqname = TRUE;
6971 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
6972 return 0;
6974 if (fqname) {
6975 char *aname;
6977 if (*p != ',')
6978 return 0;
6979 *p++ = 0;
6981 aname = p;
6982 while (*p && (*p != ']'))
6983 p++;
6985 if (*p != ']')
6986 return 0;
6988 *p++ = 0;
6989 while (*aname) {
6990 if (g_ascii_isspace (*aname)) {
6991 ++aname;
6992 continue;
6994 break;
6996 if (!*aname ||
6997 !assembly_name_to_aname (&subinfo->assembly, aname))
6998 return 0;
7001 if (i + 1 < arity) {
7002 if (*p != ',')
7003 return 0;
7004 } else {
7005 if (*p != ']')
7006 return 0;
7008 *p++ = 0;
7011 arity = 0;
7012 break;
7014 rank = 1;
7015 *p++ = 0;
7016 while (*p) {
7017 if (*p == ']')
7018 break;
7019 if (*p == ',')
7020 rank++;
7021 else if (*p == '*') /* '*' means unknown lower bound */
7022 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7023 else
7024 return 0;
7025 ++p;
7027 if (*p++ != ']')
7028 return 0;
7029 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7030 break;
7031 case ']':
7032 if (is_recursed)
7033 goto end;
7034 return 0;
7035 case ',':
7036 if (is_recursed)
7037 goto end;
7038 *p++ = 0;
7039 while (*p) {
7040 if (g_ascii_isspace (*p)) {
7041 ++p;
7042 continue;
7044 break;
7046 if (!*p)
7047 return 0; /* missing assembly name */
7048 if (!assembly_name_to_aname (&info->assembly, p))
7049 return 0;
7050 break;
7051 default:
7052 return 0;
7054 if (info->assembly.name)
7055 break;
7057 // *w = 0; /* terminate class name */
7058 end:
7059 if (!info->name || !*info->name)
7060 return 0;
7061 if (endptr)
7062 *endptr = p;
7063 /* add other consistency checks */
7064 return 1;
7068 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7070 return _mono_reflection_parse_type (name, NULL, FALSE, info);
7073 static MonoType*
7074 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7076 gboolean type_resolve = FALSE;
7077 MonoType *type;
7078 MonoImage *rootimage = image;
7080 if (info->assembly.name) {
7081 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7082 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7084 * This could happen in the AOT compiler case when the search hook is not
7085 * installed.
7087 assembly = image->assembly;
7088 if (!assembly) {
7089 /* then we must load the assembly ourselve - see #60439 */
7090 assembly = mono_assembly_load (&info->assembly, NULL, NULL);
7091 if (!assembly)
7092 return NULL;
7094 image = assembly->image;
7095 } else if (!image) {
7096 image = mono_defaults.corlib;
7099 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7100 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7101 image = mono_defaults.corlib;
7102 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7105 return type;
7108 static MonoType*
7109 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7111 MonoClass *klass;
7112 GList *mod;
7113 int modval;
7114 gboolean bounded = FALSE;
7116 if (!image)
7117 image = mono_defaults.corlib;
7119 if (ignorecase)
7120 klass = mono_class_from_name_case (image, info->name_space, info->name);
7121 else
7122 klass = mono_class_from_name (image, info->name_space, info->name);
7123 if (!klass)
7124 return NULL;
7125 for (mod = info->nested; mod; mod = mod->next) {
7126 gpointer iter = NULL;
7127 MonoClass *parent;
7129 parent = klass;
7130 mono_class_init (parent);
7132 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7133 if (ignorecase) {
7134 if (g_strcasecmp (klass->name, mod->data) == 0)
7135 break;
7136 } else {
7137 if (strcmp (klass->name, mod->data) == 0)
7138 break;
7141 if (!klass)
7142 break;
7144 if (!klass)
7145 return NULL;
7146 mono_class_init (klass);
7148 if (info->type_arguments) {
7149 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7150 MonoReflectionType *the_type;
7151 MonoType *instance;
7152 int i;
7154 for (i = 0; i < info->type_arguments->len; i++) {
7155 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7157 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7158 if (!type_args [i]) {
7159 g_free (type_args);
7160 return NULL;
7164 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7166 instance = mono_reflection_bind_generic_parameters (
7167 the_type, info->type_arguments->len, type_args);
7169 g_free (type_args);
7170 if (!instance)
7171 return NULL;
7173 klass = mono_class_from_mono_type (instance);
7176 for (mod = info->modifiers; mod; mod = mod->next) {
7177 modval = GPOINTER_TO_UINT (mod->data);
7178 if (!modval) { /* byref: must be last modifier */
7179 return &klass->this_arg;
7180 } else if (modval == -1) {
7181 klass = mono_ptr_class_get (&klass->byval_arg);
7182 } else if (modval == -2) {
7183 bounded = TRUE;
7184 } else { /* array rank */
7185 klass = mono_bounded_array_class_get (klass, modval, bounded);
7187 mono_class_init (klass);
7190 return &klass->byval_arg;
7194 * mono_reflection_get_type:
7195 * @image: a metadata context
7196 * @info: type description structure
7197 * @ignorecase: flag for case-insensitive string compares
7198 * @type_resolve: whenever type resolve was already tried
7200 * Build a MonoType from the type description in @info.
7204 MonoType*
7205 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7206 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7209 static MonoType*
7210 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7212 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (mono_domain_get (), assembly);
7213 MonoType *type;
7214 int i;
7216 g_assert (assembly->dynamic);
7218 /* Enumerate all modules */
7220 type = NULL;
7221 if (abuilder->modules) {
7222 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7223 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7224 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7225 if (type)
7226 break;
7230 if (!type && abuilder->loaded_modules) {
7231 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7232 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7233 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7234 if (type)
7235 break;
7239 return type;
7242 MonoType*
7243 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7245 MonoType *type;
7246 MonoReflectionAssembly *assembly;
7247 GString *fullName;
7248 GList *mod;
7250 if (image && image->dynamic)
7251 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7252 else
7253 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7254 if (type)
7255 return type;
7256 if (!mono_domain_has_type_resolve (mono_domain_get ()))
7257 return NULL;
7259 if (type_resolve) {
7260 if (*type_resolve)
7261 return NULL;
7262 else
7263 *type_resolve = TRUE;
7266 /* Reconstruct the type name */
7267 fullName = g_string_new ("");
7268 if (info->name_space && (info->name_space [0] != '\0'))
7269 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7270 else
7271 g_string_printf (fullName, info->name);
7272 for (mod = info->nested; mod; mod = mod->next)
7273 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7275 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7276 if (assembly) {
7277 if (assembly->assembly->dynamic)
7278 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7279 else
7280 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
7281 info, ignorecase);
7283 g_string_free (fullName, TRUE);
7284 return type;
7287 void
7288 mono_reflection_free_type_info (MonoTypeNameParse *info)
7290 g_list_free (info->modifiers);
7291 g_list_free (info->nested);
7293 if (info->type_arguments) {
7294 int i;
7296 for (i = 0; i < info->type_arguments->len; i++) {
7297 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7299 mono_reflection_free_type_info (subinfo);
7300 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7301 g_free (subinfo);
7304 g_ptr_array_free (info->type_arguments, TRUE);
7309 * mono_reflection_type_from_name:
7310 * @name: type name.
7311 * @image: a metadata context (can be NULL).
7313 * Retrieves a MonoType from its @name. If the name is not fully qualified,
7314 * it defaults to get the type from @image or, if @image is NULL or loading
7315 * from it fails, uses corlib.
7318 MonoType*
7319 mono_reflection_type_from_name (char *name, MonoImage *image)
7321 MonoType *type = NULL;
7322 MonoTypeNameParse info;
7323 char *tmp;
7325 /* Make a copy since parse_type modifies its argument */
7326 tmp = g_strdup (name);
7328 /*g_print ("requested type %s\n", str);*/
7329 if (mono_reflection_parse_type (tmp, &info)) {
7330 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7333 g_free (tmp);
7334 mono_reflection_free_type_info (&info);
7335 return type;
7339 * mono_reflection_get_token:
7341 * Return the metadata token of OBJ which should be an object
7342 * representing a metadata element.
7344 guint32
7345 mono_reflection_get_token (MonoObject *obj)
7347 MonoClass *klass;
7348 guint32 token = 0;
7350 klass = obj->vtable->klass;
7352 if (strcmp (klass->name, "MethodBuilder") == 0) {
7353 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7355 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7356 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7357 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7359 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7360 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7361 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7363 /* Call mono_image_create_token so the object gets added to the tokens hash table */
7364 token = mono_image_create_token (((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image, obj, FALSE, TRUE);
7365 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7366 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7367 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7368 } else if (strcmp (klass->name, "MonoType") == 0) {
7369 MonoReflectionType *tb = (MonoReflectionType *)obj;
7370 token = mono_class_from_mono_type (tb->type)->type_token;
7371 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7372 strcmp (klass->name, "MonoMethod") == 0 ||
7373 strcmp (klass->name, "MonoGenericMethod") == 0 ||
7374 strcmp (klass->name, "MonoGenericCMethod") == 0) {
7375 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7376 if (m->method->is_inflated) {
7377 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7378 return inflated->declaring->token;
7379 } else {
7380 token = m->method->token;
7382 } else if (strcmp (klass->name, "MonoField") == 0) {
7383 MonoReflectionField *f = (MonoReflectionField*)obj;
7385 if (is_field_on_inst (f->field)) {
7386 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
7387 int field_index = f->field - dgclass->fields;
7388 MonoObject *obj;
7390 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
7391 obj = dgclass->field_objects [field_index];
7392 return mono_reflection_get_token (obj);
7394 token = mono_class_get_field_token (f->field);
7395 } else if (strcmp (klass->name, "MonoProperty") == 0) {
7396 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7398 token = mono_class_get_property_token (p->property);
7399 } else if (strcmp (klass->name, "MonoEvent") == 0) {
7400 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
7402 token = mono_class_get_event_token (p->event);
7403 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
7404 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7406 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7407 } else if (strcmp (klass->name, "Module") == 0) {
7408 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7410 token = m->token;
7411 } else if (strcmp (klass->name, "Assembly") == 0) {
7412 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7413 } else {
7414 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7415 MonoException *ex = mono_get_exception_not_implemented (msg);
7416 g_free (msg);
7417 mono_raise_exception (ex);
7420 return token;
7423 static void*
7424 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
7426 int slen, type = t->type;
7427 MonoClass *tklass = t->data.klass;
7429 handle_enum:
7430 switch (type) {
7431 case MONO_TYPE_U1:
7432 case MONO_TYPE_I1:
7433 case MONO_TYPE_BOOLEAN: {
7434 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7435 *bval = *p;
7436 *end = p + 1;
7437 return bval;
7439 case MONO_TYPE_CHAR:
7440 case MONO_TYPE_U2:
7441 case MONO_TYPE_I2: {
7442 guint16 *val = g_malloc (sizeof (guint16));
7443 *val = read16 (p);
7444 *end = p + 2;
7445 return val;
7447 #if SIZEOF_VOID_P == 4
7448 case MONO_TYPE_U:
7449 case MONO_TYPE_I:
7450 #endif
7451 case MONO_TYPE_R4:
7452 case MONO_TYPE_U4:
7453 case MONO_TYPE_I4: {
7454 guint32 *val = g_malloc (sizeof (guint32));
7455 *val = read32 (p);
7456 *end = p + 4;
7457 return val;
7459 #if SIZEOF_VOID_P == 8
7460 case MONO_TYPE_U: /* error out instead? this should probably not happen */
7461 case MONO_TYPE_I:
7462 #endif
7463 case MONO_TYPE_U8:
7464 case MONO_TYPE_I8: {
7465 guint64 *val = g_malloc (sizeof (guint64));
7466 *val = read64 (p);
7467 *end = p + 8;
7468 return val;
7470 case MONO_TYPE_R8: {
7471 double *val = g_malloc (sizeof (double));
7472 readr8 (p, val);
7473 *end = p + 8;
7474 return val;
7476 case MONO_TYPE_VALUETYPE:
7477 if (t->data.klass->enumtype) {
7478 type = mono_class_enum_basetype (t->data.klass)->type;
7479 goto handle_enum;
7480 } else {
7481 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7483 break;
7484 case MONO_TYPE_STRING:
7485 if (*p == (char)0xFF) {
7486 *end = p + 1;
7487 return NULL;
7489 slen = mono_metadata_decode_value (p, &p);
7490 *end = p + slen;
7491 return mono_string_new_len (mono_domain_get (), p, slen);
7492 case MONO_TYPE_CLASS: {
7493 char *n;
7494 MonoType *t;
7495 if (*p == (char)0xFF) {
7496 *end = p + 1;
7497 return NULL;
7499 handle_type:
7500 slen = mono_metadata_decode_value (p, &p);
7501 n = g_memdup (p, slen + 1);
7502 n [slen] = 0;
7503 t = mono_reflection_type_from_name (n, image);
7504 if (!t)
7505 g_warning ("Cannot load type '%s'", n);
7506 g_free (n);
7507 *end = p + slen;
7508 if (t)
7509 return mono_type_get_object (mono_domain_get (), t);
7510 else
7511 return NULL;
7513 case MONO_TYPE_OBJECT: {
7514 char subt = *p++;
7515 MonoObject *obj;
7516 MonoClass *subc = NULL;
7517 void *val;
7519 if (subt == 0x50) {
7520 goto handle_type;
7521 } else if (subt == 0x0E) {
7522 type = MONO_TYPE_STRING;
7523 goto handle_enum;
7524 } else if (subt == 0x1D) {
7525 MonoType simple_type = {{0}};
7526 int etype = *p;
7527 p ++;
7529 if (etype == 0x51)
7530 /* See Partition II, Appendix B3 */
7531 etype = MONO_TYPE_OBJECT;
7532 type = MONO_TYPE_SZARRAY;
7533 simple_type.type = etype;
7534 tklass = mono_class_from_mono_type (&simple_type);
7535 goto handle_enum;
7536 } else if (subt == 0x55) {
7537 char *n;
7538 MonoType *t;
7539 slen = mono_metadata_decode_value (p, &p);
7540 n = g_memdup (p, slen + 1);
7541 n [slen] = 0;
7542 t = mono_reflection_type_from_name (n, image);
7543 if (!t)
7544 g_error ("Cannot load type '%s'", n);
7545 g_free (n);
7546 p += slen;
7547 subc = mono_class_from_mono_type (t);
7548 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
7549 MonoType simple_type = {{0}};
7550 simple_type.type = subt;
7551 subc = mono_class_from_mono_type (&simple_type);
7552 } else {
7553 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
7555 val = load_cattr_value (image, &subc->byval_arg, p, end);
7556 obj = mono_object_new (mono_domain_get (), subc);
7557 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
7558 g_free (val);
7559 return obj;
7561 case MONO_TYPE_SZARRAY: {
7562 MonoArray *arr;
7563 guint32 i, alen, basetype;
7564 alen = read32 (p);
7565 p += 4;
7566 if (alen == 0xffffffff) {
7567 *end = p;
7568 return NULL;
7570 arr = mono_array_new (mono_domain_get(), tklass, alen);
7571 basetype = tklass->byval_arg.type;
7572 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
7573 basetype = mono_class_enum_basetype (tklass)->type;
7574 switch (basetype)
7576 case MONO_TYPE_U1:
7577 case MONO_TYPE_I1:
7578 case MONO_TYPE_BOOLEAN:
7579 for (i = 0; i < alen; i++) {
7580 MonoBoolean val = *p++;
7581 mono_array_set (arr, MonoBoolean, i, val);
7583 break;
7584 case MONO_TYPE_CHAR:
7585 case MONO_TYPE_U2:
7586 case MONO_TYPE_I2:
7587 for (i = 0; i < alen; i++) {
7588 guint16 val = read16 (p);
7589 mono_array_set (arr, guint16, i, val);
7590 p += 2;
7592 break;
7593 case MONO_TYPE_R4:
7594 case MONO_TYPE_U4:
7595 case MONO_TYPE_I4:
7596 for (i = 0; i < alen; i++) {
7597 guint32 val = read32 (p);
7598 mono_array_set (arr, guint32, i, val);
7599 p += 4;
7601 break;
7602 case MONO_TYPE_R8:
7603 for (i = 0; i < alen; i++) {
7604 double val;
7605 readr8 (p, &val);
7606 mono_array_set (arr, double, i, val);
7607 p += 8;
7609 break;
7610 case MONO_TYPE_U8:
7611 case MONO_TYPE_I8:
7612 for (i = 0; i < alen; i++) {
7613 guint64 val = read64 (p);
7614 mono_array_set (arr, guint64, i, val);
7615 p += 8;
7617 break;
7618 case MONO_TYPE_CLASS:
7619 case MONO_TYPE_OBJECT:
7620 case MONO_TYPE_STRING:
7621 for (i = 0; i < alen; i++) {
7622 MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
7623 mono_array_setref (arr, i, item);
7625 break;
7626 default:
7627 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
7629 *end=p;
7630 return arr;
7632 default:
7633 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
7635 return NULL;
7638 static MonoObject*
7639 create_cattr_typed_arg (MonoType *t, MonoObject *val)
7641 static MonoClass *klass;
7642 static MonoMethod *ctor;
7643 MonoObject *retval;
7644 void *params [2], *unboxed;
7646 if (!klass)
7647 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
7648 if (!ctor)
7649 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7651 params [0] = mono_type_get_object (mono_domain_get (), t);
7652 params [1] = val;
7653 retval = mono_object_new (mono_domain_get (), klass);
7654 unboxed = mono_object_unbox (retval);
7655 mono_runtime_invoke (ctor, unboxed, params, NULL);
7657 return retval;
7660 static MonoObject*
7661 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
7663 static MonoClass *klass;
7664 static MonoMethod *ctor;
7665 MonoObject *retval;
7666 void *unboxed, *params [2];
7668 if (!klass)
7669 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
7670 if (!ctor)
7671 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7673 params [0] = minfo;
7674 params [1] = typedarg;
7675 retval = mono_object_new (mono_domain_get (), klass);
7676 unboxed = mono_object_unbox (retval);
7677 mono_runtime_invoke (ctor, unboxed, params, NULL);
7679 return retval;
7682 static gboolean
7683 type_is_reference (MonoType *type)
7685 switch (type->type) {
7686 case MONO_TYPE_BOOLEAN:
7687 case MONO_TYPE_CHAR:
7688 case MONO_TYPE_U:
7689 case MONO_TYPE_I:
7690 case MONO_TYPE_U1:
7691 case MONO_TYPE_I1:
7692 case MONO_TYPE_U2:
7693 case MONO_TYPE_I2:
7694 case MONO_TYPE_U4:
7695 case MONO_TYPE_I4:
7696 case MONO_TYPE_U8:
7697 case MONO_TYPE_I8:
7698 case MONO_TYPE_R8:
7699 case MONO_TYPE_R4:
7700 case MONO_TYPE_VALUETYPE:
7701 return FALSE;
7702 default:
7703 return TRUE;
7707 static void
7708 free_param_data (MonoMethodSignature *sig, void **params) {
7709 int i;
7710 for (i = 0; i < sig->param_count; ++i) {
7711 if (!type_is_reference (sig->params [i]))
7712 g_free (params [i]);
7717 * Find the field index in the metadata FieldDef table.
7719 static guint32
7720 find_field_index (MonoClass *klass, MonoClassField *field) {
7721 int i;
7723 for (i = 0; i < klass->field.count; ++i) {
7724 if (field == &klass->fields [i])
7725 return klass->field.first + 1 + i;
7727 return 0;
7731 * Find the property index in the metadata Property table.
7733 static guint32
7734 find_property_index (MonoClass *klass, MonoProperty *property) {
7735 int i;
7737 for (i = 0; i < klass->ext->property.count; ++i) {
7738 if (property == &klass->ext->properties [i])
7739 return klass->ext->property.first + 1 + i;
7741 return 0;
7745 * Find the event index in the metadata Event table.
7747 static guint32
7748 find_event_index (MonoClass *klass, MonoEvent *event) {
7749 int i;
7751 for (i = 0; i < klass->ext->event.count; ++i) {
7752 if (event == &klass->ext->events [i])
7753 return klass->ext->event.first + 1 + i;
7755 return 0;
7758 static MonoObject*
7759 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7761 const char *p = (const char*)data;
7762 const char *named;
7763 guint32 i, j, num_named;
7764 MonoObject *attr;
7765 void *params_buf [32];
7766 void **params;
7767 MonoMethodSignature *sig;
7769 mono_class_init (method->klass);
7771 if (len == 0) {
7772 attr = mono_object_new (mono_domain_get (), method->klass);
7773 mono_runtime_invoke (method, attr, NULL, NULL);
7774 return attr;
7777 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7778 return NULL;
7780 /*g_print ("got attr %s\n", method->klass->name);*/
7782 sig = mono_method_signature (method);
7783 if (sig->param_count < 32)
7784 params = params_buf;
7785 else
7786 /* Allocate using GC so it gets GC tracking */
7787 params = mono_gc_alloc_fixed (sig->param_count * sizeof (void*), NULL);
7789 /* skip prolog */
7790 p += 2;
7791 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7792 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7795 named = p;
7796 attr = mono_object_new (mono_domain_get (), method->klass);
7797 mono_runtime_invoke (method, attr, params, NULL);
7798 free_param_data (method->signature, params);
7799 num_named = read16 (named);
7800 named += 2;
7801 for (j = 0; j < num_named; j++) {
7802 gint name_len;
7803 char *name, named_type, data_type;
7804 named_type = *named++;
7805 data_type = *named++; /* type of data */
7806 if (data_type == MONO_TYPE_SZARRAY)
7807 data_type = *named++;
7808 if (data_type == MONO_TYPE_ENUM) {
7809 gint type_len;
7810 char *type_name;
7811 type_len = mono_metadata_decode_blob_size (named, &named);
7812 type_name = g_malloc (type_len + 1);
7813 memcpy (type_name, named, type_len);
7814 type_name [type_len] = 0;
7815 named += type_len;
7816 /* FIXME: lookup the type and check type consistency */
7817 g_free (type_name);
7819 name_len = mono_metadata_decode_blob_size (named, &named);
7820 name = g_malloc (name_len + 1);
7821 memcpy (name, named, name_len);
7822 name [name_len] = 0;
7823 named += name_len;
7824 if (named_type == 0x53) {
7825 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
7826 void *val = load_cattr_value (image, field->type, named, &named);
7827 mono_field_set_value (attr, field, val);
7828 if (!type_is_reference (field->type))
7829 g_free (val);
7830 } else if (named_type == 0x54) {
7831 MonoProperty *prop;
7832 void *pparams [1];
7833 MonoType *prop_type;
7835 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
7836 /* can we have more that 1 arg in a custom attr named property? */
7837 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7838 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7839 pparams [0] = load_cattr_value (image, prop_type, named, &named);
7840 mono_property_set_value (prop, attr, pparams, NULL);
7841 if (!type_is_reference (prop_type))
7842 g_free (pparams [0]);
7844 g_free (name);
7847 if (params != params_buf)
7848 mono_gc_free_fixed (params);
7850 return attr;
7853 static MonoObject*
7854 create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7856 MonoArray *typedargs, *namedargs;
7857 MonoClass *attrklass;
7858 static MonoMethod *ctor;
7859 MonoDomain *domain;
7860 MonoObject *attr;
7861 const char *p = (const char*)data;
7862 const char *named;
7863 guint32 i, j, num_named;
7864 void *params [3];
7866 mono_class_init (method->klass);
7868 if (!ctor)
7869 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 3);
7871 domain = mono_domain_get ();
7872 if (len == 0) {
7873 /* This is for Attributes with no parameters */
7874 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
7875 params [0] = mono_method_get_object (domain, method, NULL);
7876 params [1] = params [2] = NULL;
7877 mono_runtime_invoke (method, attr, params, NULL);
7878 return attr;
7881 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7882 return NULL;
7884 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
7886 /* skip prolog */
7887 p += 2;
7888 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7889 MonoObject *obj, *typedarg;
7890 void *val;
7892 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7893 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
7894 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
7895 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
7896 mono_array_setref (typedargs, i, typedarg);
7898 if (!type_is_reference (mono_method_signature (method)->params [i]))
7899 g_free (val);
7902 named = p;
7903 num_named = read16 (named);
7904 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
7905 named += 2;
7906 attrklass = method->klass;
7907 for (j = 0; j < num_named; j++) {
7908 gint name_len;
7909 char *name, named_type, data_type;
7910 named_type = *named++;
7911 data_type = *named++; /* type of data */
7912 if (data_type == MONO_TYPE_SZARRAY)
7913 data_type = *named++;
7914 if (data_type == MONO_TYPE_ENUM) {
7915 gint type_len;
7916 char *type_name;
7917 type_len = mono_metadata_decode_blob_size (named, &named);
7918 type_name = g_malloc (type_len + 1);
7919 memcpy (type_name, named, type_len);
7920 type_name [type_len] = 0;
7921 named += type_len;
7922 /* FIXME: lookup the type and check type consistency */
7923 g_free (type_name);
7925 name_len = mono_metadata_decode_blob_size (named, &named);
7926 name = g_malloc (name_len + 1);
7927 memcpy (name, named, name_len);
7928 name [name_len] = 0;
7929 named += name_len;
7930 if (named_type == 0x53) {
7931 MonoObject *obj, *typedarg, *namedarg;
7932 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
7933 void *minfo, *val = load_cattr_value (image, field->type, named, &named);
7935 minfo = mono_field_get_object (domain, NULL, field);
7936 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
7937 typedarg = create_cattr_typed_arg (field->type, obj);
7938 namedarg = create_cattr_named_arg (minfo, typedarg);
7939 mono_array_setref (namedargs, j, namedarg);
7940 if (!type_is_reference (field->type))
7941 g_free (val);
7942 } else if (named_type == 0x54) {
7943 MonoObject *obj, *typedarg, *namedarg;
7944 MonoType *prop_type;
7945 void *val, *minfo;
7946 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
7948 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7949 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7950 minfo = mono_property_get_object (domain, NULL, prop);
7951 val = load_cattr_value (image, prop_type, named, &named);
7952 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
7953 typedarg = create_cattr_typed_arg (prop_type, obj);
7954 namedarg = create_cattr_named_arg (minfo, typedarg);
7955 mono_array_setref (namedargs, j, namedarg);
7956 if (!type_is_reference (prop_type))
7957 g_free (val);
7959 g_free (name);
7961 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
7962 params [0] = mono_method_get_object (domain, method, NULL);
7963 params [1] = typedargs;
7964 params [2] = namedargs;
7965 mono_runtime_invoke (ctor, attr, params, NULL);
7966 return attr;
7969 MonoArray*
7970 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
7972 MonoArray *result;
7973 MonoObject *attr;
7974 int i;
7976 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, cinfo->num_attrs);
7977 for (i = 0; i < cinfo->num_attrs; ++i) {
7978 if (!cinfo->attrs [i].ctor)
7979 /* The cattr type is not finished yet */
7980 /* We should include the type name but cinfo doesn't contain it */
7981 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
7982 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7983 mono_array_setref (result, i, attr);
7985 return result;
7988 static MonoArray*
7989 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass)
7991 MonoArray *result;
7992 MonoObject *attr;
7993 int i, n;
7995 n = 0;
7996 for (i = 0; i < cinfo->num_attrs; ++i) {
7997 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
7998 n ++;
8001 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
8002 n = 0;
8003 for (i = 0; i < cinfo->num_attrs; ++i) {
8004 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
8005 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
8006 mono_array_setref (result, n, attr);
8007 n ++;
8010 return result;
8013 static MonoArray*
8014 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
8016 MonoArray *result;
8017 MonoObject *attr;
8018 int i;
8020 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
8021 for (i = 0; i < cinfo->num_attrs; ++i) {
8022 attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
8023 mono_array_setref (result, i, attr);
8025 return result;
8029 * mono_custom_attrs_from_index:
8031 * Returns: NULL if no attributes are found or if a loading error occurs.
8033 MonoCustomAttrInfo*
8034 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
8036 guint32 mtoken, i, len;
8037 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
8038 MonoTableInfo *ca;
8039 MonoCustomAttrInfo *ainfo;
8040 GList *tmp, *list = NULL;
8041 const char *data;
8043 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
8045 i = mono_metadata_custom_attrs_from_index (image, idx);
8046 if (!i)
8047 return NULL;
8048 i --;
8049 while (i < ca->rows) {
8050 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
8051 break;
8052 list = g_list_prepend (list, GUINT_TO_POINTER (i));
8053 ++i;
8055 len = g_list_length (list);
8056 if (!len)
8057 return NULL;
8058 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
8059 ainfo->num_attrs = len;
8060 ainfo->image = image;
8061 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
8062 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
8063 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
8064 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
8065 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
8066 mtoken |= MONO_TOKEN_METHOD_DEF;
8067 break;
8068 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
8069 mtoken |= MONO_TOKEN_MEMBER_REF;
8070 break;
8071 default:
8072 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
8073 break;
8075 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
8076 if (!ainfo->attrs [i].ctor) {
8077 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
8078 g_list_free (list);
8079 g_free (ainfo);
8080 return NULL;
8082 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
8083 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
8084 ainfo->attrs [i].data = (guchar*)data;
8086 g_list_free (list);
8088 return ainfo;
8091 MonoCustomAttrInfo*
8092 mono_custom_attrs_from_method (MonoMethod *method)
8094 guint32 idx;
8097 * An instantiated method has the same cattrs as the generic method definition.
8099 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8100 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8102 if (method->is_inflated)
8103 method = ((MonoMethodInflated *) method)->declaring;
8105 if (method->dynamic || method->klass->image->dynamic)
8106 return lookup_custom_attr (method->klass->image, method);
8108 if (!method->token)
8109 /* Synthetic methods */
8110 return NULL;
8112 idx = mono_method_get_index (method);
8113 idx <<= MONO_CUSTOM_ATTR_BITS;
8114 idx |= MONO_CUSTOM_ATTR_METHODDEF;
8115 return mono_custom_attrs_from_index (method->klass->image, idx);
8118 MonoCustomAttrInfo*
8119 mono_custom_attrs_from_class (MonoClass *klass)
8121 guint32 idx;
8123 if (klass->generic_class)
8124 klass = klass->generic_class->container_class;
8126 if (klass->image->dynamic)
8127 return lookup_custom_attr (klass->image, klass);
8129 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
8130 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
8131 idx <<= MONO_CUSTOM_ATTR_BITS;
8132 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
8133 } else {
8134 idx = mono_metadata_token_index (klass->type_token);
8135 idx <<= MONO_CUSTOM_ATTR_BITS;
8136 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
8138 return mono_custom_attrs_from_index (klass->image, idx);
8141 MonoCustomAttrInfo*
8142 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
8144 guint32 idx;
8146 if (assembly->image->dynamic)
8147 return lookup_custom_attr (assembly->image, assembly);
8148 idx = 1; /* there is only one assembly */
8149 idx <<= MONO_CUSTOM_ATTR_BITS;
8150 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
8151 return mono_custom_attrs_from_index (assembly->image, idx);
8154 static MonoCustomAttrInfo*
8155 mono_custom_attrs_from_module (MonoImage *image)
8157 guint32 idx;
8159 if (image->dynamic)
8160 return lookup_custom_attr (image, image);
8161 idx = 1; /* there is only one module */
8162 idx <<= MONO_CUSTOM_ATTR_BITS;
8163 idx |= MONO_CUSTOM_ATTR_MODULE;
8164 return mono_custom_attrs_from_index (image, idx);
8167 MonoCustomAttrInfo*
8168 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
8170 guint32 idx;
8172 if (klass->image->dynamic) {
8173 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
8174 return lookup_custom_attr (klass->image, property);
8176 idx = find_property_index (klass, property);
8177 idx <<= MONO_CUSTOM_ATTR_BITS;
8178 idx |= MONO_CUSTOM_ATTR_PROPERTY;
8179 return mono_custom_attrs_from_index (klass->image, idx);
8182 MonoCustomAttrInfo*
8183 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
8185 guint32 idx;
8187 if (klass->image->dynamic) {
8188 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
8189 return lookup_custom_attr (klass->image, event);
8191 idx = find_event_index (klass, event);
8192 idx <<= MONO_CUSTOM_ATTR_BITS;
8193 idx |= MONO_CUSTOM_ATTR_EVENT;
8194 return mono_custom_attrs_from_index (klass->image, idx);
8197 MonoCustomAttrInfo*
8198 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
8200 guint32 idx;
8201 if (klass->image->dynamic) {
8202 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
8203 return lookup_custom_attr (klass->image, field);
8205 idx = find_field_index (klass, field);
8206 idx <<= MONO_CUSTOM_ATTR_BITS;
8207 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
8208 return mono_custom_attrs_from_index (klass->image, idx);
8211 MonoCustomAttrInfo*
8212 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
8214 MonoTableInfo *ca;
8215 guint32 i, idx, method_index;
8216 guint32 param_list, param_last, param_pos, found;
8217 MonoImage *image;
8218 MonoReflectionMethodAux *aux;
8221 * An instantiated method has the same cattrs as the generic method definition.
8223 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8224 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8226 if (method->is_inflated)
8227 method = ((MonoMethodInflated *) method)->declaring;
8229 if (method->klass->image->dynamic) {
8230 MonoCustomAttrInfo *res, *ainfo;
8231 int size;
8233 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8234 if (!aux || !aux->param_cattr)
8235 return NULL;
8237 /* Need to copy since it will be freed later */
8238 ainfo = aux->param_cattr [param];
8239 size = sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (ainfo->num_attrs - MONO_ZERO_LEN_ARRAY);
8240 res = g_malloc0 (size);
8241 memcpy (res, ainfo, size);
8242 return res;
8245 image = method->klass->image;
8246 method_index = mono_method_get_index (method);
8247 ca = &image->tables [MONO_TABLE_METHOD];
8249 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
8250 if (method_index == ca->rows) {
8251 ca = &image->tables [MONO_TABLE_PARAM];
8252 param_last = ca->rows + 1;
8253 } else {
8254 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
8255 ca = &image->tables [MONO_TABLE_PARAM];
8257 found = FALSE;
8258 for (i = param_list; i < param_last; ++i) {
8259 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
8260 if (param_pos == param) {
8261 found = TRUE;
8262 break;
8265 if (!found)
8266 return NULL;
8267 idx = i;
8268 idx <<= MONO_CUSTOM_ATTR_BITS;
8269 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
8270 return mono_custom_attrs_from_index (image, idx);
8273 gboolean
8274 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8276 int i;
8277 MonoClass *klass;
8278 for (i = 0; i < ainfo->num_attrs; ++i) {
8279 klass = ainfo->attrs [i].ctor->klass;
8280 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
8281 return TRUE;
8283 return FALSE;
8286 MonoObject*
8287 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8289 int i, attr_index;
8290 MonoClass *klass;
8291 MonoArray *attrs;
8293 attr_index = -1;
8294 for (i = 0; i < ainfo->num_attrs; ++i) {
8295 klass = ainfo->attrs [i].ctor->klass;
8296 if (mono_class_has_parent (klass, attr_klass)) {
8297 attr_index = i;
8298 break;
8301 if (attr_index == -1)
8302 return NULL;
8304 attrs = mono_custom_attrs_construct (ainfo);
8305 if (attrs)
8306 return mono_array_get (attrs, MonoObject*, attr_index);
8307 else
8308 return NULL;
8312 * mono_reflection_get_custom_attrs_info:
8313 * @obj: a reflection object handle
8315 * Return the custom attribute info for attributes defined for the
8316 * reflection handle @obj. The objects.
8318 * FIXME this function leaks like a sieve for SRE objects.
8320 MonoCustomAttrInfo*
8321 mono_reflection_get_custom_attrs_info (MonoObject *obj)
8323 MonoClass *klass;
8324 MonoCustomAttrInfo *cinfo = NULL;
8326 klass = obj->vtable->klass;
8327 if (klass == mono_defaults.monotype_class) {
8328 MonoReflectionType *rtype = (MonoReflectionType*)obj;
8329 klass = mono_class_from_mono_type (rtype->type);
8330 cinfo = mono_custom_attrs_from_class (klass);
8331 } else if (strcmp ("Assembly", klass->name) == 0) {
8332 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
8333 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
8334 } else if (strcmp ("Module", klass->name) == 0) {
8335 MonoReflectionModule *module = (MonoReflectionModule*)obj;
8336 cinfo = mono_custom_attrs_from_module (module->image);
8337 } else if (strcmp ("MonoProperty", klass->name) == 0) {
8338 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
8339 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
8340 } else if (strcmp ("MonoEvent", klass->name) == 0) {
8341 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
8342 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
8343 } else if (strcmp ("MonoField", klass->name) == 0) {
8344 MonoReflectionField *rfield = (MonoReflectionField*)obj;
8345 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
8346 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
8347 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8348 cinfo = mono_custom_attrs_from_method (rmethod->method);
8349 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
8350 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8351 cinfo = mono_custom_attrs_from_method (rmethod->method);
8352 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
8353 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
8354 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8355 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
8356 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
8357 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
8358 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
8359 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
8360 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8361 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
8362 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
8363 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
8364 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
8365 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
8366 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8367 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
8368 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
8369 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8370 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
8371 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
8372 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8373 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
8374 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
8375 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
8376 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
8377 } else { /* handle other types here... */
8378 g_error ("get custom attrs not yet supported for %s", klass->name);
8381 return cinfo;
8385 * mono_reflection_get_custom_attrs_by_type:
8386 * @obj: a reflection object handle
8388 * Return an array with all the custom attributes defined of the
8389 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
8390 * of that type are returned. The objects are fully build. Return NULL if a loading error
8391 * occurs.
8393 MonoArray*
8394 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass)
8396 MonoArray *result;
8397 MonoCustomAttrInfo *cinfo;
8399 cinfo = mono_reflection_get_custom_attrs_info (obj);
8400 if (cinfo) {
8401 if (attr_klass)
8402 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass);
8403 else
8404 result = mono_custom_attrs_construct (cinfo);
8405 if (!cinfo->cached)
8406 mono_custom_attrs_free (cinfo);
8407 } else {
8408 if (mono_loader_get_last_error ())
8409 return NULL;
8410 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
8413 return result;
8417 * mono_reflection_get_custom_attrs:
8418 * @obj: a reflection object handle
8420 * Return an array with all the custom attributes defined of the
8421 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
8422 * occurs.
8424 MonoArray*
8425 mono_reflection_get_custom_attrs (MonoObject *obj)
8427 return mono_reflection_get_custom_attrs_by_type (obj, NULL);
8431 * mono_reflection_get_custom_attrs_data:
8432 * @obj: a reflection obj handle
8434 * Returns an array of System.Reflection.CustomAttributeData,
8435 * which include information about attributes reflected on
8436 * types loaded using the Reflection Only methods
8438 MonoArray*
8439 mono_reflection_get_custom_attrs_data (MonoObject *obj)
8441 MonoArray *result;
8442 MonoCustomAttrInfo *cinfo;
8444 cinfo = mono_reflection_get_custom_attrs_info (obj);
8445 if (cinfo) {
8446 result = mono_custom_attrs_data_construct (cinfo);
8447 if (!cinfo->cached)
8448 mono_custom_attrs_free (cinfo);
8449 } else
8450 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
8452 return result;
8455 static MonoReflectionType*
8456 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
8458 MonoMethod *method_get_underlying_system_type;
8460 method_get_underlying_system_type = mono_object_get_virtual_method ((MonoObject *) t,
8461 mono_class_get_method_from_name (mono_object_class (t),
8462 "get_UnderlyingSystemType",
8463 0));
8464 return (MonoReflectionType *) mono_runtime_invoke (method_get_underlying_system_type, t, NULL, NULL);
8467 #ifndef DISABLE_REFLECTION_EMIT
8468 static MonoType*
8469 mono_reflection_type_get_handle (MonoReflectionType* t)
8471 if (t->type)
8472 return t->type;
8474 t = mono_reflection_type_get_underlying_system_type (t);
8475 if (t)
8476 return t->type;
8478 return NULL;
8482 * LOCKING: Assumes the loader lock is held.
8484 static MonoMethodSignature*
8485 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
8486 MonoMethodSignature *sig;
8487 int count, i;
8489 count = parameters? mono_array_length (parameters): 0;
8491 sig = image_g_malloc0 (image, sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
8492 sig->param_count = count;
8493 sig->sentinelpos = -1; /* FIXME */
8494 for (i = 0; i < count; ++i) {
8495 MonoReflectionType *pt = mono_type_array_get (parameters, i);
8496 sig->params [i] = mono_reflection_type_get_handle (pt);
8498 return sig;
8502 * LOCKING: Assumes the loader lock is held.
8504 static MonoMethodSignature*
8505 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
8506 MonoMethodSignature *sig;
8508 sig = parameters_to_signature (image, ctor->parameters);
8509 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8510 sig->ret = &mono_defaults.void_class->byval_arg;
8511 return sig;
8515 * LOCKING: Assumes the loader lock is held.
8517 static MonoMethodSignature*
8518 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
8519 MonoMethodSignature *sig;
8521 sig = parameters_to_signature (image, method->parameters);
8522 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8523 sig->ret = method->rtype? monotype_cast (method->rtype)->type: &mono_defaults.void_class->byval_arg;
8524 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
8525 return sig;
8528 static MonoMethodSignature*
8529 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
8530 MonoMethodSignature *sig;
8532 sig = parameters_to_signature (NULL, method->parameters);
8533 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8534 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
8535 sig->generic_param_count = 0;
8536 return sig;
8539 static void
8540 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
8542 MonoClass *klass = mono_object_class (prop);
8543 if (strcmp (klass->name, "PropertyBuilder") == 0) {
8544 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
8545 *name = mono_string_to_utf8 (pb->name);
8546 *type = monotype_cast (pb->type)->type;
8547 } else {
8548 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
8549 *name = g_strdup (p->property->name);
8550 if (p->property->get)
8551 *type = mono_method_signature (p->property->get)->ret;
8552 else
8553 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
8557 static void
8558 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
8560 MonoClass *klass = mono_object_class (field);
8561 if (strcmp (klass->name, "FieldBuilder") == 0) {
8562 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
8563 *name = mono_string_to_utf8 (fb->name);
8564 *type = monotype_cast (fb->type)->type;
8565 } else {
8566 MonoReflectionField *f = (MonoReflectionField *)field;
8567 *name = g_strdup (mono_field_get_name (f->field));
8568 *type = f->field->type;
8571 #endif /* !DISABLE_REFLECTION_EMIT */
8574 * Encode a value in a custom attribute stream of bytes.
8575 * The value to encode is either supplied as an object in argument val
8576 * (valuetypes are boxed), or as a pointer to the data in the
8577 * argument argval.
8578 * @type represents the type of the value
8579 * @buffer is the start of the buffer
8580 * @p the current position in the buffer
8581 * @buflen contains the size of the buffer and is used to return the new buffer size
8582 * if this needs to be realloced.
8583 * @retbuffer and @retp return the start and the position of the buffer
8585 static void
8586 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
8588 MonoTypeEnum simple_type;
8590 if ((p-buffer) + 10 >= *buflen) {
8591 char *newbuf;
8592 *buflen *= 2;
8593 newbuf = g_realloc (buffer, *buflen);
8594 p = newbuf + (p-buffer);
8595 buffer = newbuf;
8597 if (!argval)
8598 argval = ((char*)arg + sizeof (MonoObject));
8599 simple_type = type->type;
8600 handle_enum:
8601 switch (simple_type) {
8602 case MONO_TYPE_BOOLEAN:
8603 case MONO_TYPE_U1:
8604 case MONO_TYPE_I1:
8605 *p++ = *argval;
8606 break;
8607 case MONO_TYPE_CHAR:
8608 case MONO_TYPE_U2:
8609 case MONO_TYPE_I2:
8610 swap_with_size (p, argval, 2, 1);
8611 p += 2;
8612 break;
8613 case MONO_TYPE_U4:
8614 case MONO_TYPE_I4:
8615 case MONO_TYPE_R4:
8616 swap_with_size (p, argval, 4, 1);
8617 p += 4;
8618 break;
8619 case MONO_TYPE_R8:
8620 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
8621 p [0] = argval [4];
8622 p [1] = argval [5];
8623 p [2] = argval [6];
8624 p [3] = argval [7];
8625 p [4] = argval [0];
8626 p [5] = argval [1];
8627 p [6] = argval [2];
8628 p [7] = argval [3];
8629 #else
8630 swap_with_size (p, argval, 8, 1);
8631 #endif
8632 p += 8;
8633 break;
8634 case MONO_TYPE_U8:
8635 case MONO_TYPE_I8:
8636 swap_with_size (p, argval, 8, 1);
8637 p += 8;
8638 break;
8639 case MONO_TYPE_VALUETYPE:
8640 if (type->data.klass->enumtype) {
8641 simple_type = mono_class_enum_basetype (type->data.klass)->type;
8642 goto handle_enum;
8643 } else {
8644 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
8646 break;
8647 case MONO_TYPE_STRING: {
8648 char *str;
8649 guint32 slen;
8650 if (!arg) {
8651 *p++ = 0xFF;
8652 break;
8654 str = mono_string_to_utf8 ((MonoString*)arg);
8655 slen = strlen (str);
8656 if ((p-buffer) + 10 + slen >= *buflen) {
8657 char *newbuf;
8658 *buflen *= 2;
8659 *buflen += slen;
8660 newbuf = g_realloc (buffer, *buflen);
8661 p = newbuf + (p-buffer);
8662 buffer = newbuf;
8664 mono_metadata_encode_value (slen, p, &p);
8665 memcpy (p, str, slen);
8666 p += slen;
8667 g_free (str);
8668 break;
8670 case MONO_TYPE_CLASS: {
8671 char *str;
8672 guint32 slen;
8673 MonoClass *k;
8674 if (!arg) {
8675 *p++ = 0xFF;
8676 break;
8678 k = mono_object_class (arg);
8679 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
8680 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit"))) {
8681 MonoReflectionType* rt = mono_reflection_type_get_underlying_system_type ((MonoReflectionType*) arg);
8682 MonoClass *rtc;
8684 if (rt && (rtc = mono_object_class (rt)) &&
8685 (mono_object_isinst ((MonoObject *) rt, mono_defaults.monotype_class) ||
8686 !strcmp (rtc->name, "TypeBuilder") || !strcmp (rtc->name_space, "System.Reflection.Emit"))) {
8687 arg = (MonoObject *) rt;
8688 k = rtc;
8689 } else
8690 g_error ("Only System.Type allowed, not %s.%s", k->name_space, k->name);
8692 handle_type:
8693 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
8694 slen = strlen (str);
8695 if ((p-buffer) + 10 + slen >= *buflen) {
8696 char *newbuf;
8697 *buflen *= 2;
8698 *buflen += slen;
8699 newbuf = g_realloc (buffer, *buflen);
8700 p = newbuf + (p-buffer);
8701 buffer = newbuf;
8703 mono_metadata_encode_value (slen, p, &p);
8704 memcpy (p, str, slen);
8705 p += slen;
8706 g_free (str);
8707 break;
8709 case MONO_TYPE_SZARRAY: {
8710 int len, i;
8711 MonoClass *eclass, *arg_eclass;
8713 if (!arg) {
8714 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
8715 break;
8717 len = mono_array_length ((MonoArray*)arg);
8718 *p++ = len & 0xff;
8719 *p++ = (len >> 8) & 0xff;
8720 *p++ = (len >> 16) & 0xff;
8721 *p++ = (len >> 24) & 0xff;
8722 *retp = p;
8723 *retbuffer = buffer;
8724 eclass = type->data.klass;
8725 arg_eclass = mono_object_class (arg)->element_class;
8727 if (!eclass) {
8728 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
8729 eclass = mono_defaults.object_class;
8731 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
8732 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
8733 int elsize = mono_class_array_element_size (arg_eclass);
8734 for (i = 0; i < len; ++i) {
8735 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
8736 elptr += elsize;
8738 } else if (eclass->valuetype && arg_eclass->valuetype) {
8739 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
8740 int elsize = mono_class_array_element_size (eclass);
8741 for (i = 0; i < len; ++i) {
8742 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
8743 elptr += elsize;
8745 } else {
8746 for (i = 0; i < len; ++i) {
8747 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
8750 break;
8752 case MONO_TYPE_OBJECT: {
8753 MonoClass *klass;
8754 char *str;
8755 guint32 slen;
8758 * The parameter type is 'object' but the type of the actual
8759 * argument is not. So we have to add type information to the blob
8760 * too. This is completely undocumented in the spec.
8763 if (arg == NULL) {
8764 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
8765 *p++ = 0xFF;
8766 break;
8769 klass = mono_object_class (arg);
8771 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
8772 *p++ = 0x50;
8773 goto handle_type;
8774 } else if (klass->enumtype) {
8775 *p++ = 0x55;
8776 } else if (klass == mono_defaults.string_class) {
8777 simple_type = MONO_TYPE_STRING;
8778 *p++ = 0x0E;
8779 goto handle_enum;
8780 } else if (klass->rank == 1) {
8781 *p++ = 0x1D;
8782 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
8783 /* See Partition II, Appendix B3 */
8784 *p++ = 0x51;
8785 else
8786 *p++ = klass->element_class->byval_arg.type;
8787 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
8788 break;
8789 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
8790 *p++ = simple_type = klass->byval_arg.type;
8791 goto handle_enum;
8792 } else {
8793 g_error ("unhandled type in custom attr");
8795 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
8796 slen = strlen (str);
8797 if ((p-buffer) + 10 + slen >= *buflen) {
8798 char *newbuf;
8799 *buflen *= 2;
8800 *buflen += slen;
8801 newbuf = g_realloc (buffer, *buflen);
8802 p = newbuf + (p-buffer);
8803 buffer = newbuf;
8805 mono_metadata_encode_value (slen, p, &p);
8806 memcpy (p, str, slen);
8807 p += slen;
8808 g_free (str);
8809 simple_type = mono_class_enum_basetype (klass)->type;
8810 goto handle_enum;
8812 default:
8813 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
8815 *retp = p;
8816 *retbuffer = buffer;
8819 static void
8820 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
8822 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
8823 char *str = type_get_qualified_name (type, NULL);
8824 int slen = strlen (str);
8826 *p++ = 0x55;
8828 * This seems to be optional...
8829 * *p++ = 0x80;
8831 mono_metadata_encode_value (slen, p, &p);
8832 memcpy (p, str, slen);
8833 p += slen;
8834 g_free (str);
8835 } else if (type->type == MONO_TYPE_OBJECT) {
8836 *p++ = 0x51;
8837 } else if (type->type == MONO_TYPE_CLASS) {
8838 /* it should be a type: encode_cattr_value () has the check */
8839 *p++ = 0x50;
8840 } else {
8841 mono_metadata_encode_value (type->type, p, &p);
8842 if (type->type == MONO_TYPE_SZARRAY)
8843 /* See the examples in Partition VI, Annex B */
8844 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
8847 *retp = p;
8850 #ifndef DISABLE_REFLECTION_EMIT
8851 static void
8852 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
8854 int len;
8855 /* Preallocate a large enough buffer */
8856 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
8857 char *str = type_get_qualified_name (type, NULL);
8858 len = strlen (str);
8859 g_free (str);
8860 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
8861 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
8862 len = strlen (str);
8863 g_free (str);
8864 } else {
8865 len = 0;
8867 len += strlen (name);
8869 if ((p-buffer) + 20 + len >= *buflen) {
8870 char *newbuf;
8871 *buflen *= 2;
8872 *buflen += len;
8873 newbuf = g_realloc (buffer, *buflen);
8874 p = newbuf + (p-buffer);
8875 buffer = newbuf;
8878 encode_field_or_prop_type (type, p, &p);
8880 len = strlen (name);
8881 mono_metadata_encode_value (len, p, &p);
8882 memcpy (p, name, len);
8883 p += len;
8884 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
8885 *retp = p;
8886 *retbuffer = buffer;
8890 * mono_reflection_get_custom_attrs_blob:
8891 * @ctor: custom attribute constructor
8892 * @ctorArgs: arguments o the constructor
8893 * @properties:
8894 * @propValues:
8895 * @fields:
8896 * @fieldValues:
8898 * Creates the blob of data that needs to be saved in the metadata and that represents
8899 * the custom attributed described by @ctor, @ctorArgs etc.
8900 * Returns: a Byte array representing the blob of data.
8902 MonoArray*
8903 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
8905 MonoArray *result;
8906 MonoMethodSignature *sig;
8907 MonoObject *arg;
8908 char *buffer, *p;
8909 guint32 buflen, i;
8911 MONO_ARCH_SAVE_REGS;
8913 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
8914 /* sig is freed later so allocate it in the heap */
8915 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
8916 } else {
8917 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
8920 g_assert (mono_array_length (ctorArgs) == sig->param_count);
8921 buflen = 256;
8922 p = buffer = g_malloc (buflen);
8923 /* write the prolog */
8924 *p++ = 1;
8925 *p++ = 0;
8926 for (i = 0; i < sig->param_count; ++i) {
8927 arg = mono_array_get (ctorArgs, MonoObject*, i);
8928 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
8930 i = 0;
8931 if (properties)
8932 i += mono_array_length (properties);
8933 if (fields)
8934 i += mono_array_length (fields);
8935 *p++ = i & 0xff;
8936 *p++ = (i >> 8) & 0xff;
8937 if (properties) {
8938 MonoObject *prop;
8939 for (i = 0; i < mono_array_length (properties); ++i) {
8940 MonoType *ptype;
8941 char *pname;
8943 prop = mono_array_get (properties, gpointer, i);
8944 get_prop_name_and_type (prop, &pname, &ptype);
8945 *p++ = 0x54; /* PROPERTY signature */
8946 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
8947 g_free (pname);
8951 if (fields) {
8952 MonoObject *field;
8953 for (i = 0; i < mono_array_length (fields); ++i) {
8954 MonoType *ftype;
8955 char *fname;
8957 field = mono_array_get (fields, gpointer, i);
8958 get_field_name_and_type (field, &fname, &ftype);
8959 *p++ = 0x53; /* FIELD signature */
8960 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
8961 g_free (fname);
8965 g_assert (p - buffer <= buflen);
8966 buflen = p - buffer;
8967 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8968 p = mono_array_addr (result, char, 0);
8969 memcpy (p, buffer, buflen);
8970 g_free (buffer);
8971 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
8972 g_free (sig);
8973 return result;
8977 * mono_reflection_setup_internal_class:
8978 * @tb: a TypeBuilder object
8980 * Creates a MonoClass that represents the TypeBuilder.
8981 * This is a trick that lets us simplify a lot of reflection code
8982 * (and will allow us to support Build and Run assemblies easier).
8984 void
8985 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
8987 MonoClass *klass, *parent;
8989 MONO_ARCH_SAVE_REGS;
8991 CHECK_MONOTYPE (tb->parent);
8993 mono_loader_lock ();
8995 if (tb->parent) {
8996 /* check so we can compile corlib correctly */
8997 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
8998 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
8999 parent = monotype_cast (tb->parent)->type->data.klass;
9000 } else {
9001 parent = mono_class_from_mono_type (monotype_cast (tb->parent)->type);
9003 } else {
9004 parent = NULL;
9007 /* the type has already being created: it means we just have to change the parent */
9008 if (tb->type.type) {
9009 klass = mono_class_from_mono_type (tb->type.type);
9010 klass->parent = NULL;
9011 /* fool mono_class_setup_parent */
9012 klass->supertypes = NULL;
9013 mono_class_setup_parent (klass, parent);
9014 mono_class_setup_mono_type (klass);
9015 mono_loader_unlock ();
9016 return;
9019 klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
9021 klass->image = &tb->module->dynamic_image->image;
9023 klass->inited = 1; /* we lie to the runtime */
9024 klass->name = mono_string_to_utf8_image (klass->image, tb->name);
9025 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace);
9026 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
9027 klass->flags = tb->attrs;
9029 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
9031 klass->element_class = klass;
9033 MOVING_GC_REGISTER (&klass->reflection_info);
9034 klass->reflection_info = tb;
9036 /* Put into cache so mono_class_get () will find it */
9037 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
9039 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
9040 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
9042 if (parent != NULL) {
9043 mono_class_setup_parent (klass, parent);
9044 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
9045 const char *old_n = klass->name;
9046 /* trick to get relative numbering right when compiling corlib */
9047 klass->name = "BuildingObject";
9048 mono_class_setup_parent (klass, mono_defaults.object_class);
9049 klass->name = old_n;
9052 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
9053 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
9054 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
9055 klass->instance_size = sizeof (MonoObject);
9056 klass->size_inited = 1;
9057 mono_class_setup_vtable_general (klass, NULL, 0);
9060 mono_class_setup_mono_type (klass);
9062 mono_class_setup_supertypes (klass);
9065 * FIXME: handle interfaces.
9068 tb->type.type = &klass->byval_arg;
9070 if (tb->nesting_type) {
9071 g_assert (tb->nesting_type->type);
9072 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
9075 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
9077 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
9079 mono_loader_unlock ();
9083 * mono_reflection_setup_generic_class:
9084 * @tb: a TypeBuilder object
9086 * Setup the generic class before adding the first generic parameter.
9088 void
9089 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
9094 * mono_reflection_create_generic_class:
9095 * @tb: a TypeBuilder object
9097 * Creates the generic class after all generic parameters have been added.
9099 void
9100 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
9102 MonoClass *klass;
9103 int count, i;
9105 MONO_ARCH_SAVE_REGS;
9107 klass = mono_class_from_mono_type (tb->type.type);
9109 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
9111 if (klass->generic_container || (count == 0))
9112 return;
9114 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
9116 klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
9118 klass->generic_container->owner.klass = klass;
9119 klass->generic_container->type_argc = count;
9120 klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
9122 klass->is_generic = 1;
9124 for (i = 0; i < count; i++) {
9125 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
9126 MonoGenericParamFull *param = (MonoGenericParamFull *) gparam->type.type->data.generic_param;
9127 klass->generic_container->type_params [i] = *param;
9128 /*Make sure we are a diferent type instance */
9129 klass->generic_container->type_params [i].param.owner = klass->generic_container;
9130 klass->generic_container->type_params [i].info.pklass = NULL;
9132 g_assert (klass->generic_container->type_params [i].param.owner);
9135 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
9139 * mono_reflection_create_internal_class:
9140 * @tb: a TypeBuilder object
9142 * Actually create the MonoClass that is associated with the TypeBuilder.
9144 void
9145 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
9147 MonoClass *klass;
9149 MONO_ARCH_SAVE_REGS;
9151 klass = mono_class_from_mono_type (tb->type.type);
9153 mono_loader_lock ();
9154 if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
9155 MonoReflectionFieldBuilder *fb;
9156 MonoClass *ec;
9157 MonoType *enum_basetype;
9159 g_assert (tb->fields != NULL);
9160 g_assert (mono_array_length (tb->fields) >= 1);
9162 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
9164 if (!mono_type_is_valid_enum_basetype (monotype_cast (fb->type)->type)) {
9165 mono_loader_unlock ();
9166 return;
9169 enum_basetype = monotype_cast (fb->type)->type;
9170 klass->element_class = mono_class_from_mono_type (enum_basetype);
9171 if (!klass->element_class)
9172 klass->element_class = mono_class_from_mono_type (enum_basetype);
9175 * get the element_class from the current corlib.
9177 ec = default_class_from_mono_type (enum_basetype);
9178 klass->instance_size = ec->instance_size;
9179 klass->size_inited = 1;
9181 * this is almost safe to do with enums and it's needed to be able
9182 * to create objects of the enum type (for use in SetConstant).
9184 /* FIXME: Does this mean enums can't have method overrides ? */
9185 mono_class_setup_vtable_general (klass, NULL, 0);
9187 mono_loader_unlock ();
9190 static MonoMarshalSpec*
9191 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
9192 MonoReflectionMarshal *minfo)
9194 MonoMarshalSpec *res;
9196 res = image_g_new0 (image, MonoMarshalSpec, 1);
9197 res->native = minfo->type;
9199 switch (minfo->type) {
9200 case MONO_NATIVE_LPARRAY:
9201 res->data.array_data.elem_type = minfo->eltype;
9202 if (minfo->has_size) {
9203 res->data.array_data.param_num = minfo->param_num;
9204 res->data.array_data.num_elem = minfo->count;
9205 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
9207 else {
9208 res->data.array_data.param_num = -1;
9209 res->data.array_data.num_elem = -1;
9210 res->data.array_data.elem_mult = -1;
9212 break;
9214 case MONO_NATIVE_BYVALTSTR:
9215 case MONO_NATIVE_BYVALARRAY:
9216 res->data.array_data.num_elem = minfo->count;
9217 break;
9219 case MONO_NATIVE_CUSTOM:
9220 if (minfo->marshaltyperef)
9221 res->data.custom_data.custom_name =
9222 type_get_fully_qualified_name (monotype_cast (minfo->marshaltyperef)->type);
9223 if (minfo->mcookie)
9224 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
9225 break;
9227 default:
9228 break;
9231 return res;
9233 #endif /* !DISABLE_REFLECTION_EMIT */
9235 MonoReflectionMarshal*
9236 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
9237 MonoMarshalSpec *spec)
9239 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
9240 MonoReflectionMarshal *minfo;
9241 MonoType *mtype;
9243 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
9244 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
9245 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
9246 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
9249 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
9250 minfo->type = spec->native;
9252 switch (minfo->type) {
9253 case MONO_NATIVE_LPARRAY:
9254 minfo->eltype = spec->data.array_data.elem_type;
9255 minfo->count = spec->data.array_data.num_elem;
9256 minfo->param_num = spec->data.array_data.param_num;
9257 break;
9259 case MONO_NATIVE_BYVALTSTR:
9260 case MONO_NATIVE_BYVALARRAY:
9261 minfo->count = spec->data.array_data.num_elem;
9262 break;
9264 case MONO_NATIVE_CUSTOM:
9265 if (spec->data.custom_data.custom_name) {
9266 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
9267 if (mtype)
9268 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
9270 MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
9272 if (spec->data.custom_data.cookie)
9273 MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
9274 break;
9276 default:
9277 break;
9280 return minfo;
9283 #ifndef DISABLE_REFLECTION_EMIT
9284 static MonoMethod*
9285 reflection_methodbuilder_to_mono_method (MonoClass *klass,
9286 ReflectionMethodBuilder *rmb,
9287 MonoMethodSignature *sig)
9289 MonoMethod *m;
9290 MonoMethodNormal *pm;
9291 MonoMarshalSpec **specs;
9292 MonoReflectionMethodAux *method_aux;
9293 MonoImage *image;
9294 gboolean dynamic;
9295 int i;
9298 * Methods created using a MethodBuilder should have their memory allocated
9299 * inside the image mempool, while dynamic methods should have their memory
9300 * malloc'd.
9302 dynamic = rmb->refs != NULL;
9303 image = dynamic ? NULL : klass->image;
9305 if (!dynamic)
9306 g_assert (!klass->generic_class);
9308 mono_loader_lock ();
9310 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
9311 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
9312 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
9313 else if (rmb->refs)
9314 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
9315 else
9316 m = (MonoMethod *)image_g_new0 (image, MonoMethodNormal, 1);
9318 pm = (MonoMethodNormal*)m;
9320 m->dynamic = dynamic;
9321 m->slot = -1;
9322 m->flags = rmb->attrs;
9323 m->iflags = rmb->iattrs;
9324 m->name = mono_string_to_utf8_image (image, rmb->name);
9325 m->klass = klass;
9326 m->signature = sig;
9327 m->skip_visibility = rmb->skip_visibility;
9328 if (rmb->table_idx)
9329 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
9331 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
9332 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
9333 m->string_ctor = 1;
9335 m->signature->pinvoke = 1;
9336 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
9337 m->signature->pinvoke = 1;
9339 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
9341 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry) : image_strdup (image, m->name);
9342 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll);
9344 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
9346 if (klass->image->dynamic)
9347 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
9349 mono_loader_unlock ();
9351 return m;
9352 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
9353 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
9354 MonoMethodHeader *header;
9355 guint32 code_size;
9356 gint32 max_stack, i;
9357 gint32 num_locals = 0;
9358 gint32 num_clauses = 0;
9359 guint8 *code;
9361 if (rmb->ilgen) {
9362 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
9363 code_size = rmb->ilgen->code_len;
9364 max_stack = rmb->ilgen->max_stack;
9365 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
9366 if (rmb->ilgen->ex_handlers)
9367 num_clauses = method_count_clauses (rmb->ilgen);
9368 } else {
9369 if (rmb->code) {
9370 code = mono_array_addr (rmb->code, guint8, 0);
9371 code_size = mono_array_length (rmb->code);
9372 /* we probably need to run a verifier on the code... */
9373 max_stack = 8;
9375 else {
9376 code = NULL;
9377 code_size = 0;
9378 max_stack = 8;
9382 header = image_g_malloc0 (image, sizeof (MonoMethodHeader) +
9383 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
9384 header->code_size = code_size;
9385 header->code = image_g_malloc (image, code_size);
9386 memcpy ((char*)header->code, code, code_size);
9387 header->max_stack = max_stack;
9388 header->init_locals = rmb->init_locals;
9389 header->num_locals = num_locals;
9391 for (i = 0; i < num_locals; ++i) {
9392 MonoReflectionLocalBuilder *lb =
9393 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
9395 header->locals [i] = image_g_new0 (image, MonoType, 1);
9396 memcpy (header->locals [i], monotype_cast (lb->type)->type, sizeof (MonoType));
9399 header->num_clauses = num_clauses;
9400 if (num_clauses) {
9401 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
9402 rmb->ilgen, num_clauses);
9405 pm->header = header;
9408 if (rmb->generic_params) {
9409 int count = mono_array_length (rmb->generic_params);
9410 MonoGenericContainer *container;
9412 container = rmb->generic_container;
9413 if (container) {
9414 m->is_generic = TRUE;
9415 mono_method_set_generic_container (m, container);
9417 container->type_argc = count;
9418 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
9419 container->owner.method = m;
9421 for (i = 0; i < count; i++) {
9422 MonoReflectionGenericParam *gp =
9423 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
9424 MonoGenericParamFull *param = (MonoGenericParamFull *) gp->type.type->data.generic_param;
9425 container->type_params [i] = *param;
9428 if (klass->generic_container) {
9429 container->parent = klass->generic_container;
9430 container->context.class_inst = klass->generic_container->context.class_inst;
9432 container->context.method_inst = mono_get_shared_generic_inst (container);
9435 if (rmb->refs) {
9436 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
9437 int i;
9438 void **data;
9440 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
9442 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
9443 data [0] = GUINT_TO_POINTER (rmb->nrefs);
9444 for (i = 0; i < rmb->nrefs; ++i)
9445 data [i + 1] = rmb->refs [i];
9448 method_aux = NULL;
9450 /* Parameter info */
9451 if (rmb->pinfo) {
9452 if (!method_aux)
9453 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
9454 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
9455 for (i = 0; i <= m->signature->param_count; ++i) {
9456 MonoReflectionParamBuilder *pb;
9457 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
9458 if ((i > 0) && (pb->attrs)) {
9459 /* Make a copy since it might point to a shared type structure */
9460 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
9461 m->signature->params [i - 1]->attrs = pb->attrs;
9464 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
9465 MonoDynamicImage *assembly;
9466 guint32 idx, def_type, len;
9467 char *p;
9468 const char *p2;
9470 if (!method_aux->param_defaults) {
9471 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
9472 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
9474 assembly = (MonoDynamicImage*)klass->image;
9475 idx = encode_constant (assembly, pb->def_value, &def_type);
9476 /* Copy the data from the blob since it might get realloc-ed */
9477 p = assembly->blob.data + idx;
9478 len = mono_metadata_decode_blob_size (p, &p2);
9479 len += p2 - p;
9480 method_aux->param_defaults [i] = image_g_malloc (image, len);
9481 method_aux->param_default_types [i] = def_type;
9482 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
9485 if (pb->name)
9486 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name);
9487 if (pb->cattrs) {
9488 if (!method_aux->param_cattr)
9489 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
9490 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
9496 /* Parameter marshalling */
9497 specs = NULL;
9498 if (rmb->pinfo)
9499 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
9500 MonoReflectionParamBuilder *pb;
9501 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
9502 if (pb->marshal_info) {
9503 if (specs == NULL)
9504 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
9505 specs [pb->position] =
9506 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
9510 if (specs != NULL) {
9511 if (!method_aux)
9512 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
9513 method_aux->param_marshall = specs;
9516 if (klass->image->dynamic && method_aux)
9517 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
9519 mono_loader_unlock ();
9521 return m;
9524 static MonoMethod*
9525 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
9527 ReflectionMethodBuilder rmb;
9528 MonoMethodSignature *sig;
9530 mono_loader_lock ();
9531 sig = ctor_builder_to_signature (klass->image, mb);
9532 mono_loader_unlock ();
9534 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
9536 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
9537 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
9539 /* If we are in a generic class, we might be called multiple times from inflate_method */
9540 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
9541 /* ilgen is no longer needed */
9542 mb->ilgen = NULL;
9545 return mb->mhandle;
9548 static MonoMethod*
9549 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
9551 ReflectionMethodBuilder rmb;
9552 MonoMethodSignature *sig;
9554 mono_loader_lock ();
9555 sig = method_builder_to_signature (klass->image, mb);
9556 mono_loader_unlock ();
9558 reflection_methodbuilder_from_method_builder (&rmb, mb);
9560 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
9561 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
9563 /* If we are in a generic class, we might be called multiple times from inflate_method */
9564 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
9565 /* ilgen is no longer needed */
9566 mb->ilgen = NULL;
9568 return mb->mhandle;
9571 static MonoClassField*
9572 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
9574 MonoClassField *field;
9575 MonoType *custom;
9577 field = g_new0 (MonoClassField, 1);
9579 field->name = mono_string_to_utf8 (fb->name);
9580 if (fb->attrs || fb->modreq || fb->modopt) {
9581 field->type = mono_metadata_type_dup (NULL, monotype_cast (fb->type)->type);
9582 field->type->attrs = fb->attrs;
9584 g_assert (klass->image->dynamic);
9585 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
9586 g_free (field->type);
9587 field->type = custom;
9588 } else {
9589 field->type = monotype_cast (fb->type)->type;
9591 if (fb->offset != -1)
9592 field->offset = fb->offset;
9593 field->parent = klass;
9594 mono_save_custom_attrs (klass->image, field, fb->cattrs);
9596 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
9598 return field;
9600 #endif
9602 MonoType*
9603 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
9605 MonoClass *klass;
9606 MonoReflectionTypeBuilder *tb = NULL;
9607 gboolean is_dynamic = FALSE;
9608 MonoDomain *domain;
9609 MonoClass *geninst;
9611 mono_loader_lock ();
9613 domain = mono_object_domain (type);
9615 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
9616 tb = (MonoReflectionTypeBuilder *) type;
9618 is_dynamic = TRUE;
9619 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
9620 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
9622 tb = rgi->generic_type;
9623 is_dynamic = TRUE;
9626 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
9627 if (tb && tb->generic_container)
9628 mono_reflection_create_generic_class (tb);
9630 klass = mono_class_from_mono_type (type->type);
9631 if (!klass->generic_container) {
9632 mono_loader_unlock ();
9633 return NULL;
9636 if (klass->wastypebuilder) {
9637 tb = (MonoReflectionTypeBuilder *) klass->reflection_info;
9639 is_dynamic = TRUE;
9642 mono_loader_unlock ();
9644 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
9646 return &geninst->byval_arg;
9649 MonoClass*
9650 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
9652 MonoGenericClass *gclass;
9653 MonoGenericInst *inst;
9655 g_assert (klass->generic_container);
9657 inst = mono_metadata_get_generic_inst (type_argc, types);
9658 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
9660 return mono_generic_class_get_class (gclass);
9663 MonoReflectionMethod*
9664 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
9666 MonoClass *klass;
9667 MonoMethod *method, *inflated;
9668 MonoMethodInflated *imethod;
9669 MonoGenericContext tmp_context;
9670 MonoGenericInst *ginst;
9671 MonoType **type_argv;
9672 int count, i;
9674 MONO_ARCH_SAVE_REGS;
9676 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
9677 #ifndef DISABLE_REFLECTION_EMIT
9678 MonoReflectionMethodBuilder *mb = NULL;
9679 MonoReflectionTypeBuilder *tb;
9680 MonoClass *klass;
9682 mb = (MonoReflectionMethodBuilder *) rmethod;
9683 tb = (MonoReflectionTypeBuilder *) mb->type;
9684 klass = mono_class_from_mono_type (tb->type.type);
9686 method = methodbuilder_to_mono_method (klass, mb);
9687 #else
9688 g_assert_not_reached ();
9689 method = NULL;
9690 #endif
9691 } else {
9692 method = rmethod->method;
9695 klass = method->klass;
9697 if (method->is_inflated)
9698 method = ((MonoMethodInflated *) method)->declaring;
9700 count = mono_method_signature (method)->generic_param_count;
9701 if (count != mono_array_length (types))
9702 return NULL;
9704 type_argv = g_new0 (MonoType *, count);
9705 for (i = 0; i < count; i++) {
9706 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
9707 type_argv [i] = garg->type;
9709 ginst = mono_metadata_get_generic_inst (count, type_argv);
9710 g_free (type_argv);
9712 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
9713 tmp_context.method_inst = ginst;
9715 inflated = mono_class_inflate_generic_method (method, &tmp_context);
9716 imethod = (MonoMethodInflated *) inflated;
9718 if (method->klass->image->dynamic) {
9719 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
9721 * This table maps metadata structures representing inflated methods/fields
9722 * to the reflection objects representing their generic definitions.
9724 mono_loader_lock ();
9725 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
9726 mono_loader_unlock ();
9729 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
9732 #ifndef DISABLE_REFLECTION_EMIT
9734 static MonoMethod *
9735 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
9737 MonoMethodInflated *imethod;
9738 MonoGenericContext *context;
9739 int i;
9742 * With generic code sharing the klass might not be inflated.
9743 * This can happen because classes inflated with their own
9744 * type arguments are "normalized" to the uninflated class.
9746 if (!klass->generic_class)
9747 return method;
9749 context = mono_class_get_context (klass);
9751 if (klass->method.count) {
9752 /* Find the already created inflated method */
9753 for (i = 0; i < klass->method.count; ++i) {
9754 g_assert (klass->methods [i]->is_inflated);
9755 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
9756 break;
9758 g_assert (i < klass->method.count);
9759 imethod = (MonoMethodInflated*)klass->methods [i];
9760 } else {
9761 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
9764 if (method->is_generic && method->klass->image->dynamic) {
9765 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
9767 mono_loader_lock ();
9768 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
9769 mono_loader_unlock ();
9771 return (MonoMethod *) imethod;
9774 static MonoMethod *
9775 inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
9777 MonoMethod *method;
9778 MonoClass *gklass;
9780 gklass = mono_class_from_mono_type (type->generic_type->type.type);
9782 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
9783 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
9784 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
9785 else
9786 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
9787 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
9788 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
9789 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
9790 method = ((MonoReflectionMethod *) obj)->method;
9791 else {
9792 method = NULL; /* prevent compiler warning */
9793 g_assert_not_reached ();
9796 return inflate_mono_method (mono_class_from_mono_type (type->type.type), method, obj);
9799 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
9800 void
9801 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
9802 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
9803 MonoArray *events)
9805 MonoGenericClass *gclass;
9806 MonoDynamicGenericClass *dgclass;
9807 MonoClass *klass, *gklass;
9808 int i;
9810 MONO_ARCH_SAVE_REGS;
9812 klass = mono_class_from_mono_type (type->type.type);
9813 g_assert (type->type.type->type == MONO_TYPE_GENERICINST);
9814 gclass = type->type.type->data.generic_class;
9816 g_assert (gclass->is_dynamic);
9817 dgclass = (MonoDynamicGenericClass *) gclass;
9819 if (dgclass->initialized)
9820 return;
9822 gklass = gclass->container_class;
9823 mono_class_init (gklass);
9825 dgclass->count_methods = methods ? mono_array_length (methods) : 0;
9826 dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
9827 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
9828 dgclass->count_properties = properties ? mono_array_length (properties) : 0;
9829 dgclass->count_events = events ? mono_array_length (events) : 0;
9831 dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
9832 dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
9833 dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
9834 dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
9835 dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
9836 dgclass->field_objects = g_new0 (MonoObject*, dgclass->count_fields);
9837 dgclass->field_generic_types = g_new0 (MonoType*, dgclass->count_fields);
9839 for (i = 0; i < dgclass->count_methods; i++) {
9840 MonoObject *obj = mono_array_get (methods, gpointer, i);
9842 dgclass->methods [i] = inflate_method (type, obj);
9845 for (i = 0; i < dgclass->count_ctors; i++) {
9846 MonoObject *obj = mono_array_get (ctors, gpointer, i);
9848 dgclass->ctors [i] = inflate_method (type, obj);
9851 for (i = 0; i < dgclass->count_fields; i++) {
9852 MonoObject *obj = mono_array_get (fields, gpointer, i);
9853 MonoClassField *field, *inflated_field = NULL;
9855 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
9856 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
9857 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
9858 field = ((MonoReflectionField *) obj)->field;
9859 else {
9860 field = NULL; /* prevent compiler warning */
9861 g_assert_not_reached ();
9864 dgclass->fields [i] = *field;
9865 dgclass->fields [i].parent = klass;
9866 dgclass->fields [i].type = mono_class_inflate_generic_type (
9867 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
9868 dgclass->field_generic_types [i] = field->type;
9869 MOVING_GC_REGISTER (&dgclass->field_objects [i]);
9870 dgclass->field_objects [i] = obj;
9872 if (inflated_field) {
9873 g_free (inflated_field);
9874 } else {
9875 dgclass->fields [i].name = g_strdup (dgclass->fields [i].name);
9879 for (i = 0; i < dgclass->count_properties; i++) {
9880 MonoObject *obj = mono_array_get (properties, gpointer, i);
9881 MonoProperty *property = &dgclass->properties [i];
9883 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
9884 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
9886 property->parent = klass;
9887 property->attrs = pb->attrs;
9888 property->name = mono_string_to_utf8 (pb->name);
9889 if (pb->get_method)
9890 property->get = inflate_method (type, (MonoObject *) pb->get_method);
9891 if (pb->set_method)
9892 property->set = inflate_method (type, (MonoObject *) pb->set_method);
9893 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
9894 *property = *((MonoReflectionProperty *) obj)->property;
9895 property->name = g_strdup (property->name);
9897 if (property->get)
9898 property->get = inflate_mono_method (klass, property->get, NULL);
9899 if (property->set)
9900 property->set = inflate_mono_method (klass, property->set, NULL);
9901 } else
9902 g_assert_not_reached ();
9905 for (i = 0; i < dgclass->count_events; i++) {
9906 MonoObject *obj = mono_array_get (events, gpointer, i);
9907 MonoEvent *event = &dgclass->events [i];
9909 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
9910 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
9912 event->parent = klass;
9913 event->attrs = eb->attrs;
9914 event->name = mono_string_to_utf8 (eb->name);
9915 if (eb->add_method)
9916 event->add = inflate_method (type, (MonoObject *) eb->add_method);
9917 if (eb->remove_method)
9918 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
9919 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
9920 *event = *((MonoReflectionMonoEvent *) obj)->event;
9921 event->name = g_strdup (event->name);
9923 if (event->add)
9924 event->add = inflate_mono_method (klass, event->add, NULL);
9925 if (event->remove)
9926 event->remove = inflate_mono_method (klass, event->remove, NULL);
9927 } else
9928 g_assert_not_reached ();
9931 dgclass->initialized = TRUE;
9934 static void
9935 ensure_generic_class_runtime_vtable (MonoClass *klass)
9937 MonoClass *gklass = klass->generic_class->container_class;
9938 int i;
9940 if (klass->wastypebuilder)
9941 return;
9943 ensure_runtime_vtable (gklass);
9945 klass->method.count = gklass->method.count;
9946 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
9948 for (i = 0; i < klass->method.count; i++) {
9949 klass->methods [i] = mono_class_inflate_generic_method_full (
9950 gklass->methods [i], klass, mono_class_get_context (klass));
9953 klass->interface_count = gklass->interface_count;
9954 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
9955 for (i = 0; i < klass->interface_count; ++i) {
9956 MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
9957 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
9958 mono_metadata_free_type (iface_type);
9960 ensure_runtime_vtable (klass->interfaces [i]);
9962 klass->interfaces_inited = 1;
9964 /*We can only finish with this klass once it's parent has as well*/
9965 if (gklass->wastypebuilder)
9966 klass->wastypebuilder = TRUE;
9967 return;
9970 static void
9971 ensure_runtime_vtable (MonoClass *klass)
9973 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9974 int i, num, j;
9976 if (!klass->image->dynamic || (!tb && !klass->generic_class) || klass->wastypebuilder)
9977 return;
9978 if (klass->parent)
9979 ensure_runtime_vtable (klass->parent);
9981 if (tb) {
9982 num = tb->ctors? mono_array_length (tb->ctors): 0;
9983 num += tb->num_methods;
9984 klass->method.count = num;
9985 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
9986 num = tb->ctors? mono_array_length (tb->ctors): 0;
9987 for (i = 0; i < num; ++i)
9988 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
9989 num = tb->num_methods;
9990 j = i;
9991 for (i = 0; i < num; ++i)
9992 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
9994 if (tb->interfaces) {
9995 klass->interface_count = mono_array_length (tb->interfaces);
9996 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
9997 for (i = 0; i < klass->interface_count; ++i) {
9998 MonoReflectionType *iface = mono_type_array_get (tb->interfaces, i);
9999 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
10000 ensure_runtime_vtable (klass->interfaces [i]);
10002 klass->interfaces_inited = 1;
10004 } else if (klass->generic_class){
10005 ensure_generic_class_runtime_vtable (klass);
10008 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
10009 for (i = 0; i < klass->method.count; ++i)
10010 klass->methods [i]->slot = i;
10012 mono_class_setup_interface_offsets (klass);
10013 mono_class_setup_interface_id (klass);
10017 * The generic vtable is needed even if image->run is not set since some
10018 * runtime code like ves_icall_Type_GetMethodsByName depends on
10019 * method->slot being defined.
10023 * tb->methods could not be freed since it is used for determining
10024 * overrides during dynamic vtable construction.
10028 void
10029 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
10031 MonoReflectionTypeBuilder *tb;
10032 int i, onum;
10034 *overrides = NULL;
10035 *num_overrides = 0;
10037 g_assert (klass->image->dynamic);
10039 if (!klass->reflection_info)
10040 return;
10042 g_assert (strcmp (((MonoObject*)klass->reflection_info)->vtable->klass->name, "TypeBuilder") == 0);
10044 tb = (MonoReflectionTypeBuilder*)klass->reflection_info;
10046 onum = 0;
10047 if (tb->methods) {
10048 for (i = 0; i < tb->num_methods; ++i) {
10049 MonoReflectionMethodBuilder *mb =
10050 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10051 if (mb->override_method)
10052 onum ++;
10056 if (onum) {
10057 *overrides = g_new0 (MonoMethod*, onum * 2);
10059 onum = 0;
10060 for (i = 0; i < tb->num_methods; ++i) {
10061 MonoReflectionMethodBuilder *mb =
10062 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10063 if (mb->override_method) {
10064 (*overrides) [onum * 2] =
10065 mb->override_method->method;
10066 (*overrides) [onum * 2 + 1] =
10067 mb->mhandle;
10069 /* FIXME: What if 'override_method' is a MethodBuilder ? */
10070 g_assert (mb->override_method->method);
10071 g_assert (mb->mhandle);
10073 onum ++;
10078 *num_overrides = onum;
10081 static void
10082 typebuilder_setup_fields (MonoClass *klass)
10084 MonoReflectionTypeBuilder *tb = klass->reflection_info;
10085 MonoReflectionFieldBuilder *fb;
10086 MonoClassField *field;
10087 MonoImage *image = klass->image;
10088 const char *p, *p2;
10089 int i;
10090 guint32 len, idx, real_size = 0;
10092 klass->field.count = tb->num_fields;
10093 klass->field.first = 0;
10095 if (tb->class_size) {
10096 g_assert ((tb->packing_size & 0xfffffff0) == 0);
10097 klass->packing_size = tb->packing_size;
10098 real_size = klass->instance_size + tb->class_size;
10101 if (!klass->field.count) {
10102 klass->instance_size = MAX (klass->instance_size, real_size);
10103 return;
10106 klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
10107 mono_class_alloc_ext (klass);
10108 klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
10110 for (i = 0; i < klass->field.count; ++i) {
10111 fb = mono_array_get (tb->fields, gpointer, i);
10112 field = &klass->fields [i];
10113 field->name = mono_string_to_utf8_image (image, fb->name);
10114 if (fb->attrs) {
10115 field->type = mono_metadata_type_dup (klass->image, monotype_cast (fb->type)->type);
10116 field->type->attrs = fb->attrs;
10117 } else {
10118 field->type = monotype_cast (fb->type)->type;
10120 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
10121 klass->ext->field_def_values [i].data = mono_array_addr (fb->rva_data, char, 0);
10122 if (fb->offset != -1)
10123 field->offset = fb->offset;
10124 field->parent = klass;
10125 fb->handle = field;
10126 mono_save_custom_attrs (klass->image, field, fb->cattrs);
10128 if (fb->def_value) {
10129 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
10130 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
10131 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
10132 /* Copy the data from the blob since it might get realloc-ed */
10133 p = assembly->blob.data + idx;
10134 len = mono_metadata_decode_blob_size (p, &p2);
10135 len += p2 - p;
10136 klass->ext->field_def_values [i].data = mono_image_alloc (image, len);
10137 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
10141 klass->instance_size = MAX (klass->instance_size, real_size);
10142 mono_class_layout_fields (klass);
10145 static void
10146 typebuilder_setup_properties (MonoClass *klass)
10148 MonoReflectionTypeBuilder *tb = klass->reflection_info;
10149 MonoReflectionPropertyBuilder *pb;
10150 MonoImage *image = klass->image;
10151 MonoProperty *properties;
10152 int i;
10154 if (!klass->ext)
10155 klass->ext = image_g_new0 (image, MonoClassExt, 1);
10157 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
10158 klass->ext->property.first = 0;
10160 properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
10161 klass->ext->properties = properties;
10162 for (i = 0; i < klass->ext->property.count; ++i) {
10163 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
10164 properties [i].parent = klass;
10165 properties [i].attrs = pb->attrs;
10166 properties [i].name = mono_string_to_utf8_image (image, pb->name);
10167 if (pb->get_method)
10168 properties [i].get = pb->get_method->mhandle;
10169 if (pb->set_method)
10170 properties [i].set = pb->set_method->mhandle;
10172 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
10176 MonoReflectionEvent *
10177 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
10179 MonoEvent *event = g_new0 (MonoEvent, 1);
10180 MonoClass *klass;
10181 int j;
10183 klass = mono_class_from_mono_type (tb->type.type);
10185 event->parent = klass;
10186 event->attrs = eb->attrs;
10187 event->name = mono_string_to_utf8 (eb->name);
10188 if (eb->add_method)
10189 event->add = eb->add_method->mhandle;
10190 if (eb->remove_method)
10191 event->remove = eb->remove_method->mhandle;
10192 if (eb->raise_method)
10193 event->raise = eb->raise_method->mhandle;
10195 if (eb->other_methods) {
10196 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
10197 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
10198 MonoReflectionMethodBuilder *mb =
10199 mono_array_get (eb->other_methods,
10200 MonoReflectionMethodBuilder*, j);
10201 event->other [j] = mb->mhandle;
10205 return mono_event_get_object (mono_object_domain (tb), klass, event);
10208 static void
10209 typebuilder_setup_events (MonoClass *klass)
10211 MonoReflectionTypeBuilder *tb = klass->reflection_info;
10212 MonoReflectionEventBuilder *eb;
10213 MonoImage *image = klass->image;
10214 MonoEvent *events;
10215 int i, j;
10217 if (!klass->ext)
10218 klass->ext = image_g_new0 (image, MonoClassExt, 1);
10220 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
10221 klass->ext->event.first = 0;
10223 events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
10224 klass->ext->events = events;
10225 for (i = 0; i < klass->ext->event.count; ++i) {
10226 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
10227 events [i].parent = klass;
10228 events [i].attrs = eb->attrs;
10229 events [i].name = mono_string_to_utf8_image (image, eb->name);
10230 if (eb->add_method)
10231 events [i].add = eb->add_method->mhandle;
10232 if (eb->remove_method)
10233 events [i].remove = eb->remove_method->mhandle;
10234 if (eb->raise_method)
10235 events [i].raise = eb->raise_method->mhandle;
10237 if (eb->other_methods) {
10238 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
10239 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
10240 MonoReflectionMethodBuilder *mb =
10241 mono_array_get (eb->other_methods,
10242 MonoReflectionMethodBuilder*, j);
10243 events [i].other [j] = mb->mhandle;
10246 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
10250 static gboolean
10251 remove_instantiations_of (gpointer key,
10252 gpointer value,
10253 gpointer user_data)
10255 MonoType *type = (MonoType*)key;
10256 MonoClass *klass = (MonoClass*)user_data;
10258 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass))
10259 return TRUE;
10260 else
10261 return FALSE;
10264 static void
10265 check_array_for_usertypes (MonoArray *arr)
10267 int i;
10269 if (!arr)
10270 return;
10272 for (i = 0; i < mono_array_length (arr); ++i)
10273 CHECK_MONOTYPE (mono_array_get (arr, gpointer, i));
10276 MonoReflectionType*
10277 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
10279 MonoClass *klass;
10280 MonoDomain* domain;
10281 MonoReflectionType* res;
10282 int i, j;
10284 MONO_ARCH_SAVE_REGS;
10286 domain = mono_object_domain (tb);
10287 klass = mono_class_from_mono_type (tb->type.type);
10290 * Check for user defined Type subclasses.
10292 CHECK_MONOTYPE (tb->parent);
10293 check_array_for_usertypes (tb->interfaces);
10294 if (tb->fields) {
10295 for (i = 0; i < mono_array_length (tb->fields); ++i) {
10296 MonoReflectionFieldBuilder *fb = mono_array_get (tb->fields, gpointer, i);
10297 if (fb) {
10298 CHECK_MONOTYPE (fb->type);
10299 check_array_for_usertypes (fb->modreq);
10300 check_array_for_usertypes (fb->modopt);
10301 if (fb->marshal_info && fb->marshal_info->marshaltyperef)
10302 CHECK_MONOTYPE (fb->marshal_info->marshaltyperef);
10306 if (tb->methods) {
10307 for (i = 0; i < mono_array_length (tb->methods); ++i) {
10308 MonoReflectionMethodBuilder *mb = mono_array_get (tb->methods, gpointer, i);
10309 if (mb) {
10310 CHECK_MONOTYPE (mb->rtype);
10311 check_array_for_usertypes (mb->return_modreq);
10312 check_array_for_usertypes (mb->return_modopt);
10313 check_array_for_usertypes (mb->parameters);
10314 if (mb->param_modreq)
10315 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
10316 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
10317 if (mb->param_modopt)
10318 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
10319 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
10323 if (tb->ctors) {
10324 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
10325 MonoReflectionCtorBuilder *mb = mono_array_get (tb->ctors, gpointer, i);
10326 if (mb) {
10327 check_array_for_usertypes (mb->parameters);
10328 if (mb->param_modreq)
10329 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
10330 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
10331 if (mb->param_modopt)
10332 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
10333 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
10338 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
10341 * we need to lock the domain because the lock will be taken inside
10342 * So, we need to keep the locking order correct.
10344 mono_loader_lock ();
10345 mono_domain_lock (domain);
10346 if (klass->wastypebuilder) {
10347 mono_domain_unlock (domain);
10348 mono_loader_unlock ();
10349 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10352 * Fields to set in klass:
10353 * the various flags: delegate/unicode/contextbound etc.
10355 klass->flags = tb->attrs;
10356 klass->has_cctor = 1;
10357 klass->has_finalize = 1;
10359 #if 0
10360 if (!((MonoDynamicImage*)klass->image)->run) {
10361 if (klass->generic_container) {
10362 /* FIXME: The code below can't handle generic classes */
10363 klass->wastypebuilder = TRUE;
10364 mono_loader_unlock ();
10365 mono_domain_unlock (domain);
10366 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10369 #endif
10371 /* enums are done right away */
10372 if (!klass->enumtype)
10373 ensure_runtime_vtable (klass);
10375 if (tb->subtypes) {
10376 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
10377 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
10378 mono_class_alloc_ext (klass);
10379 klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, mono_class_from_mono_type (subtb->type.type));
10383 klass->nested_classes_inited = TRUE;
10385 /* fields and object layout */
10386 if (klass->parent) {
10387 if (!klass->parent->size_inited)
10388 mono_class_init (klass->parent);
10389 klass->instance_size = klass->parent->instance_size;
10390 klass->sizes.class_size = 0;
10391 klass->min_align = klass->parent->min_align;
10392 /* if the type has no fields we won't call the field_setup
10393 * routine which sets up klass->has_references.
10395 klass->has_references |= klass->parent->has_references;
10396 } else {
10397 klass->instance_size = sizeof (MonoObject);
10398 klass->min_align = 1;
10401 /* FIXME: handle packing_size and instance_size */
10402 typebuilder_setup_fields (klass);
10404 typebuilder_setup_properties (klass);
10406 typebuilder_setup_events (klass);
10408 klass->wastypebuilder = TRUE;
10411 * If we are a generic TypeBuilder, there might be instantiations in the type cache
10412 * which have type System.Reflection.MonoGenericClass, but after the type is created,
10413 * we want to return normal System.MonoType objects, so clear these out from the cache.
10415 if (domain->type_hash && klass->generic_container)
10416 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of, klass);
10418 mono_domain_unlock (domain);
10419 mono_loader_unlock ();
10421 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
10422 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10423 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
10426 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10427 g_assert (res != (MonoReflectionType*)tb);
10429 return res;
10432 void
10433 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
10435 MonoGenericParamFull *param;
10436 MonoImage *image;
10437 MonoClass *pklass;
10439 MONO_ARCH_SAVE_REGS;
10441 param = g_new0 (MonoGenericParamFull, 1);
10443 if (gparam->mbuilder) {
10444 if (!gparam->mbuilder->generic_container) {
10445 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
10446 MonoClass *klass = mono_class_from_mono_type (tb->type.type);
10447 gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10448 gparam->mbuilder->generic_container->is_method = TRUE;
10450 param->param.owner = gparam->mbuilder->generic_container;
10451 } else if (gparam->tbuilder) {
10452 if (!gparam->tbuilder->generic_container) {
10453 MonoClass *klass = mono_class_from_mono_type (gparam->tbuilder->type.type);
10454 gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10455 gparam->tbuilder->generic_container->owner.klass = klass;
10457 param->param.owner = gparam->tbuilder->generic_container;
10460 param->info.name = mono_string_to_utf8 (gparam->name);
10461 param->param.num = gparam->index;
10463 image = &gparam->tbuilder->module->dynamic_image->image;
10464 pklass = mono_class_from_generic_parameter ((MonoGenericParam *) param, image, gparam->mbuilder != NULL);
10466 gparam->type.type = &pklass->byval_arg;
10468 MOVING_GC_REGISTER (&pklass->reflection_info);
10469 pklass->reflection_info = gparam; /* FIXME: GC pin gparam */
10472 MonoArray *
10473 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
10475 MonoDynamicImage *assembly = sig->module->dynamic_image;
10476 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
10477 guint32 buflen, i;
10478 MonoArray *result;
10479 SigBuffer buf;
10481 check_array_for_usertypes (sig->arguments);
10483 sigbuffer_init (&buf, 32);
10485 sigbuffer_add_value (&buf, 0x07);
10486 sigbuffer_add_value (&buf, na);
10487 for (i = 0; i < na; ++i) {
10488 MonoReflectionType *type = mono_type_array_get (sig->arguments, i);
10489 encode_reflection_type (assembly, type, &buf);
10492 buflen = buf.p - buf.buf;
10493 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10494 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
10495 sigbuffer_free (&buf);
10497 return result;
10500 MonoArray *
10501 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
10503 MonoDynamicImage *assembly = sig->module->dynamic_image;
10504 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
10505 guint32 buflen, i;
10506 MonoArray *result;
10507 SigBuffer buf;
10509 check_array_for_usertypes (sig->arguments);
10511 sigbuffer_init (&buf, 32);
10513 sigbuffer_add_value (&buf, 0x06);
10514 for (i = 0; i < na; ++i) {
10515 MonoReflectionType *type = mono_type_array_get (sig->arguments, i);
10516 encode_reflection_type (assembly, type, &buf);
10519 buflen = buf.p - buf.buf;
10520 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10521 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
10522 sigbuffer_free (&buf);
10524 return result;
10527 void
10528 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
10530 ReflectionMethodBuilder rmb;
10531 MonoMethodSignature *sig;
10532 MonoClass *klass;
10533 GSList *l;
10534 int i;
10536 sig = dynamic_method_to_signature (mb);
10538 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
10541 * Resolve references.
10544 * Every second entry in the refs array is reserved for storing handle_class,
10545 * which is needed by the ldtoken implementation in the JIT.
10547 rmb.nrefs = mb->nrefs;
10548 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
10549 for (i = 0; i < mb->nrefs; i += 2) {
10550 MonoClass *handle_class;
10551 gpointer ref;
10552 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
10554 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
10555 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
10557 * The referenced DynamicMethod should already be created by the managed
10558 * code, except in the case of circular references. In that case, we store
10559 * method in the refs array, and fix it up later when the referenced
10560 * DynamicMethod is created.
10562 if (method->mhandle) {
10563 ref = method->mhandle;
10564 } else {
10565 /* FIXME: GC object stored in unmanaged memory */
10566 ref = method;
10568 /* FIXME: GC object stored in unmanaged memory */
10569 method->referenced_by = g_slist_append (method->referenced_by, mb);
10571 handle_class = mono_defaults.methodhandle_class;
10572 } else {
10573 MonoException *ex = NULL;
10574 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
10575 if (!ref)
10576 ex = mono_get_exception_type_load (NULL, NULL);
10577 else if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
10578 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
10580 if (ex) {
10581 g_free (rmb.refs);
10582 mono_raise_exception (ex);
10583 return;
10587 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
10588 rmb.refs [i + 1] = handle_class;
10591 klass = mb->owner ? mono_class_from_mono_type (mb->owner->type) : mono_defaults.object_class;
10593 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10595 /* Fix up refs entries pointing at us */
10596 for (l = mb->referenced_by; l; l = l->next) {
10597 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
10598 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
10599 gpointer *data;
10601 g_assert (method->mhandle);
10603 data = (gpointer*)wrapper->method_data;
10604 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
10605 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
10606 data [i + 1] = mb->mhandle;
10609 g_slist_free (mb->referenced_by);
10611 g_free (rmb.refs);
10613 /* ilgen is no longer needed */
10614 mb->ilgen = NULL;
10617 #endif /* DISABLE_REFLECTION_EMIT */
10619 void
10620 mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod *mb)
10622 g_assert (mb);
10624 if (mb->mhandle)
10625 mono_runtime_free_method (
10626 mono_object_get_domain ((MonoObject*)mb), mb->mhandle);
10631 * mono_reflection_is_valid_dynamic_token:
10633 * Returns TRUE if token is valid.
10636 gboolean
10637 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
10639 return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
10642 #ifndef DISABLE_REFLECTION_EMIT
10645 * mono_reflection_lookup_dynamic_token:
10647 * Finish the Builder object pointed to by TOKEN and return the corresponding
10648 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
10649 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
10650 * mapping table.
10652 * LOCKING: Take the loader lock
10654 gpointer
10655 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
10657 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
10658 MonoObject *obj;
10659 MonoClass *klass;
10661 mono_loader_lock ();
10662 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
10663 mono_loader_unlock ();
10664 if (!obj) {
10665 if (valid_token)
10666 g_assert_not_reached ();
10667 else
10668 return NULL;
10671 if (!handle_class)
10672 handle_class = &klass;
10673 return resolve_object (image, obj, handle_class, context);
10677 * ensure_complete_type:
10679 * Ensure that KLASS is completed if it is a dynamic type, or references
10680 * dynamic types.
10682 static void
10683 ensure_complete_type (MonoClass *klass)
10685 if (klass->image->dynamic && !klass->wastypebuilder) {
10686 MonoReflectionTypeBuilder *tb = klass->reflection_info;
10688 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10690 // Asserting here could break a lot of code
10691 //g_assert (klass->wastypebuilder);
10694 if (klass->generic_class) {
10695 MonoGenericInst *inst = klass->generic_class->context.class_inst;
10696 int i;
10698 for (i = 0; i < inst->type_argc; ++i) {
10699 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
10704 static gpointer
10705 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
10707 gpointer result = NULL;
10709 if (strcmp (obj->vtable->klass->name, "String") == 0) {
10710 result = mono_string_intern ((MonoString*)obj);
10711 *handle_class = NULL;
10712 g_assert (result);
10713 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
10714 MonoReflectionType *tb = (MonoReflectionType*)obj;
10715 if (context) {
10716 MonoType *inflated = mono_class_inflate_generic_type (tb->type, context);
10717 result = mono_class_from_mono_type (inflated);
10718 mono_metadata_free_type (inflated);
10719 } else {
10720 result = mono_class_from_mono_type (tb->type);
10722 *handle_class = mono_defaults.typehandle_class;
10723 g_assert (result);
10724 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
10725 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
10726 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
10727 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
10728 result = ((MonoReflectionMethod*)obj)->method;
10729 if (context)
10730 result = mono_class_inflate_generic_method (result, context);
10731 *handle_class = mono_defaults.methodhandle_class;
10732 g_assert (result);
10733 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
10734 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
10735 result = mb->mhandle;
10736 if (!result) {
10737 /* Type is not yet created */
10738 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
10740 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10743 * Hopefully this has been filled in by calling CreateType() on the
10744 * TypeBuilder.
10747 * TODO: This won't work if the application finishes another
10748 * TypeBuilder instance instead of this one.
10750 result = mb->mhandle;
10752 if (context)
10753 result = mono_class_inflate_generic_method (result, context);
10754 *handle_class = mono_defaults.methodhandle_class;
10755 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
10756 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
10758 result = cb->mhandle;
10759 if (!result) {
10760 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
10762 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10763 result = cb->mhandle;
10765 if (context)
10766 result = mono_class_inflate_generic_method (result, context);
10767 *handle_class = mono_defaults.methodhandle_class;
10768 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
10769 MonoClassField *field = ((MonoReflectionField*)obj)->field;
10771 ensure_complete_type (field->parent);
10772 if (context) {
10773 MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
10774 MonoClass *class = mono_class_from_mono_type (inflated);
10775 MonoClassField *inflated_field;
10776 gpointer iter = NULL;
10777 mono_metadata_free_type (inflated);
10778 while ((inflated_field = mono_class_get_fields (class, &iter))) {
10779 if (!strcmp (field->name, inflated_field->name))
10780 break;
10782 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
10783 result = inflated_field;
10784 } else {
10785 result = field;
10787 *handle_class = mono_defaults.fieldhandle_class;
10788 g_assert (result);
10789 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
10790 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
10791 result = fb->handle;
10793 if (!result) {
10794 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
10796 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10797 result = fb->handle;
10800 if (fb->handle && fb->handle->parent->generic_container) {
10801 MonoClass *klass = fb->handle->parent;
10802 MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
10803 MonoClass *inflated = mono_class_from_mono_type (type);
10805 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
10806 g_assert (result);
10807 mono_metadata_free_type (type);
10809 *handle_class = mono_defaults.fieldhandle_class;
10810 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
10811 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
10812 MonoClass *klass;
10814 klass = tb->type.type->data.klass;
10815 if (klass->wastypebuilder) {
10816 /* Already created */
10817 result = klass;
10819 else {
10820 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10821 result = tb->type.type->data.klass;
10822 g_assert (result);
10824 *handle_class = mono_defaults.typehandle_class;
10825 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
10826 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
10827 MonoMethodSignature *sig;
10828 int nargs, i;
10830 if (helper->arguments)
10831 nargs = mono_array_length (helper->arguments);
10832 else
10833 nargs = 0;
10835 sig = mono_metadata_signature_alloc (image, nargs);
10836 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
10837 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
10839 if (helper->call_conv == 0) /* unmanaged */
10840 sig->call_convention = helper->unmanaged_call_conv - 1;
10841 else
10842 if (helper->call_conv & 0x02)
10843 sig->call_convention = MONO_CALL_VARARG;
10844 else
10845 sig->call_convention = MONO_CALL_DEFAULT;
10847 sig->param_count = nargs;
10848 /* TODO: Copy type ? */
10849 sig->ret = helper->return_type->type;
10850 for (i = 0; i < nargs; ++i) {
10851 MonoReflectionType *rt = mono_type_array_get (helper->arguments, i);
10852 sig->params [i] = rt->type;
10855 result = sig;
10856 *handle_class = NULL;
10857 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
10858 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
10859 /* Already created by the managed code */
10860 g_assert (method->mhandle);
10861 result = method->mhandle;
10862 *handle_class = mono_defaults.methodhandle_class;
10863 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
10864 MonoReflectionType *tb = (MonoReflectionType*)obj;
10865 MonoType *type = mono_class_inflate_generic_type (tb->type, context);
10866 result = mono_class_from_mono_type (type);
10867 *handle_class = mono_defaults.typehandle_class;
10868 g_assert (result);
10869 mono_metadata_free_type (type);
10870 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
10871 MonoReflectionGenericClass *ref = (MonoReflectionGenericClass*)obj;
10872 MonoType *type = mono_class_inflate_generic_type (ref->type.type, context);
10873 result = mono_class_from_mono_type (type);
10874 *handle_class = mono_defaults.typehandle_class;
10875 g_assert (result);
10876 mono_metadata_free_type (type);
10877 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
10878 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
10879 MonoClass *inflated;
10880 MonoType *type;
10882 type = mono_class_inflate_generic_type (f->inst->type.type, context);
10883 inflated = mono_class_from_mono_type (type);
10885 g_assert (f->fb->handle);
10886 result = mono_class_get_field_from_name (inflated, mono_field_get_name (f->fb->handle));
10887 g_assert (result);
10888 mono_metadata_free_type (type);
10889 *handle_class = mono_defaults.fieldhandle_class;
10890 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
10891 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
10892 MonoType *type = mono_class_inflate_generic_type (c->inst->type.type, context);
10893 MonoClass *inflated_klass = mono_class_from_mono_type (type);
10894 g_assert (c->cb->mhandle);
10895 result = inflate_mono_method (inflated_klass, c->cb->mhandle, (MonoObject*)c->cb);
10896 *handle_class = mono_defaults.methodhandle_class;
10897 mono_metadata_free_type (type);
10898 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
10899 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
10900 MonoType *type = mono_class_inflate_generic_type (m->inst->type.type, context);
10901 MonoClass *inflated_klass = mono_class_from_mono_type (type);
10902 g_assert (m->mb->mhandle);
10903 result = inflate_mono_method (inflated_klass, m->mb->mhandle, (MonoObject*)m->mb);
10904 *handle_class = mono_defaults.methodhandle_class;
10905 mono_metadata_free_type (type);
10906 } else {
10907 g_print (obj->vtable->klass->name);
10908 g_assert_not_reached ();
10910 return result;
10913 #else /* DISABLE_REFLECTION_EMIT */
10915 MonoArray*
10916 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
10918 g_assert_not_reached ();
10919 return NULL;
10922 void
10923 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
10925 g_assert_not_reached ();
10928 void
10929 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
10931 g_assert_not_reached ();
10934 void
10935 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
10937 g_assert_not_reached ();
10940 void
10941 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
10943 g_assert_not_reached ();
10946 void
10947 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
10949 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
10952 void
10953 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
10955 g_assert_not_reached ();
10958 MonoReflectionModule *
10959 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
10961 g_assert_not_reached ();
10962 return NULL;
10965 guint32
10966 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
10968 g_assert_not_reached ();
10969 return 0;
10972 guint32
10973 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
10975 g_assert_not_reached ();
10976 return 0;
10979 guint32
10980 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
10981 gboolean create_methodspec, gboolean register_token)
10983 g_assert_not_reached ();
10984 return 0;
10987 void
10988 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
10992 void
10993 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
10994 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
10995 MonoArray *events)
10997 g_assert_not_reached ();
11000 void
11001 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
11003 *overrides = NULL;
11004 *num_overrides = 0;
11007 MonoReflectionEvent *
11008 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11010 g_assert_not_reached ();
11011 return NULL;
11014 MonoReflectionType*
11015 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11017 g_assert_not_reached ();
11018 return NULL;
11021 void
11022 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
11024 g_assert_not_reached ();
11027 MonoArray *
11028 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
11030 g_assert_not_reached ();
11031 return NULL;
11034 MonoArray *
11035 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
11037 g_assert_not_reached ();
11038 return NULL;
11041 void
11042 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
11046 gpointer
11047 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
11049 return NULL;
11052 #endif /* DISABLE_REFLECTION_EMIT */
11054 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
11055 const static guint32 declsec_flags_map[] = {
11056 0x00000000, /* empty */
11057 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
11058 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
11059 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
11060 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
11061 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
11062 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
11063 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
11064 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
11065 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
11066 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
11067 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
11068 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
11069 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
11070 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
11071 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
11072 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
11073 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
11074 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
11078 * Returns flags that includes all available security action associated to the handle.
11079 * @token: metadata token (either for a class or a method)
11080 * @image: image where resides the metadata.
11082 static guint32
11083 mono_declsec_get_flags (MonoImage *image, guint32 token)
11085 int index = mono_metadata_declsec_from_index (image, token);
11086 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
11087 guint32 result = 0;
11088 guint32 action;
11089 int i;
11091 /* HasSecurity can be present for other, not specially encoded, attributes,
11092 e.g. SuppressUnmanagedCodeSecurityAttribute */
11093 if (index < 0)
11094 return 0;
11096 for (i = index; i < t->rows; i++) {
11097 guint32 cols [MONO_DECL_SECURITY_SIZE];
11099 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
11100 if (cols [MONO_DECL_SECURITY_PARENT] != token)
11101 break;
11103 action = cols [MONO_DECL_SECURITY_ACTION];
11104 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
11105 result |= declsec_flags_map [action];
11106 } else {
11107 g_assert_not_reached ();
11110 return result;
11114 * Get the security actions (in the form of flags) associated with the specified method.
11116 * @method: The method for which we want the declarative security flags.
11117 * Return the declarative security flags for the method (only).
11119 * Note: To keep MonoMethod size down we do not cache the declarative security flags
11120 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
11122 guint32
11123 mono_declsec_flags_from_method (MonoMethod *method)
11125 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11126 /* FIXME: No cache (for the moment) */
11127 guint32 idx = mono_method_get_index (method);
11128 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11129 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
11130 return mono_declsec_get_flags (method->klass->image, idx);
11132 return 0;
11136 * Get the security actions (in the form of flags) associated with the specified class.
11138 * @klass: The class for which we want the declarative security flags.
11139 * Return the declarative security flags for the class.
11141 * Note: We cache the flags inside the MonoClass structure as this will get
11142 * called very often (at least for each method).
11144 guint32
11145 mono_declsec_flags_from_class (MonoClass *klass)
11147 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
11148 if (!klass->ext || !klass->ext->declsec_flags) {
11149 guint32 idx;
11151 idx = mono_metadata_token_index (klass->type_token);
11152 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11153 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
11154 mono_loader_lock ();
11155 mono_class_alloc_ext (klass);
11156 mono_loader_unlock ();
11157 /* we cache the flags on classes */
11158 klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
11160 return klass->ext->declsec_flags;
11162 return 0;
11166 * Get the security actions (in the form of flags) associated with the specified assembly.
11168 * @assembly: The assembly for which we want the declarative security flags.
11169 * Return the declarative security flags for the assembly.
11171 guint32
11172 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
11174 guint32 idx = 1; /* there is only one assembly */
11175 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11176 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
11177 return mono_declsec_get_flags (assembly->image, idx);
11182 * Fill actions for the specific index (which may either be an encoded class token or
11183 * an encoded method token) from the metadata image.
11184 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
11186 static MonoBoolean
11187 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
11188 guint32 id_std, guint32 id_noncas, guint32 id_choice)
11190 MonoBoolean result = FALSE;
11191 MonoTableInfo *t;
11192 guint32 cols [MONO_DECL_SECURITY_SIZE];
11193 int index = mono_metadata_declsec_from_index (image, token);
11194 int i;
11196 t = &image->tables [MONO_TABLE_DECLSECURITY];
11197 for (i = index; i < t->rows; i++) {
11198 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
11200 if (cols [MONO_DECL_SECURITY_PARENT] != token)
11201 return result;
11203 /* if present only replace (class) permissions with method permissions */
11204 /* if empty accept either class or method permissions */
11205 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
11206 if (!actions->demand.blob) {
11207 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11208 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
11209 actions->demand.blob = (char*) (blob + 2);
11210 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
11211 result = TRUE;
11213 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
11214 if (!actions->noncasdemand.blob) {
11215 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11216 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
11217 actions->noncasdemand.blob = (char*) (blob + 2);
11218 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
11219 result = TRUE;
11221 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
11222 if (!actions->demandchoice.blob) {
11223 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11224 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
11225 actions->demandchoice.blob = (char*) (blob + 2);
11226 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
11227 result = TRUE;
11232 return result;
11235 static MonoBoolean
11236 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
11237 guint32 id_std, guint32 id_noncas, guint32 id_choice)
11239 guint32 idx = mono_metadata_token_index (klass->type_token);
11240 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11241 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
11242 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
11245 static MonoBoolean
11246 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
11247 guint32 id_std, guint32 id_noncas, guint32 id_choice)
11249 guint32 idx = mono_method_get_index (method);
11250 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11251 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
11252 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
11256 * Collect all actions (that requires to generate code in mini) assigned for
11257 * the specified method.
11258 * Note: Don't use the content of actions if the function return FALSE.
11260 MonoBoolean
11261 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
11263 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
11264 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
11265 MonoBoolean result = FALSE;
11266 guint32 flags;
11268 /* quick exit if no declarative security is present in the metadata */
11269 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11270 return FALSE;
11272 /* we want the original as the wrapper is "free" of the security informations */
11273 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
11274 method = mono_marshal_method_from_wrapper (method);
11275 if (!method)
11276 return FALSE;
11279 /* First we look for method-level attributes */
11280 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11281 mono_class_init (method->klass);
11282 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11284 result = mono_declsec_get_method_demands_params (method, demands,
11285 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
11288 /* Here we use (or create) the class declarative cache to look for demands */
11289 flags = mono_declsec_flags_from_class (method->klass);
11290 if (flags & mask) {
11291 if (!result) {
11292 mono_class_init (method->klass);
11293 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11295 result |= mono_declsec_get_class_demands_params (method->klass, demands,
11296 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
11299 /* The boolean return value is used as a shortcut in case nothing needs to
11300 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
11301 return result;
11306 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
11308 * Note: Don't use the content of actions if the function return FALSE.
11310 MonoBoolean
11311 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
11313 MonoBoolean result = FALSE;
11314 guint32 flags;
11316 /* quick exit if no declarative security is present in the metadata */
11317 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11318 return FALSE;
11320 /* we want the original as the wrapper is "free" of the security informations */
11321 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
11322 method = mono_marshal_method_from_wrapper (method);
11323 if (!method)
11324 return FALSE;
11327 /* results are independant - zeroize both */
11328 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
11329 memset (klass, 0, sizeof (MonoDeclSecurityActions));
11331 /* First we look for method-level attributes */
11332 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11333 mono_class_init (method->klass);
11335 result = mono_declsec_get_method_demands_params (method, cmethod,
11336 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
11339 /* Here we use (or create) the class declarative cache to look for demands */
11340 flags = mono_declsec_flags_from_class (method->klass);
11341 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
11342 mono_class_init (method->klass);
11344 result |= mono_declsec_get_class_demands_params (method->klass, klass,
11345 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
11348 return result;
11352 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
11354 * @klass The inherited class - this is the class that provides the security check (attributes)
11355 * @demans
11356 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
11358 * Note: Don't use the content of actions if the function return FALSE.
11360 MonoBoolean
11361 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
11363 MonoBoolean result = FALSE;
11364 guint32 flags;
11366 /* quick exit if no declarative security is present in the metadata */
11367 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11368 return FALSE;
11370 /* Here we use (or create) the class declarative cache to look for demands */
11371 flags = mono_declsec_flags_from_class (klass);
11372 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
11373 mono_class_init (klass);
11374 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11376 result |= mono_declsec_get_class_demands_params (klass, demands,
11377 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
11380 return result;
11384 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
11386 * Note: Don't use the content of actions if the function return FALSE.
11388 MonoBoolean
11389 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
11391 /* quick exit if no declarative security is present in the metadata */
11392 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11393 return FALSE;
11395 /* we want the original as the wrapper is "free" of the security informations */
11396 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
11397 method = mono_marshal_method_from_wrapper (method);
11398 if (!method)
11399 return FALSE;
11402 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11403 mono_class_init (method->klass);
11404 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11406 return mono_declsec_get_method_demands_params (method, demands,
11407 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
11409 return FALSE;
11413 static MonoBoolean
11414 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
11416 guint32 cols [MONO_DECL_SECURITY_SIZE];
11417 MonoTableInfo *t;
11418 int i;
11420 int index = mono_metadata_declsec_from_index (image, token);
11421 if (index == -1)
11422 return FALSE;
11424 t = &image->tables [MONO_TABLE_DECLSECURITY];
11425 for (i = index; i < t->rows; i++) {
11426 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
11428 /* shortcut - index are ordered */
11429 if (token != cols [MONO_DECL_SECURITY_PARENT])
11430 return FALSE;
11432 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
11433 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11434 entry->blob = (char*) (metadata + 2);
11435 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
11436 return TRUE;
11440 return FALSE;
11443 MonoBoolean
11444 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
11446 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11447 guint32 idx = mono_method_get_index (method);
11448 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11449 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
11450 return get_declsec_action (method->klass->image, idx, action, entry);
11452 return FALSE;
11455 MonoBoolean
11456 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
11458 /* use cache */
11459 guint32 flags = mono_declsec_flags_from_class (klass);
11460 if (declsec_flags_map [action] & flags) {
11461 guint32 idx = mono_metadata_token_index (klass->type_token);
11462 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11463 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
11464 return get_declsec_action (klass->image, idx, action, entry);
11466 return FALSE;
11469 MonoBoolean
11470 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
11472 guint32 idx = 1; /* there is only one assembly */
11473 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11474 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
11476 return get_declsec_action (assembly->image, idx, action, entry);
11479 gboolean
11480 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
11482 MonoObject *res, *exc;
11483 void *params [1];
11484 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
11485 static MonoMethod *method = NULL;
11487 if (!System_Reflection_Emit_TypeBuilder) {
11488 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
11489 g_assert (System_Reflection_Emit_TypeBuilder);
11491 if (method == NULL) {
11492 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
11493 g_assert (method);
11497 * The result of mono_type_get_object () might be a System.MonoType but we
11498 * need a TypeBuilder so use klass->reflection_info.
11500 g_assert (klass->reflection_info);
11501 g_assert (!strcmp (((MonoObject*)(klass->reflection_info))->vtable->klass->name, "TypeBuilder"));
11503 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
11505 res = mono_runtime_invoke (method, (MonoObject*)(klass->reflection_info), params, &exc);
11506 if (exc)
11507 return FALSE;
11508 else
11509 return *(MonoBoolean*)mono_object_unbox (res);