2009-02-03 Geoff Norton <gnorton@novell.com>
[mono-project.git] / mono / metadata / reflection.c
blob23a1f8bafc8d7a65412a06118e1c7ca292195210
1 /*
2 * reflection.c: Routines for creating an image at runtime.
3 *
4 * Author:
5 * Paolo Molaro (lupus@ximian.com)
7 * (C) 2001, 2002 Ximian, Inc. http://www.ximian.com
9 */
10 #include <config.h>
11 #ifdef HAVE_ALLOCA_H
12 #include <alloca.h>
13 #endif
14 #include "mono/utils/mono-digest.h"
15 #include "mono/utils/mono-membar.h"
16 #include "mono/metadata/reflection.h"
17 #include "mono/metadata/tabledefs.h"
18 #include "mono/metadata/metadata-internals.h"
19 #include <mono/metadata/profiler-private.h>
20 #include "mono/metadata/class-internals.h"
21 #include "mono/metadata/gc-internal.h"
22 #include "mono/metadata/tokentype.h"
23 #include "mono/metadata/domain-internals.h"
24 #include "mono/metadata/opcodes.h"
25 #include "mono/metadata/assembly.h"
26 #include "mono/metadata/object-internals.h"
27 #include <mono/metadata/exception.h>
28 #include <mono/metadata/marshal.h>
29 #include <mono/metadata/security-manager.h>
30 #include <stdio.h>
31 #include <glib.h>
32 #include <errno.h>
33 #include <time.h>
34 #include <string.h>
35 #include <ctype.h>
36 #include "image.h"
37 #include "cil-coff.h"
38 #include "mono-endian.h"
39 #include <mono/metadata/gc-internal.h>
40 #include <mono/metadata/mempool-internals.h>
42 #if HAVE_SGEN_GC
43 static void* reflection_info_desc = NULL;
44 #define MOVING_GC_REGISTER(addr) do { \
45 if (!reflection_info_desc) { \
46 gsize bmap = 1; \
47 reflection_info_desc = mono_gc_make_descr_from_bitmap (&bmap, 1); \
48 } \
49 mono_gc_register_root ((char*)(addr), sizeof (gpointer), reflection_info_desc); \
50 } while (0)
51 #else
52 #define MOVING_GC_REGISTER(addr)
53 #endif
55 typedef struct {
56 char *p;
57 char *buf;
58 char *end;
59 } SigBuffer;
61 #define TEXT_OFFSET 512
62 #define CLI_H_SIZE 136
63 #define FILE_ALIGN 512
64 #define VIRT_ALIGN 8192
65 #define START_TEXT_RVA 0x00002000
67 typedef struct {
68 MonoReflectionILGen *ilgen;
69 MonoReflectionType *rtype;
70 MonoArray *parameters;
71 MonoArray *generic_params;
72 MonoGenericContainer *generic_container;
73 MonoArray *pinfo;
74 MonoArray *opt_types;
75 guint32 attrs;
76 guint32 iattrs;
77 guint32 call_conv;
78 guint32 *table_idx; /* note: it's a pointer */
79 MonoArray *code;
80 MonoObject *type;
81 MonoString *name;
82 MonoBoolean init_locals;
83 MonoBoolean skip_visibility;
84 MonoArray *return_modreq;
85 MonoArray *return_modopt;
86 MonoArray *param_modreq;
87 MonoArray *param_modopt;
88 MonoArray *permissions;
89 MonoMethod *mhandle;
90 guint32 nrefs;
91 gpointer *refs;
92 /* for PInvoke */
93 int charset, extra_flags, native_cc;
94 MonoString *dll, *dllentry;
95 } ReflectionMethodBuilder;
97 typedef struct {
98 guint32 owner;
99 MonoReflectionGenericParam *gparam;
100 } GenericParamTableEntry;
102 const unsigned char table_sizes [MONO_TABLE_NUM] = {
103 MONO_MODULE_SIZE,
104 MONO_TYPEREF_SIZE,
105 MONO_TYPEDEF_SIZE,
107 MONO_FIELD_SIZE,
109 MONO_METHOD_SIZE,
111 MONO_PARAM_SIZE,
112 MONO_INTERFACEIMPL_SIZE,
113 MONO_MEMBERREF_SIZE, /* 0x0A */
114 MONO_CONSTANT_SIZE,
115 MONO_CUSTOM_ATTR_SIZE,
116 MONO_FIELD_MARSHAL_SIZE,
117 MONO_DECL_SECURITY_SIZE,
118 MONO_CLASS_LAYOUT_SIZE,
119 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
120 MONO_STAND_ALONE_SIGNATURE_SIZE,
121 MONO_EVENT_MAP_SIZE,
123 MONO_EVENT_SIZE,
124 MONO_PROPERTY_MAP_SIZE,
126 MONO_PROPERTY_SIZE,
127 MONO_METHOD_SEMA_SIZE,
128 MONO_METHODIMPL_SIZE,
129 MONO_MODULEREF_SIZE, /* 0x1A */
130 MONO_TYPESPEC_SIZE,
131 MONO_IMPLMAP_SIZE,
132 MONO_FIELD_RVA_SIZE,
135 MONO_ASSEMBLY_SIZE, /* 0x20 */
136 MONO_ASSEMBLY_PROCESSOR_SIZE,
137 MONO_ASSEMBLYOS_SIZE,
138 MONO_ASSEMBLYREF_SIZE,
139 MONO_ASSEMBLYREFPROC_SIZE,
140 MONO_ASSEMBLYREFOS_SIZE,
141 MONO_FILE_SIZE,
142 MONO_EXP_TYPE_SIZE,
143 MONO_MANIFEST_SIZE,
144 MONO_NESTED_CLASS_SIZE,
146 MONO_GENERICPARAM_SIZE, /* 0x2A */
147 MONO_METHODSPEC_SIZE,
148 MONO_GENPARCONSTRAINT_SIZE
152 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
153 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
154 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
155 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
156 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
157 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec);
158 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
159 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
160 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
161 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
162 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
163 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
164 static void ensure_runtime_vtable (MonoClass *klass);
165 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
166 static void encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
167 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
168 static MonoObject *mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob);
169 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t);
170 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
171 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method);
172 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
174 #define mono_reflection_lock() EnterCriticalSection (&reflection_mutex)
175 #define mono_reflection_unlock() LeaveCriticalSection (&reflection_mutex)
176 static CRITICAL_SECTION reflection_mutex;
178 void
179 mono_reflection_init (void)
181 InitializeCriticalSection (&reflection_mutex);
184 static void
185 sigbuffer_init (SigBuffer *buf, int size)
187 buf->buf = g_malloc (size);
188 buf->p = buf->buf;
189 buf->end = buf->buf + size;
192 static void
193 sigbuffer_make_room (SigBuffer *buf, int size)
195 if (buf->end - buf->p < size) {
196 int new_size = buf->end - buf->buf + size + 32;
197 char *p = g_realloc (buf->buf, new_size);
198 size = buf->p - buf->buf;
199 buf->buf = p;
200 buf->p = p + size;
201 buf->end = buf->buf + new_size;
205 static void
206 sigbuffer_add_value (SigBuffer *buf, guint32 val)
208 sigbuffer_make_room (buf, 6);
209 mono_metadata_encode_value (val, buf->p, &buf->p);
212 static void
213 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
215 sigbuffer_make_room (buf, 1);
216 buf->p [0] = val;
217 buf->p++;
220 static void
221 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
223 sigbuffer_make_room (buf, size);
224 memcpy (buf->p, p, size);
225 buf->p += size;
228 static void
229 sigbuffer_free (SigBuffer *buf)
231 g_free (buf->buf);
235 * mp_g_alloc:
237 * Allocate memory from the mempool MP if it is non-NULL. Otherwise, allocate memory
238 * from the C heap.
240 static gpointer
241 mp_g_malloc (MonoMemPool *mp, guint size)
243 if (mp)
244 return mono_mempool_alloc (mp, size);
245 else
246 return g_malloc (size);
250 * mp_g_alloc0:
252 * Allocate memory from the mempool MP if it is non-NULL. Otherwise, allocate memory
253 * from the C heap.
255 static gpointer
256 mp_g_malloc0 (MonoMemPool *mp, guint size)
258 if (mp)
259 return mono_mempool_alloc0 (mp, size);
260 else
261 return g_malloc0 (size);
265 * mp_string_to_utf8:
267 * Allocate memory from the mempool MP if it is non-NULL. Otherwise, allocate
268 * memory from the C heap.
270 static char *
271 mp_string_to_utf8 (MonoMemPool *mp, MonoString *s)
273 if (mp)
274 return mono_string_to_utf8_mp (mp, s);
275 else
276 return mono_string_to_utf8 (s);
279 #define mp_g_new(mp,struct_type, n_structs) \
280 ((struct_type *) mp_g_malloc (mp, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
282 #define mp_g_new0(mp,struct_type, n_structs) \
283 ((struct_type *) mp_g_malloc0 (mp, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
285 static void
286 alloc_table (MonoDynamicTable *table, guint nrows)
288 table->rows = nrows;
289 g_assert (table->columns);
290 if (nrows + 1 >= table->alloc_rows) {
291 while (nrows + 1 >= table->alloc_rows) {
292 if (table->alloc_rows == 0)
293 table->alloc_rows = 16;
294 else
295 table->alloc_rows *= 2;
298 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
302 static void
303 make_room_in_stream (MonoDynamicStream *stream, int size)
305 if (size <= stream->alloc_size)
306 return;
308 while (stream->alloc_size <= size) {
309 if (stream->alloc_size < 4096)
310 stream->alloc_size = 4096;
311 else
312 stream->alloc_size *= 2;
315 stream->data = g_realloc (stream->data, stream->alloc_size);
318 static guint32
319 string_heap_insert (MonoDynamicStream *sh, const char *str)
321 guint32 idx;
322 guint32 len;
323 gpointer oldkey, oldval;
325 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
326 return GPOINTER_TO_UINT (oldval);
328 len = strlen (str) + 1;
329 idx = sh->index;
331 make_room_in_stream (sh, idx + len);
334 * We strdup the string even if we already copy them in sh->data
335 * so that the string pointers in the hash remain valid even if
336 * we need to realloc sh->data. We may want to avoid that later.
338 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
339 memcpy (sh->data + idx, str, len);
340 sh->index += len;
341 return idx;
344 static guint32
345 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
347 char *name = mono_string_to_utf8 (str);
348 guint32 idx;
349 idx = string_heap_insert (sh, name);
350 g_free (name);
351 return idx;
354 static void
355 string_heap_init (MonoDynamicStream *sh)
357 sh->index = 0;
358 sh->alloc_size = 4096;
359 sh->data = g_malloc (4096);
360 sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
361 string_heap_insert (sh, "");
364 static guint32
365 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
367 guint32 idx;
369 make_room_in_stream (stream, stream->index + len);
370 memcpy (stream->data + stream->index, data, len);
371 idx = stream->index;
372 stream->index += len;
374 * align index? Not without adding an additional param that controls it since
375 * we may store a blob value in pieces.
377 return idx;
380 static guint32
381 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
383 guint32 idx;
385 make_room_in_stream (stream, stream->index + len);
386 memset (stream->data + stream->index, 0, len);
387 idx = stream->index;
388 stream->index += len;
389 return idx;
392 static void
393 stream_data_align (MonoDynamicStream *stream)
395 char buf [4] = {0};
396 guint32 count = stream->index % 4;
398 /* we assume the stream data will be aligned */
399 if (count)
400 mono_image_add_stream_data (stream, buf, 4 - count);
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;
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 /* modified version needed to handle building corlib */
535 static MonoClass*
536 my_mono_class_from_mono_type (MonoType *type) {
537 switch (type->type) {
538 case MONO_TYPE_ARRAY:
539 case MONO_TYPE_PTR:
540 case MONO_TYPE_SZARRAY:
541 case MONO_TYPE_GENERICINST:
542 return mono_class_from_mono_type (type);
543 case MONO_TYPE_VAR:
544 case MONO_TYPE_MVAR:
545 g_assert (type->data.generic_param->pklass);
546 return type->data.generic_param->pklass;
547 default:
548 /* should be always valid when we reach this case... */
549 return type->data.klass;
553 static MonoClass *
554 default_class_from_mono_type (MonoType *type)
556 switch (type->type) {
557 case MONO_TYPE_OBJECT:
558 return mono_defaults.object_class;
559 case MONO_TYPE_VOID:
560 return mono_defaults.void_class;
561 case MONO_TYPE_BOOLEAN:
562 return mono_defaults.boolean_class;
563 case MONO_TYPE_CHAR:
564 return mono_defaults.char_class;
565 case MONO_TYPE_I1:
566 return mono_defaults.sbyte_class;
567 case MONO_TYPE_U1:
568 return mono_defaults.byte_class;
569 case MONO_TYPE_I2:
570 return mono_defaults.int16_class;
571 case MONO_TYPE_U2:
572 return mono_defaults.uint16_class;
573 case MONO_TYPE_I4:
574 return mono_defaults.int32_class;
575 case MONO_TYPE_U4:
576 return mono_defaults.uint32_class;
577 case MONO_TYPE_I:
578 return mono_defaults.int_class;
579 case MONO_TYPE_U:
580 return mono_defaults.uint_class;
581 case MONO_TYPE_I8:
582 return mono_defaults.int64_class;
583 case MONO_TYPE_U8:
584 return mono_defaults.uint64_class;
585 case MONO_TYPE_R4:
586 return mono_defaults.single_class;
587 case MONO_TYPE_R8:
588 return mono_defaults.double_class;
589 case MONO_TYPE_STRING:
590 return mono_defaults.string_class;
591 default:
592 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
593 g_assert_not_reached ();
596 return NULL;
599 static void
600 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
602 int i;
603 MonoGenericInst *class_inst;
604 MonoClass *klass;
606 g_assert (gclass);
608 class_inst = gclass->context.class_inst;
610 sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
611 klass = gclass->container_class;
612 sigbuffer_add_value (buf, klass->byval_arg.type);
613 sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
615 sigbuffer_add_value (buf, class_inst->type_argc);
616 for (i = 0; i < class_inst->type_argc; ++i)
617 encode_type (assembly, class_inst->type_argv [i], buf);
621 static void
622 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
624 if (!type) {
625 g_assert_not_reached ();
626 return;
629 if (type->byref)
630 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
632 switch (type->type){
633 case MONO_TYPE_VOID:
634 case MONO_TYPE_BOOLEAN:
635 case MONO_TYPE_CHAR:
636 case MONO_TYPE_I1:
637 case MONO_TYPE_U1:
638 case MONO_TYPE_I2:
639 case MONO_TYPE_U2:
640 case MONO_TYPE_I4:
641 case MONO_TYPE_U4:
642 case MONO_TYPE_I8:
643 case MONO_TYPE_U8:
644 case MONO_TYPE_R4:
645 case MONO_TYPE_R8:
646 case MONO_TYPE_I:
647 case MONO_TYPE_U:
648 case MONO_TYPE_STRING:
649 case MONO_TYPE_OBJECT:
650 case MONO_TYPE_TYPEDBYREF:
651 sigbuffer_add_value (buf, type->type);
652 break;
653 case MONO_TYPE_PTR:
654 sigbuffer_add_value (buf, type->type);
655 encode_type (assembly, type->data.type, buf);
656 break;
657 case MONO_TYPE_SZARRAY:
658 sigbuffer_add_value (buf, type->type);
659 encode_type (assembly, &type->data.klass->byval_arg, buf);
660 break;
661 case MONO_TYPE_VALUETYPE:
662 case MONO_TYPE_CLASS: {
663 MonoClass *k = mono_class_from_mono_type (type);
665 if (k->generic_container) {
666 MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
667 encode_generic_class (assembly, gclass, buf);
668 } else {
670 * Make sure we use the correct type.
672 sigbuffer_add_value (buf, k->byval_arg.type);
674 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
675 * otherwise two typerefs could point to the same type, leading to
676 * verification errors.
678 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
680 break;
682 case MONO_TYPE_ARRAY:
683 sigbuffer_add_value (buf, type->type);
684 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
685 sigbuffer_add_value (buf, type->data.array->rank);
686 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
687 sigbuffer_add_value (buf, 0);
688 break;
689 case MONO_TYPE_GENERICINST:
690 encode_generic_class (assembly, type->data.generic_class, buf);
691 break;
692 case MONO_TYPE_VAR:
693 case MONO_TYPE_MVAR:
694 sigbuffer_add_value (buf, type->type);
695 sigbuffer_add_value (buf, type->data.generic_param->num);
696 break;
697 default:
698 g_error ("need to encode type %x", type->type);
702 static void
703 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
705 if (!type) {
706 sigbuffer_add_value (buf, MONO_TYPE_VOID);
707 return;
710 if (type->type ||
711 ((type = mono_reflection_type_get_underlying_system_type (type)) && type->type)) {
712 encode_type (assembly, type->type, buf);
713 return;
716 g_assert_not_reached ();
720 static void
721 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
723 int i;
725 if (modreq) {
726 for (i = 0; i < mono_array_length (modreq); ++i) {
727 MonoReflectionType *mod = mono_array_get (modreq, MonoReflectionType*, i);
728 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
729 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod->type));
732 if (modopt) {
733 for (i = 0; i < mono_array_length (modopt); ++i) {
734 MonoReflectionType *mod = mono_array_get (modopt, MonoReflectionType*, i);
735 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
736 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod->type));
741 static guint32
742 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
744 SigBuffer buf;
745 int i;
746 guint32 nparams = sig->param_count;
747 guint32 idx;
749 if (!assembly->save)
750 return 0;
752 sigbuffer_init (&buf, 32);
754 * FIXME: vararg, explicit_this, differenc call_conv values...
756 idx = sig->call_convention;
757 if (sig->hasthis)
758 idx |= 0x20; /* hasthis */
759 if (sig->generic_param_count)
760 idx |= 0x10; /* generic */
761 sigbuffer_add_byte (&buf, idx);
762 if (sig->generic_param_count)
763 sigbuffer_add_value (&buf, sig->generic_param_count);
764 sigbuffer_add_value (&buf, nparams);
765 encode_type (assembly, sig->ret, &buf);
766 for (i = 0; i < nparams; ++i) {
767 if (i == sig->sentinelpos)
768 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
769 encode_type (assembly, sig->params [i], &buf);
771 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
772 sigbuffer_free (&buf);
773 return idx;
776 static guint32
777 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
780 * FIXME: reuse code from method_encode_signature().
782 SigBuffer buf;
783 int i;
784 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
785 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
786 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
787 guint32 idx;
789 sigbuffer_init (&buf, 32);
790 /* LAMESPEC: all the call conv spec is foobared */
791 idx = mb->call_conv & 0x60; /* has-this, explicit-this */
792 if (mb->call_conv & 2)
793 idx |= 0x5; /* vararg */
794 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
795 idx |= 0x20; /* hasthis */
796 if (ngparams)
797 idx |= 0x10; /* generic */
798 sigbuffer_add_byte (&buf, idx);
799 if (ngparams)
800 sigbuffer_add_value (&buf, ngparams);
801 sigbuffer_add_value (&buf, nparams + notypes);
802 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
803 encode_reflection_type (assembly, mb->rtype, &buf);
804 for (i = 0; i < nparams; ++i) {
805 MonoArray *modreq = NULL;
806 MonoArray *modopt = NULL;
807 MonoReflectionType *pt;
809 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
810 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
811 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
812 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
813 encode_custom_modifiers (assembly, modreq, modopt, &buf);
814 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
815 encode_reflection_type (assembly, pt, &buf);
817 if (notypes)
818 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
819 for (i = 0; i < notypes; ++i) {
820 MonoReflectionType *pt;
822 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
823 encode_reflection_type (assembly, pt, &buf);
826 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
827 sigbuffer_free (&buf);
828 return idx;
831 static guint32
832 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
834 MonoDynamicTable *table;
835 guint32 *values;
836 guint32 idx, sig_idx;
837 guint nl = mono_array_length (ilgen->locals);
838 SigBuffer buf;
839 int i;
841 sigbuffer_init (&buf, 32);
842 sigbuffer_add_value (&buf, 0x07);
843 sigbuffer_add_value (&buf, nl);
844 for (i = 0; i < nl; ++i) {
845 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
847 if (lb->is_pinned)
848 sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
850 encode_reflection_type (assembly, lb->type, &buf);
852 sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
853 sigbuffer_free (&buf);
855 if (assembly->standalonesig_cache == NULL)
856 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
857 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
858 if (idx)
859 return idx;
861 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
862 idx = table->next_idx ++;
863 table->rows ++;
864 alloc_table (table, table->rows);
865 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
867 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
869 g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
871 return idx;
874 static guint32
875 method_count_clauses (MonoReflectionILGen *ilgen)
877 guint32 num_clauses = 0;
878 int i;
880 MonoILExceptionInfo *ex_info;
881 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
882 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
883 if (ex_info->handlers)
884 num_clauses += mono_array_length (ex_info->handlers);
885 else
886 num_clauses++;
889 return num_clauses;
892 static MonoExceptionClause*
893 method_encode_clauses (MonoMemPool *mp, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
895 MonoExceptionClause *clauses;
896 MonoExceptionClause *clause;
897 MonoILExceptionInfo *ex_info;
898 MonoILExceptionBlock *ex_block;
899 guint32 finally_start;
900 int i, j, clause_index;;
902 clauses = mp_g_new0 (mp, MonoExceptionClause, num_clauses);
904 clause_index = 0;
905 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
906 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
907 finally_start = ex_info->start + ex_info->len;
908 if (!ex_info->handlers)
909 continue;
910 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
911 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
912 clause = &(clauses [clause_index]);
914 clause->flags = ex_block->type;
915 clause->try_offset = ex_info->start;
917 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
918 clause->try_len = finally_start - ex_info->start;
919 else
920 clause->try_len = ex_info->len;
921 clause->handler_offset = ex_block->start;
922 clause->handler_len = ex_block->len;
923 if (ex_block->extype) {
924 clause->data.catch_class = mono_class_from_mono_type (ex_block->extype->type);
925 } else {
926 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
927 clause->data.filter_offset = ex_block->filter_offset;
928 else
929 clause->data.filter_offset = 0;
931 finally_start = ex_block->start + ex_block->len;
933 clause_index ++;
937 return clauses;
940 static guint32
941 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
943 char flags = 0;
944 guint32 idx;
945 guint32 code_size;
946 gint32 max_stack, i;
947 gint32 num_locals = 0;
948 gint32 num_exception = 0;
949 gint maybe_small;
950 guint32 fat_flags;
951 char fat_header [12];
952 guint32 int_value;
953 guint16 short_value;
954 guint32 local_sig = 0;
955 guint32 header_size = 12;
956 MonoArray *code;
958 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
959 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
960 return 0;
962 /*if (mb->name)
963 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
964 if (mb->ilgen) {
965 code = mb->ilgen->code;
966 code_size = mb->ilgen->code_len;
967 max_stack = mb->ilgen->max_stack;
968 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
969 if (mb->ilgen->ex_handlers)
970 num_exception = method_count_clauses (mb->ilgen);
971 } else {
972 code = mb->code;
973 if (code == NULL){
974 char *name = mono_string_to_utf8 (mb->name);
975 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
976 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
977 g_free (str);
978 g_free (name);
979 mono_raise_exception (exception);
982 code_size = mono_array_length (code);
983 max_stack = 8; /* we probably need to run a verifier on the code... */
986 stream_data_align (&assembly->code);
988 /* check for exceptions, maxstack, locals */
989 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
990 if (maybe_small) {
991 if (code_size < 64 && !(code_size & 1)) {
992 flags = (code_size << 2) | 0x2;
993 } else if (code_size < 32 && (code_size & 1)) {
994 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
995 } else {
996 goto fat_header;
998 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
999 /* add to the fixup todo list */
1000 if (mb->ilgen && mb->ilgen->num_token_fixups)
1001 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1002 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1003 return assembly->text_rva + idx;
1005 fat_header:
1006 if (num_locals)
1007 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
1009 * FIXME: need to set also the header size in fat_flags.
1010 * (and more sects and init locals flags)
1012 fat_flags = 0x03;
1013 if (num_exception)
1014 fat_flags |= METHOD_HEADER_MORE_SECTS;
1015 if (mb->init_locals)
1016 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1017 fat_header [0] = fat_flags;
1018 fat_header [1] = (header_size / 4 ) << 4;
1019 short_value = GUINT16_TO_LE (max_stack);
1020 memcpy (fat_header + 2, &short_value, 2);
1021 int_value = GUINT32_TO_LE (code_size);
1022 memcpy (fat_header + 4, &int_value, 4);
1023 int_value = GUINT32_TO_LE (local_sig);
1024 memcpy (fat_header + 8, &int_value, 4);
1025 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1026 /* add to the fixup todo list */
1027 if (mb->ilgen && mb->ilgen->num_token_fixups)
1028 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1030 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1031 if (num_exception) {
1032 unsigned char sheader [4];
1033 MonoILExceptionInfo * ex_info;
1034 MonoILExceptionBlock * ex_block;
1035 int j;
1037 stream_data_align (&assembly->code);
1038 /* always use fat format for now */
1039 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1040 num_exception *= 6 * sizeof (guint32);
1041 num_exception += 4; /* include the size of the header */
1042 sheader [1] = num_exception & 0xff;
1043 sheader [2] = (num_exception >> 8) & 0xff;
1044 sheader [3] = (num_exception >> 16) & 0xff;
1045 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1046 /* fat header, so we are already aligned */
1047 /* reverse order */
1048 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1049 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1050 if (ex_info->handlers) {
1051 int finally_start = ex_info->start + ex_info->len;
1052 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1053 guint32 val;
1054 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1055 /* the flags */
1056 val = GUINT32_TO_LE (ex_block->type);
1057 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1058 /* try offset */
1059 val = GUINT32_TO_LE (ex_info->start);
1060 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1061 /* need fault, too, probably */
1062 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1063 val = GUINT32_TO_LE (finally_start - ex_info->start);
1064 else
1065 val = GUINT32_TO_LE (ex_info->len);
1066 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1067 /* handler offset */
1068 val = GUINT32_TO_LE (ex_block->start);
1069 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1070 /* handler len */
1071 val = GUINT32_TO_LE (ex_block->len);
1072 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1073 finally_start = ex_block->start + ex_block->len;
1074 if (ex_block->extype) {
1075 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, ex_block->extype->type));
1076 } else {
1077 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1078 val = ex_block->filter_offset;
1079 else
1080 val = 0;
1082 val = GUINT32_TO_LE (val);
1083 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1084 /*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",
1085 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);*/
1087 } else {
1088 g_error ("No clauses for ex info block %d", i);
1092 return assembly->text_rva + idx;
1095 static guint32
1096 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1098 int i;
1099 MonoDynamicTable *table;
1100 guint32 *values;
1102 table = &assembly->tables [table_idx];
1104 g_assert (col < table->columns);
1106 values = table->values + table->columns;
1107 for (i = 1; i <= table->rows; ++i) {
1108 if (values [col] == token)
1109 return i;
1110 values += table->columns;
1112 return 0;
1116 * LOCKING: Acquires the loader lock.
1118 static MonoCustomAttrInfo*
1119 lookup_custom_attr (MonoImage *image, gpointer member)
1121 MonoCustomAttrInfo* res;
1123 mono_loader_lock ();
1124 res = mono_property_hash_lookup (image->property_hash, member, MONO_PROP_DYNAMIC_CATTR);
1125 mono_loader_unlock ();
1127 if (!res)
1128 return NULL;
1130 return g_memdup (res, sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (res->num_attrs - MONO_ZERO_LEN_ARRAY));
1133 static gboolean
1134 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1136 /* FIXME: Need to do more checks */
1137 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1138 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1140 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1141 return FALSE;
1144 return TRUE;
1147 static MonoCustomAttrInfo*
1148 mono_custom_attrs_from_builders (MonoMemPool *mp, MonoImage *image, MonoArray *cattrs)
1150 int i, index, count, not_visible;
1151 MonoCustomAttrInfo *ainfo;
1152 MonoReflectionCustomAttr *cattr;
1154 if (!cattrs)
1155 return NULL;
1156 /* FIXME: check in assembly the Run flag is set */
1158 count = mono_array_length (cattrs);
1160 /* Skip nonpublic attributes since MS.NET seems to do the same */
1161 /* FIXME: This needs to be done more globally */
1162 not_visible = 0;
1163 for (i = 0; i < count; ++i) {
1164 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1165 if (!custom_attr_visible (image, cattr))
1166 not_visible ++;
1168 count -= not_visible;
1170 ainfo = mp_g_malloc0 (mp, sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
1172 ainfo->image = image;
1173 ainfo->num_attrs = count;
1174 ainfo->cached = mp != NULL;
1175 index = 0;
1176 mono_loader_lock ();
1177 for (i = 0; i < count; ++i) {
1178 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1179 if (custom_attr_visible (image, cattr)) {
1180 unsigned char *saved = mono_image_alloc (image, mono_array_length (cattr->data));
1181 memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1182 ainfo->attrs [index].ctor = cattr->ctor->method;
1183 ainfo->attrs [index].data = saved;
1184 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1185 index ++;
1188 mono_loader_unlock ();
1190 return ainfo;
1194 * LOCKING: Acquires the loader lock.
1196 static void
1197 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1199 MonoCustomAttrInfo *ainfo, *tmp;
1201 if (!cattrs || !mono_array_length (cattrs))
1202 return;
1204 ainfo = mono_custom_attrs_from_builders (image->mempool, image, cattrs);
1205 mono_loader_lock ();
1206 tmp = mono_property_hash_lookup (image->property_hash, obj, MONO_PROP_DYNAMIC_CATTR);
1207 if (tmp)
1208 mono_custom_attrs_free (tmp);
1209 mono_property_hash_insert (image->property_hash, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1210 mono_loader_unlock ();
1213 void
1214 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1216 if (!ainfo->cached)
1217 g_free (ainfo);
1221 * idx is the table index of the object
1222 * type is one of MONO_CUSTOM_ATTR_*
1224 static void
1225 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1227 MonoDynamicTable *table;
1228 MonoReflectionCustomAttr *cattr;
1229 guint32 *values;
1230 guint32 count, i, token;
1231 char blob_size [6];
1232 char *p = blob_size;
1234 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1235 if (!cattrs)
1236 return;
1237 count = mono_array_length (cattrs);
1238 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1239 table->rows += count;
1240 alloc_table (table, table->rows);
1241 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1242 idx <<= MONO_CUSTOM_ATTR_BITS;
1243 idx |= type;
1244 for (i = 0; i < count; ++i) {
1245 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1246 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1247 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE);
1248 type = mono_metadata_token_index (token);
1249 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1250 switch (mono_metadata_token_table (token)) {
1251 case MONO_TABLE_METHOD:
1252 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1253 break;
1254 case MONO_TABLE_MEMBERREF:
1255 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1256 break;
1257 default:
1258 g_warning ("got wrong token in custom attr");
1259 continue;
1261 values [MONO_CUSTOM_ATTR_TYPE] = type;
1262 p = blob_size;
1263 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1264 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1265 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1266 values += MONO_CUSTOM_ATTR_SIZE;
1267 ++table->next_idx;
1271 static void
1272 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1274 MonoDynamicTable *table;
1275 guint32 *values;
1276 guint32 count, i, idx;
1277 MonoReflectionPermissionSet *perm;
1279 if (!permissions)
1280 return;
1282 count = mono_array_length (permissions);
1283 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1284 table->rows += count;
1285 alloc_table (table, table->rows);
1287 for (i = 0; i < mono_array_length (permissions); ++i) {
1288 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1290 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1292 idx = mono_metadata_token_index (parent_token);
1293 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1294 switch (mono_metadata_token_table (parent_token)) {
1295 case MONO_TABLE_TYPEDEF:
1296 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1297 break;
1298 case MONO_TABLE_METHOD:
1299 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1300 break;
1301 case MONO_TABLE_ASSEMBLY:
1302 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1303 break;
1304 default:
1305 g_assert_not_reached ();
1308 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1309 values [MONO_DECL_SECURITY_PARENT] = idx;
1310 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1312 ++table->next_idx;
1317 * Fill in the MethodDef and ParamDef tables for a method.
1318 * This is used for both normal methods and constructors.
1320 static void
1321 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1323 MonoDynamicTable *table;
1324 guint32 *values;
1325 guint i, count;
1327 /* room in this table is already allocated */
1328 table = &assembly->tables [MONO_TABLE_METHOD];
1329 *mb->table_idx = table->next_idx ++;
1330 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1331 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1332 values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1333 values [MONO_METHOD_FLAGS] = mb->attrs;
1334 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1335 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1336 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1338 table = &assembly->tables [MONO_TABLE_PARAM];
1339 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1341 mono_image_add_decl_security (assembly,
1342 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1344 if (mb->pinfo) {
1345 MonoDynamicTable *mtable;
1346 guint32 *mvalues;
1348 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1349 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1351 count = 0;
1352 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1353 if (mono_array_get (mb->pinfo, gpointer, i))
1354 count++;
1356 table->rows += count;
1357 alloc_table (table, table->rows);
1358 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1359 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1360 MonoReflectionParamBuilder *pb;
1361 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1362 values [MONO_PARAM_FLAGS] = pb->attrs;
1363 values [MONO_PARAM_SEQUENCE] = i;
1364 if (pb->name != NULL) {
1365 values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1366 } else {
1367 values [MONO_PARAM_NAME] = 0;
1369 values += MONO_PARAM_SIZE;
1370 if (pb->marshal_info) {
1371 mtable->rows++;
1372 alloc_table (mtable, mtable->rows);
1373 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1374 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1375 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1377 pb->table_idx = table->next_idx++;
1378 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1379 guint32 field_type = 0;
1380 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1381 mtable->rows ++;
1382 alloc_table (mtable, mtable->rows);
1383 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1384 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1385 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1386 mvalues [MONO_CONSTANT_TYPE] = field_type;
1387 mvalues [MONO_CONSTANT_PADDING] = 0;
1394 static void
1395 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1397 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1399 rmb->ilgen = mb->ilgen;
1400 rmb->rtype = mb->rtype;
1401 rmb->parameters = mb->parameters;
1402 rmb->generic_params = mb->generic_params;
1403 rmb->generic_container = mb->generic_container;
1404 rmb->opt_types = NULL;
1405 rmb->pinfo = mb->pinfo;
1406 rmb->attrs = mb->attrs;
1407 rmb->iattrs = mb->iattrs;
1408 rmb->call_conv = mb->call_conv;
1409 rmb->code = mb->code;
1410 rmb->type = mb->type;
1411 rmb->name = mb->name;
1412 rmb->table_idx = &mb->table_idx;
1413 rmb->init_locals = mb->init_locals;
1414 rmb->skip_visibility = FALSE;
1415 rmb->return_modreq = mb->return_modreq;
1416 rmb->return_modopt = mb->return_modopt;
1417 rmb->param_modreq = mb->param_modreq;
1418 rmb->param_modopt = mb->param_modopt;
1419 rmb->permissions = mb->permissions;
1420 rmb->mhandle = mb->mhandle;
1421 rmb->nrefs = 0;
1422 rmb->refs = NULL;
1424 if (mb->dll) {
1425 rmb->charset = mb->charset;
1426 rmb->extra_flags = mb->extra_flags;
1427 rmb->native_cc = mb->native_cc;
1428 rmb->dllentry = mb->dllentry;
1429 rmb->dll = mb->dll;
1433 static void
1434 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1436 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1438 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1440 rmb->ilgen = mb->ilgen;
1441 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1442 rmb->parameters = mb->parameters;
1443 rmb->generic_params = NULL;
1444 rmb->generic_container = NULL;
1445 rmb->opt_types = NULL;
1446 rmb->pinfo = mb->pinfo;
1447 rmb->attrs = mb->attrs;
1448 rmb->iattrs = mb->iattrs;
1449 rmb->call_conv = mb->call_conv;
1450 rmb->code = NULL;
1451 rmb->type = mb->type;
1452 rmb->name = mono_string_new (mono_domain_get (), name);
1453 rmb->table_idx = &mb->table_idx;
1454 rmb->init_locals = mb->init_locals;
1455 rmb->skip_visibility = FALSE;
1456 rmb->return_modreq = NULL;
1457 rmb->return_modopt = NULL;
1458 rmb->param_modreq = mb->param_modreq;
1459 rmb->param_modopt = mb->param_modopt;
1460 rmb->permissions = mb->permissions;
1461 rmb->mhandle = mb->mhandle;
1462 rmb->nrefs = 0;
1463 rmb->refs = NULL;
1466 static void
1467 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1469 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1471 rmb->ilgen = mb->ilgen;
1472 rmb->rtype = mb->rtype;
1473 rmb->parameters = mb->parameters;
1474 rmb->generic_params = NULL;
1475 rmb->generic_container = NULL;
1476 rmb->opt_types = NULL;
1477 rmb->pinfo = NULL;
1478 rmb->attrs = mb->attrs;
1479 rmb->iattrs = 0;
1480 rmb->call_conv = mb->call_conv;
1481 rmb->code = NULL;
1482 rmb->type = (MonoObject *) mb->owner;
1483 rmb->name = mb->name;
1484 rmb->table_idx = NULL;
1485 rmb->init_locals = mb->init_locals;
1486 rmb->skip_visibility = mb->skip_visibility;
1487 rmb->return_modreq = NULL;
1488 rmb->return_modopt = NULL;
1489 rmb->param_modreq = NULL;
1490 rmb->param_modopt = NULL;
1491 rmb->permissions = NULL;
1492 rmb->mhandle = mb->mhandle;
1493 rmb->nrefs = 0;
1494 rmb->refs = NULL;
1497 static void
1498 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1500 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1501 MonoDynamicTable *table;
1502 guint32 *values;
1503 guint32 tok;
1505 if (!mb->override_method)
1506 return;
1508 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1509 table->rows ++;
1510 alloc_table (table, table->rows);
1511 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1512 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1513 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1515 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE, FALSE);
1516 switch (mono_metadata_token_table (tok)) {
1517 case MONO_TABLE_MEMBERREF:
1518 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1519 break;
1520 case MONO_TABLE_METHOD:
1521 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1522 break;
1523 default:
1524 g_assert_not_reached ();
1526 values [MONO_METHODIMPL_DECLARATION] = tok;
1529 static void
1530 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1532 MonoDynamicTable *table;
1533 guint32 *values;
1534 ReflectionMethodBuilder rmb;
1535 int i;
1537 reflection_methodbuilder_from_method_builder (&rmb, mb);
1539 mono_image_basic_method (&rmb, assembly);
1540 mb->table_idx = *rmb.table_idx;
1542 if (mb->dll) { /* It's a P/Invoke method */
1543 guint32 moduleref;
1544 /* map CharSet values to on-disk values */
1545 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1546 int extra_flags = mb->extra_flags;
1547 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1548 table->rows ++;
1549 alloc_table (table, table->rows);
1550 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1552 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1553 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1554 if (mb->dllentry)
1555 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1556 else
1557 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1558 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1559 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1560 table = &assembly->tables [MONO_TABLE_MODULEREF];
1561 table->rows ++;
1562 alloc_table (table, table->rows);
1563 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1564 values [MONO_IMPLMAP_SCOPE] = table->rows;
1568 if (mb->generic_params) {
1569 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1570 table->rows += mono_array_length (mb->generic_params);
1571 alloc_table (table, table->rows);
1572 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1573 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1575 mono_image_get_generic_param_info (
1576 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1582 static void
1583 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1585 ReflectionMethodBuilder rmb;
1587 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1589 mono_image_basic_method (&rmb, assembly);
1590 mb->table_idx = *rmb.table_idx;
1593 static char*
1594 type_get_fully_qualified_name (MonoType *type)
1596 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1599 static char*
1600 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1601 MonoClass *klass;
1602 MonoAssembly *ta;
1604 klass = my_mono_class_from_mono_type (type);
1605 if (!klass)
1606 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1607 ta = klass->image->assembly;
1608 if (ta->dynamic || (ta == ass)) {
1609 if (klass->generic_class || klass->generic_container)
1610 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1611 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1612 else
1613 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1616 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1619 static guint32
1620 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
1622 SigBuffer buf;
1623 guint32 idx, i;
1625 if (!assembly->save)
1626 return 0;
1628 sigbuffer_init (&buf, 32);
1630 sigbuffer_add_value (&buf, 0x06);
1631 /* encode custom attributes before the type */
1632 /* FIXME: This should probably go in encode_type () */
1633 if (type->num_mods) {
1634 for (i = 0; i < type->num_mods; ++i) {
1635 if (type->modifiers [i].required)
1636 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1637 else
1638 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1639 sigbuffer_add_value (&buf, type->modifiers [i].token);
1642 encode_type (assembly, type, &buf);
1643 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1644 sigbuffer_free (&buf);
1645 return idx;
1648 static guint32
1649 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1651 SigBuffer buf;
1652 guint32 idx;
1654 sigbuffer_init (&buf, 32);
1656 sigbuffer_add_value (&buf, 0x06);
1657 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1658 /* encode custom attributes before the type */
1659 encode_reflection_type (assembly, fb->type, &buf);
1660 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1661 sigbuffer_free (&buf);
1662 return idx;
1665 static guint32
1666 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1667 char blob_size [64];
1668 char *b = blob_size;
1669 char *p, *box_val;
1670 char* buf;
1671 guint32 idx = 0, len = 0, dummy = 0;
1672 #ifdef ARM_FPU_FPA
1673 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1674 guint32 fpa_double [2];
1675 guint32 *fpa_p;
1676 #endif
1677 #endif
1679 p = buf = g_malloc (64);
1680 if (!val) {
1681 *ret_type = MONO_TYPE_CLASS;
1682 len = 4;
1683 box_val = (char*)&dummy;
1684 } else {
1685 box_val = ((char*)val) + sizeof (MonoObject);
1686 *ret_type = val->vtable->klass->byval_arg.type;
1688 handle_enum:
1689 switch (*ret_type) {
1690 case MONO_TYPE_BOOLEAN:
1691 case MONO_TYPE_U1:
1692 case MONO_TYPE_I1:
1693 len = 1;
1694 break;
1695 case MONO_TYPE_CHAR:
1696 case MONO_TYPE_U2:
1697 case MONO_TYPE_I2:
1698 len = 2;
1699 break;
1700 case MONO_TYPE_U4:
1701 case MONO_TYPE_I4:
1702 case MONO_TYPE_R4:
1703 len = 4;
1704 break;
1705 case MONO_TYPE_U8:
1706 case MONO_TYPE_I8:
1707 len = 8;
1708 break;
1709 case MONO_TYPE_R8:
1710 len = 8;
1711 #ifdef ARM_FPU_FPA
1712 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1713 fpa_p = (guint32*)box_val;
1714 fpa_double [0] = fpa_p [1];
1715 fpa_double [1] = fpa_p [0];
1716 box_val = (char*)fpa_double;
1717 #endif
1718 #endif
1719 break;
1720 case MONO_TYPE_VALUETYPE:
1721 if (val->vtable->klass->enumtype) {
1722 *ret_type = val->vtable->klass->enum_basetype->type;
1723 goto handle_enum;
1724 } else
1725 g_error ("we can't encode valuetypes");
1726 case MONO_TYPE_CLASS:
1727 break;
1728 case MONO_TYPE_STRING: {
1729 MonoString *str = (MonoString*)val;
1730 /* there is no signature */
1731 len = str->length * 2;
1732 mono_metadata_encode_value (len, b, &b);
1733 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1735 char *swapped = g_malloc (2 * mono_string_length (str));
1736 const char *p = (const char*)mono_string_chars (str);
1738 swap_with_size (swapped, p, 2, mono_string_length (str));
1739 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1740 g_free (swapped);
1742 #else
1743 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1744 #endif
1746 g_free (buf);
1747 return idx;
1749 case MONO_TYPE_GENERICINST:
1750 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
1751 goto handle_enum;
1752 default:
1753 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1756 /* there is no signature */
1757 mono_metadata_encode_value (len, b, &b);
1758 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1759 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1760 swap_with_size (blob_size, box_val, len, 1);
1761 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1762 #else
1763 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1764 #endif
1766 g_free (buf);
1767 return idx;
1770 static guint32
1771 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1772 char *str;
1773 SigBuffer buf;
1774 guint32 idx, len;
1776 sigbuffer_init (&buf, 32);
1778 sigbuffer_add_value (&buf, minfo->type);
1780 switch (minfo->type) {
1781 case MONO_NATIVE_BYVALTSTR:
1782 case MONO_NATIVE_BYVALARRAY:
1783 sigbuffer_add_value (&buf, minfo->count);
1784 break;
1785 case MONO_NATIVE_LPARRAY:
1786 if (minfo->eltype || minfo->has_size) {
1787 sigbuffer_add_value (&buf, minfo->eltype);
1788 if (minfo->has_size) {
1789 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
1790 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
1792 /* LAMESPEC: ElemMult is undocumented */
1793 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1796 break;
1797 case MONO_NATIVE_CUSTOM:
1798 if (minfo->guid) {
1799 str = mono_string_to_utf8 (minfo->guid);
1800 len = strlen (str);
1801 sigbuffer_add_value (&buf, len);
1802 sigbuffer_add_mem (&buf, str, len);
1803 g_free (str);
1804 } else {
1805 sigbuffer_add_value (&buf, 0);
1807 /* native type name */
1808 sigbuffer_add_value (&buf, 0);
1809 /* custom marshaler type name */
1810 if (minfo->marshaltype || minfo->marshaltyperef) {
1811 if (minfo->marshaltyperef)
1812 str = type_get_fully_qualified_name (minfo->marshaltyperef->type);
1813 else
1814 str = mono_string_to_utf8 (minfo->marshaltype);
1815 len = strlen (str);
1816 sigbuffer_add_value (&buf, len);
1817 sigbuffer_add_mem (&buf, str, len);
1818 g_free (str);
1819 } else {
1820 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
1821 sigbuffer_add_value (&buf, 0);
1823 if (minfo->mcookie) {
1824 str = mono_string_to_utf8 (minfo->mcookie);
1825 len = strlen (str);
1826 sigbuffer_add_value (&buf, len);
1827 sigbuffer_add_mem (&buf, str, len);
1828 g_free (str);
1829 } else {
1830 sigbuffer_add_value (&buf, 0);
1832 break;
1833 default:
1834 break;
1836 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1837 sigbuffer_free (&buf);
1838 return idx;
1841 static void
1842 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1844 MonoDynamicTable *table;
1845 guint32 *values;
1847 /* maybe this fixup should be done in the C# code */
1848 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1849 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1850 table = &assembly->tables [MONO_TABLE_FIELD];
1851 fb->table_idx = table->next_idx ++;
1852 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1853 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1854 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
1855 values [MONO_FIELD_FLAGS] = fb->attrs;
1856 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1858 if (fb->offset != -1) {
1859 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1860 table->rows ++;
1861 alloc_table (table, table->rows);
1862 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1863 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1864 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1866 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1867 guint32 field_type = 0;
1868 table = &assembly->tables [MONO_TABLE_CONSTANT];
1869 table->rows ++;
1870 alloc_table (table, table->rows);
1871 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1872 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1873 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1874 values [MONO_CONSTANT_TYPE] = field_type;
1875 values [MONO_CONSTANT_PADDING] = 0;
1877 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1878 guint32 rva_idx;
1879 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1880 table->rows ++;
1881 alloc_table (table, table->rows);
1882 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1883 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1885 * We store it in the code section because it's simpler for now.
1887 if (fb->rva_data) {
1888 if (mono_array_length (fb->rva_data) >= 10)
1889 stream_data_align (&assembly->code);
1890 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1891 } else
1892 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1893 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1895 if (fb->marshal_info) {
1896 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1897 table->rows ++;
1898 alloc_table (table, table->rows);
1899 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1900 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1901 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1905 static guint32
1906 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1908 SigBuffer buf;
1909 guint32 nparams = 0;
1910 MonoReflectionMethodBuilder *mb = fb->get_method;
1911 MonoReflectionMethodBuilder *smb = fb->set_method;
1912 guint32 idx, i;
1914 if (mb && mb->parameters)
1915 nparams = mono_array_length (mb->parameters);
1916 if (!mb && smb && smb->parameters)
1917 nparams = mono_array_length (smb->parameters) - 1;
1918 sigbuffer_init (&buf, 32);
1919 sigbuffer_add_byte (&buf, 0x08);
1920 sigbuffer_add_value (&buf, nparams);
1921 if (mb) {
1922 encode_reflection_type (assembly, mb->rtype, &buf);
1923 for (i = 0; i < nparams; ++i) {
1924 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1925 encode_reflection_type (assembly, pt, &buf);
1927 } else if (smb && smb->parameters) {
1928 /* the property type is the last param */
1929 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
1930 for (i = 0; i < nparams; ++i) {
1931 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1932 encode_reflection_type (assembly, pt, &buf);
1934 } else {
1935 encode_reflection_type (assembly, fb->type, &buf);
1938 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1939 sigbuffer_free (&buf);
1940 return idx;
1943 static void
1944 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1946 MonoDynamicTable *table;
1947 guint32 *values;
1948 guint num_methods = 0;
1949 guint32 semaidx;
1952 * we need to set things in the following tables:
1953 * PROPERTYMAP (info already filled in _get_type_info ())
1954 * PROPERTY (rows already preallocated in _get_type_info ())
1955 * METHOD (method info already done with the generic method code)
1956 * METHODSEMANTICS
1958 table = &assembly->tables [MONO_TABLE_PROPERTY];
1959 pb->table_idx = table->next_idx ++;
1960 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1961 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1962 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1963 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1965 /* FIXME: we still don't handle 'other' methods */
1966 if (pb->get_method) num_methods ++;
1967 if (pb->set_method) num_methods ++;
1969 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1970 table->rows += num_methods;
1971 alloc_table (table, table->rows);
1973 if (pb->get_method) {
1974 semaidx = table->next_idx ++;
1975 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1976 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1977 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1978 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1980 if (pb->set_method) {
1981 semaidx = table->next_idx ++;
1982 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1983 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1984 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1985 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1989 static void
1990 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1992 MonoDynamicTable *table;
1993 guint32 *values;
1994 guint num_methods = 0;
1995 guint32 semaidx;
1998 * we need to set things in the following tables:
1999 * EVENTMAP (info already filled in _get_type_info ())
2000 * EVENT (rows already preallocated in _get_type_info ())
2001 * METHOD (method info already done with the generic method code)
2002 * METHODSEMANTICS
2004 table = &assembly->tables [MONO_TABLE_EVENT];
2005 eb->table_idx = table->next_idx ++;
2006 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2007 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2008 values [MONO_EVENT_FLAGS] = eb->attrs;
2009 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
2012 * FIXME: we still don't handle 'other' methods
2014 if (eb->add_method) num_methods ++;
2015 if (eb->remove_method) num_methods ++;
2016 if (eb->raise_method) num_methods ++;
2018 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2019 table->rows += num_methods;
2020 alloc_table (table, table->rows);
2022 if (eb->add_method) {
2023 semaidx = table->next_idx ++;
2024 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2025 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2026 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2027 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2029 if (eb->remove_method) {
2030 semaidx = table->next_idx ++;
2031 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2032 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2033 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2034 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2036 if (eb->raise_method) {
2037 semaidx = table->next_idx ++;
2038 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2039 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2040 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2041 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2045 static void
2046 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2048 MonoDynamicTable *table;
2049 guint32 num_constraints, i;
2050 guint32 *values;
2051 guint32 table_idx;
2053 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2054 num_constraints = gparam->iface_constraints ?
2055 mono_array_length (gparam->iface_constraints) : 0;
2056 table->rows += num_constraints;
2057 if (gparam->base_type)
2058 table->rows++;
2059 alloc_table (table, table->rows);
2061 if (gparam->base_type) {
2062 table_idx = table->next_idx ++;
2063 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2065 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2066 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2067 assembly, gparam->base_type->type);
2070 for (i = 0; i < num_constraints; i++) {
2071 MonoReflectionType *constraint = mono_array_get (
2072 gparam->iface_constraints, gpointer, i);
2074 table_idx = table->next_idx ++;
2075 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2077 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2078 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2079 assembly, constraint->type);
2083 static void
2084 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2086 GenericParamTableEntry *entry;
2089 * The GenericParam table must be sorted according to the `owner' field.
2090 * We need to do this sorting prior to writing the GenericParamConstraint
2091 * table, since we have to use the final GenericParam table indices there
2092 * and they must also be sorted.
2095 entry = g_new0 (GenericParamTableEntry, 1);
2096 entry->owner = owner;
2097 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2098 MOVING_GC_REGISTER (&entry->gparam);
2099 entry->gparam = gparam;
2101 g_ptr_array_add (assembly->gen_params, entry);
2104 static void
2105 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2107 MonoDynamicTable *table;
2108 MonoGenericParam *param;
2109 guint32 *values;
2110 guint32 table_idx;
2112 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2113 table_idx = table->next_idx ++;
2114 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2116 param = entry->gparam->type.type->data.generic_param;
2118 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2119 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2120 values [MONO_GENERICPARAM_NUMBER] = param->num;
2121 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
2123 mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2125 encode_constraints (entry->gparam, table_idx, assembly);
2128 static guint32
2129 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2131 MonoDynamicTable *table;
2132 guint32 token;
2133 guint32 *values;
2134 guint32 cols [MONO_ASSEMBLY_SIZE];
2135 const char *pubkey;
2136 guint32 publen;
2138 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2139 return token;
2141 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2142 table = &assembly->tables [MONO_TABLE_MODULEREF];
2143 token = table->next_idx ++;
2144 table->rows ++;
2145 alloc_table (table, table->rows);
2146 values = table->values + token * MONO_MODULEREF_SIZE;
2147 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2149 token <<= MONO_RESOLTION_SCOPE_BITS;
2150 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2151 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2153 return token;
2156 if (image->assembly->dynamic)
2157 /* FIXME: */
2158 memset (cols, 0, sizeof (cols));
2159 else {
2160 /* image->assembly->image is the manifest module */
2161 image = image->assembly->image;
2162 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2165 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2166 token = table->next_idx ++;
2167 table->rows ++;
2168 alloc_table (table, table->rows);
2169 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2170 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2171 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2172 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2173 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2174 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2175 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2176 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2177 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2179 if (strcmp ("", image->assembly->aname.culture)) {
2180 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2181 image->assembly->aname.culture);
2184 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2185 guchar pubtoken [9];
2186 pubtoken [0] = 8;
2187 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2188 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2189 } else {
2190 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2192 token <<= MONO_RESOLTION_SCOPE_BITS;
2193 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2194 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2195 return token;
2198 static guint32
2199 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2201 MonoDynamicTable *table;
2202 guint32 *values;
2203 guint32 token;
2204 SigBuffer buf;
2206 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2207 return token;
2209 sigbuffer_init (&buf, 32);
2210 switch (type->type) {
2211 case MONO_TYPE_FNPTR:
2212 case MONO_TYPE_PTR:
2213 case MONO_TYPE_SZARRAY:
2214 case MONO_TYPE_ARRAY:
2215 case MONO_TYPE_VAR:
2216 case MONO_TYPE_MVAR:
2217 case MONO_TYPE_GENERICINST:
2218 encode_type (assembly, type, &buf);
2219 break;
2220 case MONO_TYPE_CLASS:
2221 case MONO_TYPE_VALUETYPE: {
2222 MonoClass *k = mono_class_from_mono_type (type);
2223 if (!k || !k->generic_container) {
2224 sigbuffer_free (&buf);
2225 return 0;
2227 encode_type (assembly, type, &buf);
2228 break;
2230 default:
2231 sigbuffer_free (&buf);
2232 return 0;
2235 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2236 if (assembly->save) {
2237 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2238 alloc_table (table, table->rows + 1);
2239 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2240 values [MONO_TYPESPEC_SIGNATURE] = token;
2242 sigbuffer_free (&buf);
2244 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2245 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2246 table->next_idx ++;
2247 return token;
2250 static guint32
2251 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2253 MonoDynamicTable *table;
2254 guint32 *values;
2255 guint32 token, scope, enclosing;
2256 MonoClass *klass;
2258 /* if the type requires a typespec, we must try that first*/
2259 if (try_typespec && (token = create_typespec (assembly, type)))
2260 return token;
2261 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2262 if (token)
2263 return token;
2264 klass = my_mono_class_from_mono_type (type);
2265 if (!klass)
2266 klass = mono_class_from_mono_type (type);
2269 * If it's in the same module and not a generic type parameter:
2271 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2272 (type->type != MONO_TYPE_MVAR)) {
2273 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2274 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2275 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2276 return token;
2279 if (klass->nested_in) {
2280 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2281 /* get the typeref idx of the enclosing type */
2282 enclosing >>= MONO_TYPEDEFORREF_BITS;
2283 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2284 } else {
2285 scope = resolution_scope_from_image (assembly, klass->image);
2287 table = &assembly->tables [MONO_TABLE_TYPEREF];
2288 if (assembly->save) {
2289 alloc_table (table, table->rows + 1);
2290 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2291 values [MONO_TYPEREF_SCOPE] = scope;
2292 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2293 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2295 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2296 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2297 table->next_idx ++;
2298 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2299 return token;
2303 * Despite the name, we handle also TypeSpec (with the above helper).
2305 static guint32
2306 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2308 return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2312 * Insert a memberef row into the metadata: the token that point to the memberref
2313 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2314 * mono_image_get_fieldref_token()).
2315 * The sig param is an index to an already built signature.
2317 static guint32
2318 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2320 MonoDynamicTable *table;
2321 guint32 *values;
2322 guint32 token, pclass;
2323 guint32 parent;
2325 parent = mono_image_typedef_or_ref (assembly, type);
2326 switch (parent & MONO_TYPEDEFORREF_MASK) {
2327 case MONO_TYPEDEFORREF_TYPEREF:
2328 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2329 break;
2330 case MONO_TYPEDEFORREF_TYPESPEC:
2331 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2332 break;
2333 case MONO_TYPEDEFORREF_TYPEDEF:
2334 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2335 break;
2336 default:
2337 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2338 return 0;
2340 /* extract the index */
2341 parent >>= MONO_TYPEDEFORREF_BITS;
2343 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2345 if (assembly->save) {
2346 alloc_table (table, table->rows + 1);
2347 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2348 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2349 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2350 values [MONO_MEMBERREF_SIGNATURE] = sig;
2353 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2354 table->next_idx ++;
2356 return token;
2359 static guint32
2360 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2362 guint32 token;
2363 MonoMethodSignature *sig;
2365 create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2367 if (create_typespec) {
2368 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2369 if (token)
2370 return token;
2373 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2374 if (token && !create_typespec)
2375 return token;
2377 g_assert (!method->is_inflated);
2378 if (!token) {
2380 * A methodref signature can't contain an unmanaged calling convention.
2382 sig = mono_metadata_signature_dup (mono_method_signature (method));
2383 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2384 sig->call_convention = MONO_CALL_DEFAULT;
2385 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2386 method->name, method_encode_signature (assembly, sig));
2387 g_free (sig);
2388 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2391 if (create_typespec) {
2392 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2393 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2394 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2396 if (assembly->save) {
2397 guint32 *values;
2399 alloc_table (table, table->rows + 1);
2400 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2401 values [MONO_METHODSPEC_METHOD] = token;
2402 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2405 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2406 table->next_idx ++;
2407 /*methodspec and memberef tokens are diferent, */
2408 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2409 return token;
2411 return token;
2414 static guint32
2415 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2417 guint32 token;
2418 ReflectionMethodBuilder rmb;
2419 char *name;
2421 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2422 if (token)
2423 return token;
2425 name = mono_string_to_utf8 (method->name);
2426 reflection_methodbuilder_from_method_builder (&rmb, method);
2429 * A methodref signature can't contain an unmanaged calling convention.
2430 * Since some flags are encoded as part of call_conv, we need to check against it.
2432 if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2433 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2434 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2435 name, method_builder_encode_signature (assembly, &rmb));
2437 g_free (name);
2438 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2439 return token;
2442 static guint32
2443 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2444 const gchar *name, guint32 sig)
2446 MonoDynamicTable *table;
2447 guint32 token;
2448 guint32 *values;
2450 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2452 if (assembly->save) {
2453 alloc_table (table, table->rows + 1);
2454 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2455 values [MONO_MEMBERREF_CLASS] = original;
2456 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2457 values [MONO_MEMBERREF_SIGNATURE] = sig;
2460 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2461 table->next_idx ++;
2463 return token;
2466 static guint32
2467 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2469 SigBuffer buf;
2470 int i;
2471 guint32 nparams = mono_array_length (mb->generic_params);
2472 guint32 idx;
2474 if (!assembly->save)
2475 return 0;
2477 sigbuffer_init (&buf, 32);
2479 sigbuffer_add_value (&buf, 0xa);
2480 sigbuffer_add_value (&buf, nparams);
2482 for (i = 0; i < nparams; i++) {
2483 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2484 sigbuffer_add_value (&buf, i);
2487 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2488 sigbuffer_free (&buf);
2489 return idx;
2492 static guint32
2493 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2495 MonoDynamicTable *table;
2496 guint32 *values;
2497 guint32 token, mtoken = 0;
2499 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2500 if (token)
2501 return token;
2503 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2505 mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2506 switch (mono_metadata_token_table (mtoken)) {
2507 case MONO_TABLE_MEMBERREF:
2508 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2509 break;
2510 case MONO_TABLE_METHOD:
2511 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2512 break;
2513 default:
2514 g_assert_not_reached ();
2517 if (assembly->save) {
2518 alloc_table (table, table->rows + 1);
2519 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2520 values [MONO_METHODSPEC_METHOD] = mtoken;
2521 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2524 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2525 table->next_idx ++;
2527 mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2528 return token;
2531 static guint32
2532 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2534 guint32 token;
2536 if (mb->generic_params && create_methodspec)
2537 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2539 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2540 if (token)
2541 return token;
2543 token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2544 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2545 return token;
2548 static guint32
2549 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2551 guint32 token;
2552 ReflectionMethodBuilder rmb;
2553 char *name;
2555 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2556 if (token)
2557 return token;
2559 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2561 name = mono_string_to_utf8 (rmb.name);
2562 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2563 name, method_builder_encode_signature (assembly, &rmb));
2565 g_free (name);
2566 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2567 return token;
2570 static gboolean
2571 is_field_on_inst (MonoClassField *field)
2573 return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2577 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2579 static MonoType*
2580 get_field_on_inst_generic_type (MonoClassField *field)
2582 MonoDynamicGenericClass *dgclass;
2583 int field_index;
2585 g_assert (is_field_on_inst (field));
2587 dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2588 field_index = field - dgclass->fields;
2590 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
2591 return dgclass->field_generic_types [field_index];
2594 static guint32
2595 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2597 MonoType *type;
2598 guint32 token;
2599 MonoClassField *field;
2601 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2602 if (token)
2603 return token;
2604 g_assert (f->field->parent);
2606 field = f->field;
2607 if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2608 int index = field - field->parent->fields;
2609 type = field->parent->generic_class->container_class->fields [index].type;
2610 } else {
2611 if (is_field_on_inst (f->field))
2612 type = get_field_on_inst_generic_type (f->field);
2613 else
2614 type = f->field->type;
2616 token = mono_image_get_memberref_token (assembly, &f->field->parent->byval_arg,
2617 mono_field_get_name (f->field),
2618 fieldref_encode_signature (assembly, type));
2619 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2620 return token;
2623 static guint32
2624 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
2626 guint32 token;
2627 MonoClass *klass;
2628 MonoGenericClass *gclass;
2629 MonoDynamicGenericClass *dgclass;
2630 MonoReflectionFieldBuilder *fb = f->fb;
2631 char *name;
2633 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2634 if (token)
2635 return token;
2636 klass = mono_class_from_mono_type (f->inst->type.type);
2637 gclass = f->inst->type.type->data.generic_class;
2638 g_assert (gclass->is_dynamic);
2639 dgclass = (MonoDynamicGenericClass *) gclass;
2641 name = mono_string_to_utf8 (fb->name);
2642 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name,
2643 field_encode_signature (assembly, fb));
2644 g_free (name);
2645 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER (token));
2646 return token;
2649 static guint32
2650 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
2652 guint32 sig, token;
2653 MonoClass *klass;
2654 MonoGenericClass *gclass;
2655 MonoDynamicGenericClass *dgclass;
2656 MonoReflectionCtorBuilder *cb = c->cb;
2657 ReflectionMethodBuilder rmb;
2658 char *name;
2660 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
2662 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, c));
2663 if (token)
2664 return token;
2665 klass = mono_class_from_mono_type (c->inst->type.type);
2666 gclass = c->inst->type.type->data.generic_class;
2667 g_assert (gclass->is_dynamic);
2668 dgclass = (MonoDynamicGenericClass *) gclass;
2670 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
2672 name = mono_string_to_utf8 (rmb.name);
2674 sig = method_builder_encode_signature (assembly, &rmb);
2676 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2677 g_free (name);
2679 g_hash_table_insert (assembly->handleref, c, GUINT_TO_POINTER (token));
2680 return token;
2683 static guint32
2684 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
2686 guint32 sig, token;
2687 MonoClass *klass;
2688 MonoGenericClass *gclass;
2689 MonoReflectionMethodBuilder *mb = m->mb;
2690 ReflectionMethodBuilder rmb;
2691 char *name;
2693 if (create_methodspec && mb->generic_params)
2694 // FIXME:
2695 g_assert_not_reached ();
2697 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
2698 if (token)
2699 return token;
2700 klass = mono_class_from_mono_type (m->inst->type.type);
2701 gclass = m->inst->type.type->data.generic_class;
2702 g_assert (gclass->is_dynamic);
2704 reflection_methodbuilder_from_method_builder (&rmb, mb);
2706 name = mono_string_to_utf8 (rmb.name);
2708 sig = method_builder_encode_signature (assembly, &rmb);
2710 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2711 g_free (name);
2713 g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER (token));
2714 return token;
2717 static guint32
2718 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
2720 SigBuffer buf;
2721 int i;
2722 guint32 nparams = context->method_inst->type_argc;
2723 guint32 idx;
2725 if (!assembly->save)
2726 return 0;
2728 sigbuffer_init (&buf, 32);
2730 * FIXME: vararg, explicit_this, differenc call_conv values...
2732 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
2733 sigbuffer_add_value (&buf, nparams);
2735 for (i = 0; i < nparams; i++)
2736 encode_type (assembly, context->method_inst->type_argv [i], &buf);
2738 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2739 sigbuffer_free (&buf);
2740 return idx;
2743 static guint32
2744 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2746 MonoDynamicTable *table;
2747 guint32 *values;
2748 guint32 token, mtoken = 0, sig;
2749 MonoMethodInflated *imethod;
2750 MonoMethod *declaring;
2752 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2754 g_assert (method->is_inflated);
2755 imethod = (MonoMethodInflated *) method;
2756 declaring = imethod->declaring;
2758 sig = method_encode_signature (assembly, mono_method_signature (declaring));
2759 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2761 if (!mono_method_signature (declaring)->generic_param_count)
2762 return mtoken;
2764 switch (mono_metadata_token_table (mtoken)) {
2765 case MONO_TABLE_MEMBERREF:
2766 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2767 break;
2768 case MONO_TABLE_METHOD:
2769 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2770 break;
2771 default:
2772 g_assert_not_reached ();
2775 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
2777 if (assembly->save) {
2778 alloc_table (table, table->rows + 1);
2779 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2780 values [MONO_METHODSPEC_METHOD] = mtoken;
2781 values [MONO_METHODSPEC_SIGNATURE] = sig;
2784 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2785 table->next_idx ++;
2787 return token;
2790 static guint32
2791 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
2793 MonoMethodInflated *imethod;
2794 guint32 token;
2796 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2797 if (token)
2798 return token;
2800 g_assert (method->is_inflated);
2801 imethod = (MonoMethodInflated *) method;
2803 if (mono_method_signature (imethod->declaring)->generic_param_count) {
2804 token = method_encode_methodspec (assembly, method);
2805 } else {
2806 guint32 sig = method_encode_signature (
2807 assembly, mono_method_signature (imethod->declaring));
2808 token = mono_image_get_memberref_token (
2809 assembly, &method->klass->byval_arg, method->name, sig);
2812 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2813 return token;
2816 static guint32
2817 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
2819 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
2820 guint32 sig, token;
2822 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
2823 token = mono_image_get_memberref_token (
2824 assembly, &m->klass->byval_arg, m->name, sig);
2826 return token;
2829 static guint32
2830 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2832 MonoDynamicTable *table;
2833 MonoClass *klass;
2834 guint32 *values;
2835 guint32 token;
2836 SigBuffer buf;
2837 int count, i;
2840 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2841 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2842 * Because of this, we must not insert it into the `typeref' hash table.
2845 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2846 if (token)
2847 return token;
2849 sigbuffer_init (&buf, 32);
2851 g_assert (tb->generic_params);
2852 klass = mono_class_from_mono_type (tb->type.type);
2854 if (tb->generic_container)
2855 mono_reflection_create_generic_class (tb);
2857 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
2858 g_assert (klass->generic_container);
2859 sigbuffer_add_value (&buf, klass->byval_arg.type);
2860 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
2862 count = mono_array_length (tb->generic_params);
2863 sigbuffer_add_value (&buf, count);
2864 for (i = 0; i < count; i++) {
2865 MonoReflectionGenericParam *gparam;
2867 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2869 encode_type (assembly, gparam->type.type, &buf);
2872 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2874 if (assembly->save) {
2875 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2876 alloc_table (table, table->rows + 1);
2877 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2878 values [MONO_TYPESPEC_SIGNATURE] = token;
2880 sigbuffer_free (&buf);
2882 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2883 g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2884 table->next_idx ++;
2885 return token;
2889 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
2891 static MonoType*
2892 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
2894 int i, count, len, pos;
2895 MonoType *t;
2897 count = 0;
2898 if (modreq)
2899 count += mono_array_length (modreq);
2900 if (modopt)
2901 count += mono_array_length (modopt);
2903 if (count == 0)
2904 return mono_metadata_type_dup (NULL, type);
2906 len = sizeof (MonoType) + ((gint32)count - MONO_ZERO_LEN_ARRAY) * sizeof (MonoCustomMod);
2907 t = g_malloc (len);
2908 memcpy (t, type, len);
2910 t->num_mods = count;
2911 pos = 0;
2912 if (modreq) {
2913 for (i = 0; i < mono_array_length (modreq); ++i) {
2914 MonoReflectionType *mod = mono_array_get (modreq, MonoReflectionType*, i);
2915 t->modifiers [pos].required = 1;
2916 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod->type);
2917 pos ++;
2920 if (modopt) {
2921 for (i = 0; i < mono_array_length (modopt); ++i) {
2922 MonoReflectionType *mod = mono_array_get (modopt, MonoReflectionType*, i);
2923 t->modifiers [pos].required = 0;
2924 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod->type);
2925 pos ++;
2929 return t;
2932 static guint32
2933 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2935 MonoDynamicTable *table;
2936 MonoClass *klass;
2937 MonoType *custom = NULL;
2938 guint32 *values;
2939 guint32 token, pclass, parent, sig;
2940 gchar *name;
2942 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2943 if (token)
2944 return token;
2946 klass = mono_class_from_mono_type (fb->typeb->type);
2947 name = mono_string_to_utf8 (fb->name);
2949 /* fb->type does not include the custom modifiers */
2950 /* FIXME: We should do this in one place when a fieldbuilder is created */
2951 if (fb->modreq || fb->modopt) {
2952 custom = add_custom_modifiers (assembly, fb->type->type, fb->modreq, fb->modopt);
2953 sig = fieldref_encode_signature (assembly, custom);
2954 g_free (custom);
2955 } else {
2956 sig = fieldref_encode_signature (assembly, fb->type->type);
2959 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2960 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
2962 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2963 parent >>= MONO_TYPEDEFORREF_BITS;
2965 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2967 if (assembly->save) {
2968 alloc_table (table, table->rows + 1);
2969 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2970 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2971 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2972 values [MONO_MEMBERREF_SIGNATURE] = sig;
2975 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2976 table->next_idx ++;
2977 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2978 g_free (name);
2979 return token;
2982 static guint32
2983 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2985 SigBuffer buf;
2986 guint32 nargs;
2987 guint32 size;
2988 guint32 i, idx;
2990 if (!assembly->save)
2991 return 0;
2993 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
2994 g_assert (helper->type == 2);
2996 if (helper->arguments)
2997 nargs = mono_array_length (helper->arguments);
2998 else
2999 nargs = 0;
3001 size = 10 + (nargs * 10);
3003 sigbuffer_init (&buf, 32);
3005 /* Encode calling convention */
3006 /* Change Any to Standard */
3007 if ((helper->call_conv & 0x03) == 0x03)
3008 helper->call_conv = 0x01;
3009 /* explicit_this implies has_this */
3010 if (helper->call_conv & 0x40)
3011 helper->call_conv &= 0x20;
3013 if (helper->call_conv == 0) { /* Unmanaged */
3014 idx = helper->unmanaged_call_conv - 1;
3015 } else {
3016 /* Managed */
3017 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3018 if (helper->call_conv & 0x02) /* varargs */
3019 idx += 0x05;
3022 sigbuffer_add_byte (&buf, idx);
3023 sigbuffer_add_value (&buf, nargs);
3024 encode_reflection_type (assembly, helper->return_type, &buf);
3025 for (i = 0; i < nargs; ++i) {
3026 MonoArray *modreqs = NULL;
3027 MonoArray *modopts = NULL;
3028 MonoReflectionType *pt;
3030 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3031 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3032 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3033 modopts = mono_array_get (helper->modopts, MonoArray*, i);
3035 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3036 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3037 encode_reflection_type (assembly, pt, &buf);
3039 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3040 sigbuffer_free (&buf);
3042 return idx;
3045 static guint32
3046 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3048 guint32 idx;
3049 MonoDynamicTable *table;
3050 guint32 *values;
3052 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3053 idx = table->next_idx ++;
3054 table->rows ++;
3055 alloc_table (table, table->rows);
3056 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3058 values [MONO_STAND_ALONE_SIGNATURE] =
3059 mono_reflection_encode_sighelper (assembly, helper);
3061 return idx;
3064 static int
3065 reflection_cc_to_file (int call_conv) {
3066 switch (call_conv & 0x3) {
3067 case 0:
3068 case 1: return MONO_CALL_DEFAULT;
3069 case 2: return MONO_CALL_VARARG;
3070 default:
3071 g_assert_not_reached ();
3073 return 0;
3076 typedef struct {
3077 MonoType *parent;
3078 MonoMethodSignature *sig;
3079 char *name;
3080 guint32 token;
3081 } ArrayMethod;
3083 static guint32
3084 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3086 guint32 nparams, i;
3087 GList *tmp;
3088 char *name;
3089 MonoMethodSignature *sig;
3090 ArrayMethod *am;
3092 name = mono_string_to_utf8 (m->name);
3093 nparams = mono_array_length (m->parameters);
3094 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
3095 sig->hasthis = 1;
3096 sig->sentinelpos = -1;
3097 sig->call_convention = reflection_cc_to_file (m->call_conv);
3098 sig->param_count = nparams;
3099 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
3100 for (i = 0; i < nparams; ++i) {
3101 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
3102 sig->params [i] = t->type;
3105 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3106 am = tmp->data;
3107 if (strcmp (name, am->name) == 0 &&
3108 mono_metadata_type_equal (am->parent, m->parent->type) &&
3109 mono_metadata_signature_equal (am->sig, sig)) {
3110 g_free (name);
3111 g_free (sig);
3112 m->table_idx = am->token & 0xffffff;
3113 return am->token;
3116 am = g_new0 (ArrayMethod, 1);
3117 am->name = name;
3118 am->sig = sig;
3119 am->parent = m->parent->type;
3120 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3121 method_encode_signature (assembly, sig));
3122 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3123 m->table_idx = am->token & 0xffffff;
3124 return am->token;
3128 * Insert into the metadata tables all the info about the TypeBuilder tb.
3129 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3131 static void
3132 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3134 MonoDynamicTable *table;
3135 guint *values;
3136 int i, is_object = 0, is_system = 0;
3137 char *n;
3139 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3140 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3141 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3142 n = mono_string_to_utf8 (tb->name);
3143 if (strcmp (n, "Object") == 0)
3144 is_object++;
3145 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3146 g_free (n);
3147 n = mono_string_to_utf8 (tb->nspace);
3148 if (strcmp (n, "System") == 0)
3149 is_system++;
3150 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3151 g_free (n);
3152 if (tb->parent && !(is_system && is_object) &&
3153 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3154 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
3155 } else {
3156 values [MONO_TYPEDEF_EXTENDS] = 0;
3158 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3159 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3162 * if we have explicitlayout or sequentiallayouts, output data in the
3163 * ClassLayout table.
3165 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3166 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3167 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3168 table->rows++;
3169 alloc_table (table, table->rows);
3170 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3171 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3172 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3173 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3176 /* handle interfaces */
3177 if (tb->interfaces) {
3178 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3179 i = table->rows;
3180 table->rows += mono_array_length (tb->interfaces);
3181 alloc_table (table, table->rows);
3182 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3183 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3184 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3185 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3186 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
3187 values += MONO_INTERFACEIMPL_SIZE;
3191 /* handle fields */
3192 if (tb->fields) {
3193 table = &assembly->tables [MONO_TABLE_FIELD];
3194 table->rows += tb->num_fields;
3195 alloc_table (table, table->rows);
3196 for (i = 0; i < tb->num_fields; ++i)
3197 mono_image_get_field_info (
3198 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3201 /* handle constructors */
3202 if (tb->ctors) {
3203 table = &assembly->tables [MONO_TABLE_METHOD];
3204 table->rows += mono_array_length (tb->ctors);
3205 alloc_table (table, table->rows);
3206 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3207 mono_image_get_ctor_info (domain,
3208 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3211 /* handle methods */
3212 if (tb->methods) {
3213 table = &assembly->tables [MONO_TABLE_METHOD];
3214 table->rows += tb->num_methods;
3215 alloc_table (table, table->rows);
3216 for (i = 0; i < tb->num_methods; ++i)
3217 mono_image_get_method_info (
3218 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3221 /* Do the same with properties etc.. */
3222 if (tb->events && mono_array_length (tb->events)) {
3223 table = &assembly->tables [MONO_TABLE_EVENT];
3224 table->rows += mono_array_length (tb->events);
3225 alloc_table (table, table->rows);
3226 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3227 table->rows ++;
3228 alloc_table (table, table->rows);
3229 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3230 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3231 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3232 for (i = 0; i < mono_array_length (tb->events); ++i)
3233 mono_image_get_event_info (
3234 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3236 if (tb->properties && mono_array_length (tb->properties)) {
3237 table = &assembly->tables [MONO_TABLE_PROPERTY];
3238 table->rows += mono_array_length (tb->properties);
3239 alloc_table (table, table->rows);
3240 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3241 table->rows ++;
3242 alloc_table (table, table->rows);
3243 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3244 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3245 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3246 for (i = 0; i < mono_array_length (tb->properties); ++i)
3247 mono_image_get_property_info (
3248 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3251 /* handle generic parameters */
3252 if (tb->generic_params) {
3253 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3254 table->rows += mono_array_length (tb->generic_params);
3255 alloc_table (table, table->rows);
3256 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3257 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3259 mono_image_get_generic_param_info (
3260 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3264 mono_image_add_decl_security (assembly,
3265 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3267 if (tb->subtypes) {
3268 MonoDynamicTable *ntable;
3270 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3271 ntable->rows += mono_array_length (tb->subtypes);
3272 alloc_table (ntable, ntable->rows);
3273 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3275 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3276 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3278 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3279 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3280 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3281 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3282 mono_string_to_utf8 (tb->name), tb->table_idx,
3283 ntable->next_idx, ntable->rows);*/
3284 values += MONO_NESTED_CLASS_SIZE;
3285 ntable->next_idx++;
3290 static void
3291 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
3293 int i;
3295 g_ptr_array_add (types, type); /* FIXME: GC object added to unmanaged memory */
3297 if (!type->subtypes)
3298 return;
3300 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3301 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3302 collect_types (types, subtype);
3306 static gint
3307 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3309 if ((*type1)->table_idx < (*type2)->table_idx)
3310 return -1;
3311 else
3312 if ((*type1)->table_idx > (*type2)->table_idx)
3313 return 1;
3314 else
3315 return 0;
3318 static void
3319 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3320 int i;
3322 if (!pinfo)
3323 return;
3324 for (i = 0; i < mono_array_length (pinfo); ++i) {
3325 MonoReflectionParamBuilder *pb;
3326 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3327 if (!pb)
3328 continue;
3329 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3333 static void
3334 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3335 int i;
3337 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3338 if (tb->fields) {
3339 for (i = 0; i < tb->num_fields; ++i) {
3340 MonoReflectionFieldBuilder* fb;
3341 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3342 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3345 if (tb->events) {
3346 for (i = 0; i < mono_array_length (tb->events); ++i) {
3347 MonoReflectionEventBuilder* eb;
3348 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3349 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3352 if (tb->properties) {
3353 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3354 MonoReflectionPropertyBuilder* pb;
3355 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3356 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3359 if (tb->ctors) {
3360 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3361 MonoReflectionCtorBuilder* cb;
3362 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3363 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3364 params_add_cattrs (assembly, cb->pinfo);
3368 if (tb->methods) {
3369 for (i = 0; i < tb->num_methods; ++i) {
3370 MonoReflectionMethodBuilder* mb;
3371 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3372 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3373 params_add_cattrs (assembly, mb->pinfo);
3377 if (tb->subtypes) {
3378 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3379 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3383 static void
3384 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3386 int i;
3388 mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3390 if (moduleb->global_methods) {
3391 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3392 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3393 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3394 params_add_cattrs (assembly, mb->pinfo);
3398 if (moduleb->global_fields) {
3399 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3400 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3401 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3405 if (moduleb->types) {
3406 for (i = 0; i < moduleb->num_types; ++i)
3407 type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3411 static void
3412 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3414 MonoDynamicTable *table;
3415 guint32 *values;
3416 char blob_size [6];
3417 guchar hash [20];
3418 char *b = blob_size;
3419 char *dir, *path;
3421 table = &assembly->tables [MONO_TABLE_FILE];
3422 table->rows++;
3423 alloc_table (table, table->rows);
3424 values = table->values + table->next_idx * MONO_FILE_SIZE;
3425 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3426 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3427 if (module->image->dynamic) {
3428 /* This depends on the fact that the main module is emitted last */
3429 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3430 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3431 } else {
3432 dir = NULL;
3433 path = g_strdup (module->image->name);
3435 mono_sha1_get_digest_from_file (path, hash);
3436 g_free (dir);
3437 g_free (path);
3438 mono_metadata_encode_value (20, b, &b);
3439 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3440 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3441 table->next_idx ++;
3444 static void
3445 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3447 MonoDynamicTable *table;
3448 int i;
3450 table = &assembly->tables [MONO_TABLE_MODULE];
3451 mb->table_idx = table->next_idx ++;
3452 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3453 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3454 i /= 16;
3455 ++i;
3456 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3457 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3458 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3459 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3462 static guint32
3463 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3464 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3466 MonoDynamicTable *table;
3467 guint32 *values;
3468 guint32 visib, res;
3470 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3471 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3472 return 0;
3474 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3475 table->rows++;
3476 alloc_table (table, table->rows);
3477 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3479 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3480 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3481 if (klass->nested_in)
3482 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3483 else
3484 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3485 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3486 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3488 res = table->next_idx;
3490 table->next_idx ++;
3492 /* Emit nested types */
3493 if (klass->nested_classes) {
3494 GList *tmp;
3496 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
3497 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3500 return res;
3503 static void
3504 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3505 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3507 MonoClass *klass;
3508 guint32 idx, i;
3510 klass = mono_class_from_mono_type (tb->type.type);
3512 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3514 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3515 parent_index, assembly);
3518 * Emit nested types
3519 * We need to do this ourselves since klass->nested_classes is not set up.
3521 if (tb->subtypes) {
3522 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3523 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3527 static void
3528 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3529 guint32 module_index, MonoDynamicImage *assembly)
3531 MonoImage *image = module->image;
3532 MonoTableInfo *t;
3533 guint32 i;
3535 t = &image->tables [MONO_TABLE_TYPEDEF];
3537 for (i = 0; i < t->rows; ++i) {
3538 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3540 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3541 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3545 static void
3546 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3548 MonoDynamicTable *table;
3549 MonoClass *klass;
3550 guint32 *values;
3551 guint32 scope, idx;
3552 int i;
3554 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3556 if (assemblyb->type_forwarders) {
3557 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3558 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType*, i);
3559 if (!t)
3560 continue;
3562 g_assert (t->type);
3564 klass = mono_class_from_mono_type (t->type);
3566 scope = resolution_scope_from_image (assembly, klass->image);
3567 g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3568 idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3570 table->rows++;
3571 alloc_table (table, table->rows);
3572 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3574 values [MONO_EXP_TYPE_FLAGS] = TYPE_ATTRIBUTE_FORWARDER;
3575 values [MONO_EXP_TYPE_TYPEDEF] = 0;
3576 values [MONO_EXP_TYPE_IMPLEMENTATION] = (idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3577 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3578 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3580 table->next_idx++;
3585 #define align_pointer(base,p)\
3586 do {\
3587 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3588 if (__diff & 3)\
3589 (p) += 4 - (__diff & 3);\
3590 } while (0)
3592 static int
3593 compare_constants (const void *a, const void *b)
3595 const guint32 *a_values = a;
3596 const guint32 *b_values = b;
3597 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3600 static int
3601 compare_semantics (const void *a, const void *b)
3603 const guint32 *a_values = a;
3604 const guint32 *b_values = b;
3605 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3606 if (assoc)
3607 return assoc;
3608 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3611 static int
3612 compare_custom_attrs (const void *a, const void *b)
3614 const guint32 *a_values = a;
3615 const guint32 *b_values = b;
3617 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3620 static int
3621 compare_field_marshal (const void *a, const void *b)
3623 const guint32 *a_values = a;
3624 const guint32 *b_values = b;
3626 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3629 static int
3630 compare_nested (const void *a, const void *b)
3632 const guint32 *a_values = a;
3633 const guint32 *b_values = b;
3635 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3638 static int
3639 compare_genericparam (const void *a, const void *b)
3641 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3642 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3644 if ((*b_entry)->owner == (*a_entry)->owner)
3645 return
3646 (*a_entry)->gparam->type.type->data.generic_param->num -
3647 (*b_entry)->gparam->type.type->data.generic_param->num;
3648 else
3649 return (*a_entry)->owner - (*b_entry)->owner;
3652 static int
3653 compare_declsecurity_attrs (const void *a, const void *b)
3655 const guint32 *a_values = a;
3656 const guint32 *b_values = b;
3658 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3661 static int
3662 compare_interface_impl (const void *a, const void *b)
3664 const guint32 *a_values = a;
3665 const guint32 *b_values = b;
3667 int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
3668 if (klass)
3669 return klass;
3671 return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
3674 static void
3675 pad_heap (MonoDynamicStream *sh)
3677 if (sh->index & 3) {
3678 int sz = 4 - (sh->index & 3);
3679 memset (sh->data + sh->index, 0, sz);
3680 sh->index += sz;
3684 struct StreamDesc {
3685 const char *name;
3686 MonoDynamicStream *stream;
3690 * build_compressed_metadata() fills in the blob of data that represents the
3691 * raw metadata as it will be saved in the PE file. The five streams are output
3692 * and the metadata tables are comnpressed from the guint32 array representation,
3693 * to the compressed on-disk format.
3695 static void
3696 build_compressed_metadata (MonoDynamicImage *assembly)
3698 MonoDynamicTable *table;
3699 int i;
3700 guint64 valid_mask = 0;
3701 guint64 sorted_mask;
3702 guint32 heapt_size = 0;
3703 guint32 meta_size = 256; /* allow for header and other stuff */
3704 guint32 table_offset;
3705 guint32 ntables = 0;
3706 guint64 *int64val;
3707 guint32 *int32val;
3708 guint16 *int16val;
3709 MonoImage *meta;
3710 unsigned char *p;
3711 struct StreamDesc stream_desc [5];
3713 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3714 for (i = 0; i < assembly->gen_params->len; i++){
3715 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3716 write_generic_param_entry (assembly, entry);
3719 stream_desc [0].name = "#~";
3720 stream_desc [0].stream = &assembly->tstream;
3721 stream_desc [1].name = "#Strings";
3722 stream_desc [1].stream = &assembly->sheap;
3723 stream_desc [2].name = "#US";
3724 stream_desc [2].stream = &assembly->us;
3725 stream_desc [3].name = "#Blob";
3726 stream_desc [3].stream = &assembly->blob;
3727 stream_desc [4].name = "#GUID";
3728 stream_desc [4].stream = &assembly->guid;
3730 /* tables that are sorted */
3731 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3732 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3733 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3734 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3735 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3736 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
3737 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
3739 /* Compute table sizes */
3740 /* the MonoImage has already been created in mono_image_basic_init() */
3741 meta = &assembly->image;
3743 /* sizes should be multiple of 4 */
3744 pad_heap (&assembly->blob);
3745 pad_heap (&assembly->guid);
3746 pad_heap (&assembly->sheap);
3747 pad_heap (&assembly->us);
3749 /* Setup the info used by compute_sizes () */
3750 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3751 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3752 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3754 meta_size += assembly->blob.index;
3755 meta_size += assembly->guid.index;
3756 meta_size += assembly->sheap.index;
3757 meta_size += assembly->us.index;
3759 for (i=0; i < MONO_TABLE_NUM; ++i)
3760 meta->tables [i].rows = assembly->tables [i].rows;
3762 for (i = 0; i < MONO_TABLE_NUM; i++){
3763 if (meta->tables [i].rows == 0)
3764 continue;
3765 valid_mask |= (guint64)1 << i;
3766 ntables ++;
3767 meta->tables [i].row_size = mono_metadata_compute_size (
3768 meta, i, &meta->tables [i].size_bitfield);
3769 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3771 heapt_size += 24; /* #~ header size */
3772 heapt_size += ntables * 4;
3773 /* make multiple of 4 */
3774 heapt_size += 3;
3775 heapt_size &= ~3;
3776 meta_size += heapt_size;
3777 meta->raw_metadata = g_malloc0 (meta_size);
3778 p = (unsigned char*)meta->raw_metadata;
3779 /* the metadata signature */
3780 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3781 /* version numbers and 4 bytes reserved */
3782 int16val = (guint16*)p;
3783 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
3784 *int16val = GUINT16_TO_LE (meta->md_version_minor);
3785 p += 8;
3786 /* version string */
3787 int32val = (guint32*)p;
3788 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3789 p += 4;
3790 memcpy (p, meta->version, strlen (meta->version));
3791 p += GUINT32_FROM_LE (*int32val);
3792 align_pointer (meta->raw_metadata, p);
3793 int16val = (guint16*)p;
3794 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3795 *int16val = GUINT16_TO_LE (5); /* number of streams */
3796 p += 4;
3799 * write the stream info.
3801 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3802 table_offset += 3; table_offset &= ~3;
3804 assembly->tstream.index = heapt_size;
3805 for (i = 0; i < 5; ++i) {
3806 int32val = (guint32*)p;
3807 stream_desc [i].stream->offset = table_offset;
3808 *int32val++ = GUINT32_TO_LE (table_offset);
3809 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3810 table_offset += GUINT32_FROM_LE (*int32val);
3811 table_offset += 3; table_offset &= ~3;
3812 p += 8;
3813 strcpy ((char*)p, stream_desc [i].name);
3814 p += strlen (stream_desc [i].name) + 1;
3815 align_pointer (meta->raw_metadata, p);
3818 * now copy the data, the table stream header and contents goes first.
3820 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3821 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
3822 int32val = (guint32*)p;
3823 *int32val = GUINT32_TO_LE (0); /* reserved */
3824 p += 4;
3826 if (mono_framework_version () > 1) {
3827 *p++ = 2; /* version */
3828 *p++ = 0;
3829 } else {
3830 *p++ = 1; /* version */
3831 *p++ = 0;
3834 if (meta->idx_string_wide)
3835 *p |= 0x01;
3836 if (meta->idx_guid_wide)
3837 *p |= 0x02;
3838 if (meta->idx_blob_wide)
3839 *p |= 0x04;
3840 ++p;
3841 *p++ = 1; /* reserved */
3842 int64val = (guint64*)p;
3843 *int64val++ = GUINT64_TO_LE (valid_mask);
3844 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3845 p += 16;
3846 int32val = (guint32*)p;
3847 for (i = 0; i < MONO_TABLE_NUM; i++){
3848 if (meta->tables [i].rows == 0)
3849 continue;
3850 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3852 p = (unsigned char*)int32val;
3854 /* sort the tables that still need sorting */
3855 table = &assembly->tables [MONO_TABLE_CONSTANT];
3856 if (table->rows)
3857 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
3858 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3859 if (table->rows)
3860 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3861 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3862 if (table->rows)
3863 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3864 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3865 if (table->rows)
3866 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3867 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3868 if (table->rows)
3869 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3870 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3871 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
3872 if (table->rows)
3873 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
3874 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3875 if (table->rows)
3876 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
3878 /* compress the tables */
3879 for (i = 0; i < MONO_TABLE_NUM; i++){
3880 int row, col;
3881 guint32 *values;
3882 guint32 bitfield = meta->tables [i].size_bitfield;
3883 if (!meta->tables [i].rows)
3884 continue;
3885 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3886 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3887 meta->tables [i].base = (char*)p;
3888 for (row = 1; row <= meta->tables [i].rows; ++row) {
3889 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3890 for (col = 0; col < assembly->tables [i].columns; ++col) {
3891 switch (mono_metadata_table_size (bitfield, col)) {
3892 case 1:
3893 *p++ = values [col];
3894 break;
3895 case 2:
3896 *p++ = values [col] & 0xff;
3897 *p++ = (values [col] >> 8) & 0xff;
3898 break;
3899 case 4:
3900 *p++ = values [col] & 0xff;
3901 *p++ = (values [col] >> 8) & 0xff;
3902 *p++ = (values [col] >> 16) & 0xff;
3903 *p++ = (values [col] >> 24) & 0xff;
3904 break;
3905 default:
3906 g_assert_not_reached ();
3910 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3913 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3914 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3915 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3916 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3917 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3919 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3923 * Some tables in metadata need to be sorted according to some criteria, but
3924 * when methods and fields are first created with reflection, they may be assigned a token
3925 * that doesn't correspond to the final token they will get assigned after the sorting.
3926 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3927 * with the reflection objects that represent them. Once all the tables are set up, the
3928 * reflection objects will contains the correct table index. fixup_method() will fixup the
3929 * tokens for the method with ILGenerator @ilgen.
3931 static void
3932 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
3934 guint32 code_idx = GPOINTER_TO_UINT (value);
3935 MonoReflectionILTokenInfo *iltoken;
3936 MonoReflectionFieldBuilder *field;
3937 MonoReflectionCtorBuilder *ctor;
3938 MonoReflectionMethodBuilder *method;
3939 MonoReflectionTypeBuilder *tb;
3940 MonoReflectionArrayMethod *am;
3941 guint32 i, idx = 0;
3942 unsigned char *target;
3944 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3945 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3946 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
3947 switch (target [3]) {
3948 case MONO_TABLE_FIELD:
3949 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3950 field = (MonoReflectionFieldBuilder *)iltoken->member;
3951 idx = field->table_idx;
3952 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3953 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3954 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
3955 } else {
3956 g_assert_not_reached ();
3958 break;
3959 case MONO_TABLE_METHOD:
3960 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3961 method = (MonoReflectionMethodBuilder *)iltoken->member;
3962 idx = method->table_idx;
3963 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3964 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3965 idx = ctor->table_idx;
3966 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3967 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3968 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3969 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3970 } else {
3971 g_assert_not_reached ();
3973 break;
3974 case MONO_TABLE_TYPEDEF:
3975 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3976 g_assert_not_reached ();
3977 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3978 idx = tb->table_idx;
3979 break;
3980 case MONO_TABLE_MEMBERREF:
3981 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3982 am = (MonoReflectionArrayMethod*)iltoken->member;
3983 idx = am->table_idx;
3984 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3985 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
3986 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
3987 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
3988 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3989 g_assert (m->klass->generic_class || m->klass->generic_container);
3990 continue;
3991 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3992 continue;
3993 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3994 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3995 g_assert (is_field_on_inst (f));
3996 continue;
3997 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
3998 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3999 continue;
4000 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4001 continue;
4002 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4003 continue;
4004 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4005 continue;
4006 } else {
4007 g_assert_not_reached ();
4009 break;
4010 case MONO_TABLE_METHODSPEC:
4011 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4012 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4013 g_assert (mono_method_signature (m)->generic_param_count);
4014 continue;
4015 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4016 continue;
4017 } else {
4018 g_assert_not_reached ();
4020 break;
4021 default:
4022 g_error ("got unexpected table 0x%02x in fixup", target [3]);
4024 target [0] = idx & 0xff;
4025 target [1] = (idx >> 8) & 0xff;
4026 target [2] = (idx >> 16) & 0xff;
4031 * fixup_cattrs:
4033 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4034 * value is not known when the table is emitted.
4036 static void
4037 fixup_cattrs (MonoDynamicImage *assembly)
4039 MonoDynamicTable *table;
4040 guint32 *values;
4041 guint32 type, i, idx, token;
4042 MonoObject *ctor;
4044 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4046 for (i = 0; i < table->rows; ++i) {
4047 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4049 type = values [MONO_CUSTOM_ATTR_TYPE];
4050 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4051 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4052 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4053 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4054 g_assert (ctor);
4056 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4057 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4058 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4059 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4065 static void
4066 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4068 MonoDynamicTable *table;
4069 guint32 *values;
4071 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4072 table->rows++;
4073 alloc_table (table, table->rows);
4074 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4075 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4076 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4077 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4078 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4079 table->next_idx++;
4082 static void
4083 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4085 MonoDynamicTable *table;
4086 guint32 *values;
4087 char blob_size [6];
4088 guchar hash [20];
4089 char *b = blob_size;
4090 char *name, *sname;
4091 guint32 idx, offset;
4093 if (rsrc->filename) {
4094 name = mono_string_to_utf8 (rsrc->filename);
4095 sname = g_path_get_basename (name);
4097 table = &assembly->tables [MONO_TABLE_FILE];
4098 table->rows++;
4099 alloc_table (table, table->rows);
4100 values = table->values + table->next_idx * MONO_FILE_SIZE;
4101 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4102 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4103 g_free (sname);
4105 mono_sha1_get_digest_from_file (name, hash);
4106 mono_metadata_encode_value (20, b, &b);
4107 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4108 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4109 g_free (name);
4110 idx = table->next_idx++;
4111 rsrc->offset = 0;
4112 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4113 } else {
4114 char sizebuf [4];
4115 char *data;
4116 guint len;
4117 if (rsrc->data) {
4118 data = mono_array_addr (rsrc->data, char, 0);
4119 len = mono_array_length (rsrc->data);
4120 } else {
4121 data = NULL;
4122 len = 0;
4124 offset = len;
4125 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4126 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4127 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4128 mono_image_add_stream_data (&assembly->resources, data, len);
4130 if (!mb->is_main)
4132 * The entry should be emitted into the MANIFESTRESOURCE table of
4133 * the main module, but that needs to reference the FILE table
4134 * which isn't emitted yet.
4136 return;
4137 else
4138 idx = 0;
4141 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4144 static void
4145 set_version_from_string (MonoString *version, guint32 *values)
4147 gchar *ver, *p, *str;
4148 guint32 i;
4150 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4151 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4152 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4153 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4154 if (!version)
4155 return;
4156 ver = str = mono_string_to_utf8 (version);
4157 for (i = 0; i < 4; ++i) {
4158 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4159 switch (*p) {
4160 case '.':
4161 p++;
4162 break;
4163 case '*':
4164 /* handle Revision and Build */
4165 p++;
4166 break;
4168 ver = p;
4170 g_free (str);
4173 static guint32
4174 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4175 gsize len;
4176 guint32 token = 0;
4177 char blob_size [6];
4178 char *b = blob_size;
4180 if (!pkey)
4181 return token;
4183 len = mono_array_length (pkey);
4184 mono_metadata_encode_value (len, b, &b);
4185 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4186 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4188 assembly->public_key = g_malloc (len);
4189 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4190 assembly->public_key_len = len;
4192 /* Special case: check for ECMA key (16 bytes) */
4193 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4194 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4195 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4196 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4197 /* minimum key size (in 2.0) is 384 bits */
4198 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4199 } else {
4200 /* FIXME - verifier */
4201 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4202 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4204 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
4206 return token;
4209 static void
4210 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4212 MonoDynamicTable *table;
4213 MonoDynamicImage *assembly;
4214 MonoReflectionAssemblyBuilder *assemblyb;
4215 MonoDomain *domain;
4216 guint32 *values;
4217 int i;
4218 guint32 module_index;
4220 assemblyb = moduleb->assemblyb;
4221 assembly = moduleb->dynamic_image;
4222 domain = mono_object_domain (assemblyb);
4224 /* Emit ASSEMBLY table */
4225 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4226 alloc_table (table, 1);
4227 values = table->values + MONO_ASSEMBLY_SIZE;
4228 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4229 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4230 if (assemblyb->culture) {
4231 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4232 } else {
4233 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4235 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4236 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4237 set_version_from_string (assemblyb->version, values);
4239 /* Emit FILE + EXPORTED_TYPE table */
4240 module_index = 0;
4241 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4242 int j;
4243 MonoReflectionModuleBuilder *file_module =
4244 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4245 if (file_module != moduleb) {
4246 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4247 module_index ++;
4248 if (file_module->types) {
4249 for (j = 0; j < file_module->num_types; ++j) {
4250 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4251 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4256 if (assemblyb->loaded_modules) {
4257 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4258 MonoReflectionModule *file_module =
4259 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4260 mono_image_fill_file_table (domain, file_module, assembly);
4261 module_index ++;
4262 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4265 if (assemblyb->type_forwarders)
4266 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4268 /* Emit MANIFESTRESOURCE table */
4269 module_index = 0;
4270 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4271 int j;
4272 MonoReflectionModuleBuilder *file_module =
4273 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4274 /* The table for the main module is emitted later */
4275 if (file_module != moduleb) {
4276 module_index ++;
4277 if (file_module->resources) {
4278 int len = mono_array_length (file_module->resources);
4279 for (j = 0; j < len; ++j) {
4280 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4281 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4288 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4291 * mono_image_build_metadata() will fill the info in all the needed metadata tables
4292 * for the modulebuilder @moduleb.
4293 * At the end of the process, method and field tokens are fixed up and the
4294 * on-disk compressed metadata representation is created.
4296 void
4297 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4299 MonoDynamicTable *table;
4300 MonoDynamicImage *assembly;
4301 MonoReflectionAssemblyBuilder *assemblyb;
4302 MonoDomain *domain;
4303 GPtrArray *types;
4304 guint32 *values;
4305 int i, j;
4307 assemblyb = moduleb->assemblyb;
4308 assembly = moduleb->dynamic_image;
4309 domain = mono_object_domain (assemblyb);
4311 if (assembly->text_rva)
4312 return;
4314 assembly->text_rva = START_TEXT_RVA;
4316 if (moduleb->is_main) {
4317 mono_image_emit_manifest (moduleb);
4320 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4321 table->rows = 1; /* .<Module> */
4322 table->next_idx++;
4323 alloc_table (table, table->rows);
4325 * Set the first entry.
4327 values = table->values + table->columns;
4328 values [MONO_TYPEDEF_FLAGS] = 0;
4329 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4330 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4331 values [MONO_TYPEDEF_EXTENDS] = 0;
4332 values [MONO_TYPEDEF_FIELD_LIST] = 1;
4333 values [MONO_TYPEDEF_METHOD_LIST] = 1;
4336 * handle global methods
4337 * FIXME: test what to do when global methods are defined in multiple modules.
4339 if (moduleb->global_methods) {
4340 table = &assembly->tables [MONO_TABLE_METHOD];
4341 table->rows += mono_array_length (moduleb->global_methods);
4342 alloc_table (table, table->rows);
4343 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4344 mono_image_get_method_info (
4345 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4347 if (moduleb->global_fields) {
4348 table = &assembly->tables [MONO_TABLE_FIELD];
4349 table->rows += mono_array_length (moduleb->global_fields);
4350 alloc_table (table, table->rows);
4351 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4352 mono_image_get_field_info (
4353 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4356 table = &assembly->tables [MONO_TABLE_MODULE];
4357 alloc_table (table, 1);
4358 mono_image_fill_module_table (domain, moduleb, assembly);
4360 /* Collect all types into a list sorted by their table_idx */
4361 types = g_ptr_array_new ();
4363 if (moduleb->types)
4364 for (i = 0; i < moduleb->num_types; ++i) {
4365 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4366 collect_types (types, type);
4369 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
4370 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4371 table->rows += types->len;
4372 alloc_table (table, table->rows);
4375 * Emit type names + namespaces at one place inside the string heap,
4376 * so load_class_names () needs to touch fewer pages.
4378 for (i = 0; i < types->len; ++i) {
4379 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4380 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4382 for (i = 0; i < types->len; ++i) {
4383 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4384 string_heap_insert_mstring (&assembly->sheap, tb->name);
4387 for (i = 0; i < types->len; ++i) {
4388 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4389 mono_image_get_type_info (domain, type, assembly);
4393 * table->rows is already set above and in mono_image_fill_module_table.
4395 /* add all the custom attributes at the end, once all the indexes are stable */
4396 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4398 /* CAS assembly permissions */
4399 if (assemblyb->permissions_minimum)
4400 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4401 if (assemblyb->permissions_optional)
4402 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4403 if (assemblyb->permissions_refused)
4404 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4406 module_add_cattrs (assembly, moduleb);
4408 /* fixup tokens */
4409 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4411 /* Create the MethodImpl table. We do this after emitting all methods so we already know
4412 * the final tokens and don't need another fixup pass. */
4414 if (moduleb->global_methods) {
4415 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4416 MonoReflectionMethodBuilder *mb = mono_array_get (
4417 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4418 mono_image_add_methodimpl (assembly, mb);
4422 for (i = 0; i < types->len; ++i) {
4423 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4424 if (type->methods) {
4425 for (j = 0; j < type->num_methods; ++j) {
4426 MonoReflectionMethodBuilder *mb = mono_array_get (
4427 type->methods, MonoReflectionMethodBuilder*, j);
4429 mono_image_add_methodimpl (assembly, mb);
4434 g_ptr_array_free (types, TRUE);
4436 fixup_cattrs (assembly);
4439 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4441 void
4442 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4444 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4447 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4449 #ifndef DISABLE_REFLECTION_EMIT
4452 * mono_image_insert_string:
4453 * @module: module builder object
4454 * @str: a string
4456 * Insert @str into the user string stream of @module.
4458 guint32
4459 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4461 MonoDynamicImage *assembly;
4462 guint32 idx;
4463 char buf [16];
4464 char *b = buf;
4466 MONO_ARCH_SAVE_REGS;
4468 if (!module->dynamic_image)
4469 mono_image_module_basic_init (module);
4471 assembly = module->dynamic_image;
4473 if (assembly->save) {
4474 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4475 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4476 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4478 char *swapped = g_malloc (2 * mono_string_length (str));
4479 const char *p = (const char*)mono_string_chars (str);
4481 swap_with_size (swapped, p, 2, mono_string_length (str));
4482 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4483 g_free (swapped);
4485 #else
4486 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4487 #endif
4488 mono_image_add_stream_data (&assembly->us, "", 1);
4489 } else {
4490 idx = assembly->us.index ++;
4493 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4495 return MONO_TOKEN_STRING | idx;
4498 guint32
4499 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4501 MonoClass *klass;
4502 guint32 token = 0;
4504 klass = obj->vtable->klass;
4505 if (strcmp (klass->name, "MonoMethod") == 0) {
4506 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4507 MonoMethodSignature *sig, *old;
4508 guint32 sig_token, parent;
4509 int nargs, i;
4511 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4513 nargs = mono_array_length (opt_param_types);
4514 old = mono_method_signature (method);
4515 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4517 sig->hasthis = old->hasthis;
4518 sig->explicit_this = old->explicit_this;
4519 sig->call_convention = old->call_convention;
4520 sig->generic_param_count = old->generic_param_count;
4521 sig->param_count = old->param_count + nargs;
4522 sig->sentinelpos = old->param_count;
4523 sig->ret = old->ret;
4525 for (i = 0; i < old->param_count; i++)
4526 sig->params [i] = old->params [i];
4528 for (i = 0; i < nargs; i++) {
4529 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4530 sig->params [old->param_count + i] = rt->type;
4533 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4534 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4535 parent >>= MONO_TYPEDEFORREF_BITS;
4537 parent <<= MONO_MEMBERREF_PARENT_BITS;
4538 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4540 sig_token = method_encode_signature (assembly, sig);
4541 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4542 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4543 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4544 ReflectionMethodBuilder rmb;
4545 guint32 parent, sig;
4546 char *name;
4548 reflection_methodbuilder_from_method_builder (&rmb, mb);
4549 rmb.opt_types = opt_param_types;
4551 sig = method_builder_encode_signature (assembly, &rmb);
4553 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
4554 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4556 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4557 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4559 name = mono_string_to_utf8 (rmb.name);
4560 token = mono_image_get_varargs_method_token (
4561 assembly, parent, name, sig);
4562 g_free (name);
4563 } else {
4564 g_error ("requested method token for %s\n", klass->name);
4567 return token;
4571 * mono_image_create_token:
4572 * @assembly: a dynamic assembly
4573 * @obj:
4574 * @register_token: Whenever to register the token in the assembly->tokens hash.
4576 * Get a token to insert in the IL code stream for the given MemberInfo.
4577 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
4578 * the table_idx-es were recomputed, so registering the token would overwrite an existing
4579 * entry.
4581 guint32
4582 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
4583 gboolean create_methodspec, gboolean register_token)
4585 MonoClass *klass;
4586 guint32 token = 0;
4588 klass = obj->vtable->klass;
4589 if (strcmp (klass->name, "MethodBuilder") == 0) {
4590 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4591 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4593 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
4594 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4595 else
4596 token = mono_image_get_methodbuilder_token (assembly, mb, create_methodspec);
4597 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4598 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4599 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4600 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4602 if (tb->module->dynamic_image == assembly && !tb->generic_params)
4603 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4604 else
4605 token = mono_image_get_ctorbuilder_token (assembly, mb);
4606 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4607 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4608 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4609 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4610 if (tb->generic_params) {
4611 token = mono_image_get_generic_field_token (assembly, fb);
4612 } else {
4613 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4615 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4616 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4617 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4618 } else if (strcmp (klass->name, "MonoType") == 0) {
4619 MonoReflectionType *tb = (MonoReflectionType *)obj;
4620 MonoClass *mc = mono_class_from_mono_type (tb->type);
4621 token = mono_metadata_token_from_dor (
4622 mono_image_typedef_or_ref_full (assembly, tb->type, mc->generic_container == NULL));
4623 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4624 MonoReflectionType *tb = (MonoReflectionType *)obj;
4625 token = mono_metadata_token_from_dor (
4626 mono_image_typedef_or_ref (assembly, tb->type));
4627 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4628 MonoReflectionType *tb = (MonoReflectionType *)obj;
4629 token = mono_metadata_token_from_dor (
4630 mono_image_typedef_or_ref (assembly, tb->type));
4631 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4632 strcmp (klass->name, "MonoMethod") == 0 ||
4633 strcmp (klass->name, "MonoGenericMethod") == 0 ||
4634 strcmp (klass->name, "MonoGenericCMethod") == 0) {
4635 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4636 if (m->method->is_inflated) {
4637 if (create_methodspec)
4638 token = mono_image_get_methodspec_token (assembly, m->method);
4639 else
4640 token = mono_image_get_inflated_method_token (assembly, m->method);
4641 } else if ((m->method->klass->image == &assembly->image) &&
4642 !m->method->klass->generic_class) {
4643 static guint32 method_table_idx = 0xffffff;
4644 if (m->method->klass->wastypebuilder) {
4645 /* we use the same token as the one that was assigned
4646 * to the Methodbuilder.
4647 * FIXME: do the equivalent for Fields.
4649 token = m->method->token;
4650 } else {
4652 * Each token should have a unique index, but the indexes are
4653 * assigned by managed code, so we don't know about them. An
4654 * easy solution is to count backwards...
4656 method_table_idx --;
4657 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4659 } else {
4660 token = mono_image_get_methodref_token (assembly, m->method, create_methodspec);
4662 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4663 } else if (strcmp (klass->name, "MonoField") == 0) {
4664 MonoReflectionField *f = (MonoReflectionField *)obj;
4665 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
4666 static guint32 field_table_idx = 0xffffff;
4667 field_table_idx --;
4668 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4669 } else {
4670 token = mono_image_get_fieldref_token (assembly, f);
4672 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4673 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4674 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4675 token = mono_image_get_array_token (assembly, m);
4676 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4677 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4678 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4679 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
4680 MonoReflectionType *tb = (MonoReflectionType *)obj;
4681 token = mono_metadata_token_from_dor (
4682 mono_image_typedef_or_ref (assembly, tb->type));
4683 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
4684 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
4685 token = mono_image_get_field_on_inst_token (assembly, f);
4686 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
4687 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
4688 token = mono_image_get_ctor_on_inst_token (assembly, c, create_methodspec);
4689 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
4690 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
4691 token = mono_image_get_method_on_inst_token (assembly, m, create_methodspec);
4692 } else {
4693 g_error ("requested token for %s\n", klass->name);
4696 if (register_token)
4697 mono_image_register_token (assembly, token, obj);
4699 return token;
4703 * mono_image_register_token:
4705 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
4706 * the Module.ResolveXXXToken () methods to work.
4708 void
4709 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
4711 MonoObject *prev = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4712 if (prev) {
4713 /* There could be multiple MethodInfo objects with the same token */
4714 //g_assert (prev == obj);
4715 } else {
4716 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4720 #endif /* DISABLE_REFLECTION_EMIT */
4722 typedef struct {
4723 guint32 import_lookup_table;
4724 guint32 timestamp;
4725 guint32 forwarder;
4726 guint32 name_rva;
4727 guint32 import_address_table_rva;
4728 } MonoIDT;
4730 typedef struct {
4731 guint32 name_rva;
4732 guint32 flags;
4733 } MonoILT;
4735 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4737 static MonoDynamicImage*
4738 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4740 static const guchar entrycode [16] = {0xff, 0x25, 0};
4741 MonoDynamicImage *image;
4742 int i;
4744 const char *version;
4746 if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
4747 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
4748 else
4749 version = mono_get_runtime_info ()->runtime_version;
4751 #if HAVE_BOEHM_GC
4752 image = GC_MALLOC (sizeof (MonoDynamicImage));
4753 #else
4754 image = g_new0 (MonoDynamicImage, 1);
4755 #endif
4757 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
4759 /*g_print ("created image %p\n", image);*/
4760 /* keep in sync with image.c */
4761 image->image.name = assembly_name;
4762 image->image.assembly_name = image->image.name; /* they may be different */
4763 image->image.module_name = module_name;
4764 image->image.version = g_strdup (version);
4765 image->image.md_version_major = 1;
4766 image->image.md_version_minor = 1;
4767 image->image.dynamic = TRUE;
4769 image->image.references = g_new0 (MonoAssembly*, 1);
4770 image->image.references [0] = NULL;
4772 mono_image_init (&image->image);
4774 image->token_fixups = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_KEY_GC);
4775 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
4776 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
4777 image->method_aux_hash = g_hash_table_new (NULL, NULL);
4778 image->handleref = g_hash_table_new (NULL, NULL);
4779 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4780 image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4781 image->methodspec = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_KEY_GC);
4782 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4783 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4784 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4785 image->gen_params = g_ptr_array_new ();
4787 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
4788 string_heap_init (&image->sheap);
4789 mono_image_add_stream_data (&image->us, "", 1);
4790 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4791 /* import tables... */
4792 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
4793 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4794 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4795 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4796 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4797 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4798 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4799 stream_data_align (&image->code);
4801 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4803 for (i=0; i < MONO_TABLE_NUM; ++i) {
4804 image->tables [i].next_idx = 1;
4805 image->tables [i].columns = table_sizes [i];
4808 image->image.assembly = (MonoAssembly*)assembly;
4809 image->run = assembly->run;
4810 image->save = assembly->save;
4811 image->pe_kind = 0x1; /* ILOnly */
4812 image->machine = 0x14c; /* I386 */
4814 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
4816 return image;
4819 static void
4820 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
4822 g_free (key);
4825 void
4826 mono_dynamic_image_free (MonoDynamicImage *image)
4828 MonoDynamicImage *di = image;
4829 GList *list;
4830 int i;
4832 if (di->methodspec)
4833 mono_g_hash_table_destroy (di->methodspec);
4834 if (di->typespec)
4835 g_hash_table_destroy (di->typespec);
4836 if (di->typeref)
4837 g_hash_table_destroy (di->typeref);
4838 if (di->handleref)
4839 g_hash_table_destroy (di->handleref);
4840 if (di->tokens)
4841 mono_g_hash_table_destroy (di->tokens);
4842 if (di->generic_def_objects)
4843 mono_g_hash_table_destroy (di->generic_def_objects);
4844 if (di->blob_cache) {
4845 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
4846 g_hash_table_destroy (di->blob_cache);
4848 if (di->standalonesig_cache)
4849 g_hash_table_destroy (di->standalonesig_cache);
4850 for (list = di->array_methods; list; list = list->next) {
4851 ArrayMethod *am = (ArrayMethod *)list->data;
4852 g_free (am->sig);
4853 g_free (am->name);
4854 g_free (am);
4856 g_list_free (di->array_methods);
4857 if (di->gen_params) {
4858 for (i = 0; i < di->gen_params->len; i++) {
4859 GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
4860 if (entry->gparam->type.type) {
4861 MonoGenericParam *param = entry->gparam->type.type->data.generic_param;
4862 g_free ((char*)param->name);
4863 g_free (param);
4865 g_free (entry);
4867 g_ptr_array_free (di->gen_params, TRUE);
4869 if (di->token_fixups)
4870 mono_g_hash_table_destroy (di->token_fixups);
4871 if (di->method_to_table_idx)
4872 g_hash_table_destroy (di->method_to_table_idx);
4873 if (di->field_to_table_idx)
4874 g_hash_table_destroy (di->field_to_table_idx);
4875 if (di->method_aux_hash)
4876 g_hash_table_destroy (di->method_aux_hash);
4877 g_free (di->strong_name);
4878 g_free (di->win32_res);
4879 if (di->public_key)
4880 g_free (di->public_key);
4882 /*g_print ("string heap destroy for image %p\n", di);*/
4883 mono_dynamic_stream_reset (&di->sheap);
4884 mono_dynamic_stream_reset (&di->code);
4885 mono_dynamic_stream_reset (&di->resources);
4886 mono_dynamic_stream_reset (&di->us);
4887 mono_dynamic_stream_reset (&di->blob);
4888 mono_dynamic_stream_reset (&di->tstream);
4889 mono_dynamic_stream_reset (&di->guid);
4890 for (i = 0; i < MONO_TABLE_NUM; ++i) {
4891 g_free (di->tables [i].values);
4895 #ifndef DISABLE_REFLECTION_EMIT
4898 * mono_image_basic_init:
4899 * @assembly: an assembly builder object
4901 * Create the MonoImage that represents the assembly builder and setup some
4902 * of the helper hash table and the basic metadata streams.
4904 void
4905 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4907 MonoDynamicAssembly *assembly;
4908 MonoDynamicImage *image;
4909 MonoDomain *domain = mono_object_domain (assemblyb);
4911 MONO_ARCH_SAVE_REGS;
4913 if (assemblyb->dynamic_assembly)
4914 return;
4916 #if HAVE_BOEHM_GC
4917 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4918 #else
4919 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
4920 #endif
4922 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
4924 assembly->assembly.ref_count = 1;
4925 assembly->assembly.dynamic = TRUE;
4926 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
4927 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4928 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4929 if (assemblyb->culture)
4930 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4931 else
4932 assembly->assembly.aname.culture = g_strdup ("");
4934 if (assemblyb->version) {
4935 char *vstr = mono_string_to_utf8 (assemblyb->version);
4936 char **version = g_strsplit (vstr, ".", 4);
4937 char **parts = version;
4938 assembly->assembly.aname.major = atoi (*parts++);
4939 assembly->assembly.aname.minor = atoi (*parts++);
4940 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
4941 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
4943 g_strfreev (version);
4944 g_free (vstr);
4945 } else {
4946 assembly->assembly.aname.major = 0;
4947 assembly->assembly.aname.minor = 0;
4948 assembly->assembly.aname.build = 0;
4949 assembly->assembly.aname.revision = 0;
4952 assembly->run = assemblyb->access != 2;
4953 assembly->save = assemblyb->access != 1;
4955 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4956 image->initial_image = TRUE;
4957 assembly->assembly.aname.name = image->image.name;
4958 assembly->assembly.image = &image->image;
4960 mono_domain_assemblies_lock (domain);
4961 domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
4962 mono_domain_assemblies_unlock (domain);
4964 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4966 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
4968 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4971 #endif /* DISABLE_REFLECTION_EMIT */
4973 static int
4974 calc_section_size (MonoDynamicImage *assembly)
4976 int nsections = 0;
4978 /* alignment constraints */
4979 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
4980 g_assert ((assembly->code.index % 4) == 0);
4981 assembly->meta_size += 3;
4982 assembly->meta_size &= ~3;
4983 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
4984 g_assert ((assembly->resources.index % 4) == 0);
4986 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4987 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4988 nsections++;
4990 if (assembly->win32_res) {
4991 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4993 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4994 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4995 nsections++;
4998 assembly->sections [MONO_SECTION_RELOC].size = 12;
4999 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5000 nsections++;
5002 return nsections;
5005 typedef struct {
5006 guint32 id;
5007 guint32 offset;
5008 GSList *children;
5009 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5010 } ResTreeNode;
5012 static int
5013 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5015 ResTreeNode *t1 = (ResTreeNode*)a;
5016 ResTreeNode *t2 = (ResTreeNode*)b;
5018 return t1->id - t2->id;
5022 * resource_tree_create:
5024 * Organize the resources into a resource tree.
5026 static ResTreeNode *
5027 resource_tree_create (MonoArray *win32_resources)
5029 ResTreeNode *tree, *res_node, *type_node, *lang_node;
5030 GSList *l;
5031 int i;
5033 tree = g_new0 (ResTreeNode, 1);
5035 for (i = 0; i < mono_array_length (win32_resources); ++i) {
5036 MonoReflectionWin32Resource *win32_res =
5037 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5039 /* Create node */
5041 /* FIXME: BUG: this stores managed references in unmanaged memory */
5042 lang_node = g_new0 (ResTreeNode, 1);
5043 lang_node->id = win32_res->lang_id;
5044 lang_node->win32_res = win32_res;
5046 /* Create type node if neccesary */
5047 type_node = NULL;
5048 for (l = tree->children; l; l = l->next)
5049 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5050 type_node = (ResTreeNode*)l->data;
5051 break;
5054 if (!type_node) {
5055 type_node = g_new0 (ResTreeNode, 1);
5056 type_node->id = win32_res->res_type;
5059 * The resource types have to be sorted otherwise
5060 * Windows Explorer can't display the version information.
5062 tree->children = g_slist_insert_sorted (tree->children,
5063 type_node, resource_tree_compare_by_id);
5066 /* Create res node if neccesary */
5067 res_node = NULL;
5068 for (l = type_node->children; l; l = l->next)
5069 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5070 res_node = (ResTreeNode*)l->data;
5071 break;
5074 if (!res_node) {
5075 res_node = g_new0 (ResTreeNode, 1);
5076 res_node->id = win32_res->res_id;
5077 type_node->children = g_slist_append (type_node->children, res_node);
5080 res_node->children = g_slist_append (res_node->children, lang_node);
5083 return tree;
5087 * resource_tree_encode:
5089 * Encode the resource tree into the format used in the PE file.
5091 static void
5092 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5094 char *entries;
5095 MonoPEResourceDir dir;
5096 MonoPEResourceDirEntry dir_entry;
5097 MonoPEResourceDataEntry data_entry;
5098 GSList *l;
5099 guint32 res_id_entries;
5102 * For the format of the resource directory, see the article
5103 * "An In-Depth Look into the Win32 Portable Executable File Format" by
5104 * Matt Pietrek
5107 memset (&dir, 0, sizeof (dir));
5108 memset (&dir_entry, 0, sizeof (dir_entry));
5109 memset (&data_entry, 0, sizeof (data_entry));
5111 g_assert (sizeof (dir) == 16);
5112 g_assert (sizeof (dir_entry) == 8);
5113 g_assert (sizeof (data_entry) == 16);
5115 node->offset = p - begin;
5117 /* IMAGE_RESOURCE_DIRECTORY */
5118 res_id_entries = g_slist_length (node->children);
5119 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5121 memcpy (p, &dir, sizeof (dir));
5122 p += sizeof (dir);
5124 /* Reserve space for entries */
5125 entries = p;
5126 p += sizeof (dir_entry) * res_id_entries;
5128 /* Write children */
5129 for (l = node->children; l; l = l->next) {
5130 ResTreeNode *child = (ResTreeNode*)l->data;
5132 if (child->win32_res) {
5133 guint32 size;
5135 child->offset = p - begin;
5137 /* IMAGE_RESOURCE_DATA_ENTRY */
5138 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5139 size = mono_array_length (child->win32_res->res_data);
5140 data_entry.rde_size = GUINT32_TO_LE (size);
5142 memcpy (p, &data_entry, sizeof (data_entry));
5143 p += sizeof (data_entry);
5145 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5146 p += size;
5147 } else {
5148 resource_tree_encode (child, begin, p, &p);
5152 /* IMAGE_RESOURCE_ENTRY */
5153 for (l = node->children; l; l = l->next) {
5154 ResTreeNode *child = (ResTreeNode*)l->data;
5156 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5157 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5159 memcpy (entries, &dir_entry, sizeof (dir_entry));
5160 entries += sizeof (dir_entry);
5163 *endbuf = p;
5166 static void
5167 resource_tree_free (ResTreeNode * node)
5169 GSList * list;
5170 for (list = node->children; list; list = list->next)
5171 resource_tree_free ((ResTreeNode*)list->data);
5172 g_slist_free(node->children);
5173 g_free (node);
5176 static void
5177 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5179 char *buf;
5180 char *p;
5181 guint32 size, i;
5182 MonoReflectionWin32Resource *win32_res;
5183 ResTreeNode *tree;
5185 if (!assemblyb->win32_resources)
5186 return;
5189 * Resources are stored in a three level tree inside the PE file.
5190 * - level one contains a node for each type of resource
5191 * - level two contains a node for each resource
5192 * - level three contains a node for each instance of a resource for a
5193 * specific language.
5196 tree = resource_tree_create (assemblyb->win32_resources);
5198 /* Estimate the size of the encoded tree */
5199 size = 0;
5200 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5201 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5202 size += mono_array_length (win32_res->res_data);
5204 /* Directory structure */
5205 size += mono_array_length (assemblyb->win32_resources) * 256;
5206 p = buf = g_malloc (size);
5208 resource_tree_encode (tree, p, p, &p);
5210 g_assert (p - buf <= size);
5212 assembly->win32_res = g_malloc (p - buf);
5213 assembly->win32_res_size = p - buf;
5214 memcpy (assembly->win32_res, buf, p - buf);
5216 g_free (buf);
5217 resource_tree_free (tree);
5220 static void
5221 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5223 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5224 int i;
5226 p += sizeof (MonoPEResourceDir);
5227 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5228 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5229 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5230 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5231 fixup_resource_directory (res_section, child, rva);
5232 } else {
5233 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5234 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5237 p += sizeof (MonoPEResourceDirEntry);
5241 static void
5242 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5244 guint32 dummy;
5245 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5246 g_error ("WriteFile returned %d\n", GetLastError ());
5249 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5252 * mono_image_create_pefile:
5253 * @mb: a module builder object
5255 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
5256 * assembly->pefile where it can be easily retrieved later in chunks.
5258 void
5259 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5261 MonoMSDOSHeader *msdos;
5262 MonoDotNetHeader *header;
5263 MonoSectionTable *section;
5264 MonoCLIHeader *cli_header;
5265 guint32 size, image_size, virtual_base, text_offset;
5266 guint32 header_start, section_start, file_offset, virtual_offset;
5267 MonoDynamicImage *assembly;
5268 MonoReflectionAssemblyBuilder *assemblyb;
5269 MonoDynamicStream pefile_stream = {0};
5270 MonoDynamicStream *pefile = &pefile_stream;
5271 int i, nsections;
5272 guint32 *rva, value;
5273 guchar *p;
5274 static const unsigned char msheader[] = {
5275 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5276 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5277 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5278 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5279 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5280 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5281 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5282 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5285 assemblyb = mb->assemblyb;
5287 mono_image_basic_init (assemblyb);
5288 assembly = mb->dynamic_image;
5290 assembly->pe_kind = assemblyb->pe_kind;
5291 assembly->machine = assemblyb->machine;
5292 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5293 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5295 mono_image_build_metadata (mb);
5297 if (mb->is_main && assemblyb->resources) {
5298 int len = mono_array_length (assemblyb->resources);
5299 for (i = 0; i < len; ++i)
5300 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5303 if (mb->resources) {
5304 int len = mono_array_length (mb->resources);
5305 for (i = 0; i < len; ++i)
5306 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5309 build_compressed_metadata (assembly);
5311 if (mb->is_main)
5312 assembly_add_win32_resources (assembly, assemblyb);
5314 nsections = calc_section_size (assembly);
5316 /* The DOS header and stub */
5317 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5318 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5320 /* the dotnet header */
5321 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5323 /* the section tables */
5324 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5326 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5327 virtual_offset = VIRT_ALIGN;
5328 image_size = 0;
5330 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5331 if (!assembly->sections [i].size)
5332 continue;
5333 /* align offsets */
5334 file_offset += FILE_ALIGN - 1;
5335 file_offset &= ~(FILE_ALIGN - 1);
5336 virtual_offset += VIRT_ALIGN - 1;
5337 virtual_offset &= ~(VIRT_ALIGN - 1);
5339 assembly->sections [i].offset = file_offset;
5340 assembly->sections [i].rva = virtual_offset;
5342 file_offset += assembly->sections [i].size;
5343 virtual_offset += assembly->sections [i].size;
5344 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5347 file_offset += FILE_ALIGN - 1;
5348 file_offset &= ~(FILE_ALIGN - 1);
5350 image_size += section_start + sizeof (MonoSectionTable) * nsections;
5352 /* back-patch info */
5353 msdos = (MonoMSDOSHeader*)pefile->data;
5354 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5356 header = (MonoDotNetHeader*)(pefile->data + header_start);
5357 header->pesig [0] = 'P';
5358 header->pesig [1] = 'E';
5360 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5361 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5362 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5363 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5364 if (assemblyb->pekind == 1) {
5365 /* it's a dll */
5366 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5367 } else {
5368 /* it's an exe */
5369 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5372 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5374 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5375 header->pe.pe_major = 6;
5376 header->pe.pe_minor = 0;
5377 size = assembly->sections [MONO_SECTION_TEXT].size;
5378 size += FILE_ALIGN - 1;
5379 size &= ~(FILE_ALIGN - 1);
5380 header->pe.pe_code_size = GUINT32_FROM_LE(size);
5381 size = assembly->sections [MONO_SECTION_RSRC].size;
5382 size += FILE_ALIGN - 1;
5383 size &= ~(FILE_ALIGN - 1);
5384 header->pe.pe_data_size = GUINT32_FROM_LE(size);
5385 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5386 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5387 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5388 /* pe_rva_entry_point always at the beginning of the text section */
5389 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5391 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5392 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5393 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5394 header->nt.pe_os_major = GUINT16_FROM_LE (4);
5395 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5396 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5397 size = section_start;
5398 size += FILE_ALIGN - 1;
5399 size &= ~(FILE_ALIGN - 1);
5400 header->nt.pe_header_size = GUINT32_FROM_LE (size);
5401 size = image_size;
5402 size += VIRT_ALIGN - 1;
5403 size &= ~(VIRT_ALIGN - 1);
5404 header->nt.pe_image_size = GUINT32_FROM_LE (size);
5407 // Translate the PEFileKind value to the value expected by the Windows loader
5410 short kind;
5413 // PEFileKinds.Dll == 1
5414 // PEFileKinds.ConsoleApplication == 2
5415 // PEFileKinds.WindowApplication == 3
5417 // need to get:
5418 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5419 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5421 if (assemblyb->pekind == 3)
5422 kind = 2;
5423 else
5424 kind = 3;
5426 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5428 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5429 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5430 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5431 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5432 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5433 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
5435 /* fill data directory entries */
5437 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
5438 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5440 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
5441 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
5443 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
5444 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
5445 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
5446 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5447 /* patch entrypoint name */
5448 if (assemblyb->pekind == 1)
5449 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
5450 else
5451 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
5452 /* patch imported function RVA name */
5453 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
5454 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
5456 /* the import table */
5457 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
5458 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
5459 /* patch imported dll RVA name and other entries in the dir */
5460 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
5461 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
5462 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
5463 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5464 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
5465 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
5467 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
5468 value = (assembly->text_rva + assembly->imp_names_offset);
5469 *p++ = (value) & 0xff;
5470 *p++ = (value >> 8) & (0xff);
5471 *p++ = (value >> 16) & (0xff);
5472 *p++ = (value >> 24) & (0xff);
5474 /* the CLI header info */
5475 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
5476 cli_header->ch_size = GUINT32_FROM_LE (72);
5477 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
5478 if (mono_framework_version () > 1)
5479 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
5480 else
5481 cli_header->ch_runtime_minor = GUINT16_FROM_LE (0);
5482 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
5483 if (assemblyb->entry_point) {
5484 guint32 table_idx = 0;
5485 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
5486 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
5487 table_idx = methodb->table_idx;
5488 } else {
5489 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
5491 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
5492 } else {
5493 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
5495 /* The embedded managed resources */
5496 text_offset = assembly->text_rva + assembly->code.index;
5497 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
5498 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
5499 text_offset += assembly->resources.index;
5500 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
5501 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
5502 text_offset += assembly->meta_size;
5503 if (assembly->strong_name_size) {
5504 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
5505 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
5506 text_offset += assembly->strong_name_size;
5509 /* write the section tables and section content */
5510 section = (MonoSectionTable*)(pefile->data + section_start);
5511 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5512 static const char section_names [][7] = {
5513 ".text", ".rsrc", ".reloc"
5515 if (!assembly->sections [i].size)
5516 continue;
5517 strcpy (section->st_name, section_names [i]);
5518 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5519 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5520 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5521 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5522 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5523 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5524 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5525 section ++;
5528 checked_write_file (file, pefile->data, pefile->index);
5530 mono_dynamic_stream_reset (pefile);
5532 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5533 if (!assembly->sections [i].size)
5534 continue;
5536 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5537 g_error ("SetFilePointer returned %d\n", GetLastError ());
5539 switch (i) {
5540 case MONO_SECTION_TEXT:
5541 /* patch entry point */
5542 p = (guchar*)(assembly->code.data + 2);
5543 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5544 *p++ = (value) & 0xff;
5545 *p++ = (value >> 8) & 0xff;
5546 *p++ = (value >> 16) & 0xff;
5547 *p++ = (value >> 24) & 0xff;
5549 checked_write_file (file, assembly->code.data, assembly->code.index);
5550 checked_write_file (file, assembly->resources.data, assembly->resources.index);
5551 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5552 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5555 g_free (assembly->image.raw_metadata);
5556 break;
5557 case MONO_SECTION_RELOC: {
5558 struct {
5559 guint32 page_rva;
5560 guint32 block_size;
5561 guint16 type_and_offset;
5562 guint16 term;
5563 } reloc;
5565 g_assert (sizeof (reloc) == 12);
5567 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5568 reloc.block_size = GUINT32_FROM_LE (12);
5571 * the entrypoint is always at the start of the text section
5572 * 3 is IMAGE_REL_BASED_HIGHLOW
5573 * 2 is patch_size_rva - text_rva
5575 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5576 reloc.term = 0;
5578 checked_write_file (file, &reloc, sizeof (reloc));
5580 break;
5582 case MONO_SECTION_RSRC:
5583 if (assembly->win32_res) {
5585 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5586 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5587 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5589 break;
5590 default:
5591 g_assert_not_reached ();
5595 /* check that the file is properly padded */
5596 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5597 g_error ("SetFilePointer returned %d\n", GetLastError ());
5598 if (! SetEndOfFile (file))
5599 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5601 mono_dynamic_stream_reset (&assembly->code);
5602 mono_dynamic_stream_reset (&assembly->us);
5603 mono_dynamic_stream_reset (&assembly->blob);
5604 mono_dynamic_stream_reset (&assembly->guid);
5605 mono_dynamic_stream_reset (&assembly->sheap);
5607 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5608 g_hash_table_destroy (assembly->blob_cache);
5609 assembly->blob_cache = NULL;
5612 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5614 void
5615 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5617 g_assert_not_reached ();
5620 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5622 #ifndef DISABLE_REFLECTION_EMIT
5624 MonoReflectionModule *
5625 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5627 char *name;
5628 MonoImage *image;
5629 MonoImageOpenStatus status;
5630 MonoDynamicAssembly *assembly;
5631 guint32 module_count;
5632 MonoImage **new_modules;
5633 gboolean *new_modules_loaded;
5635 name = mono_string_to_utf8 (fileName);
5637 image = mono_image_open (name, &status);
5638 if (!image) {
5639 MonoException *exc;
5640 if (status == MONO_IMAGE_ERROR_ERRNO)
5641 exc = mono_get_exception_file_not_found (fileName);
5642 else
5643 exc = mono_get_exception_bad_image_format (name);
5644 g_free (name);
5645 mono_raise_exception (exc);
5648 g_free (name);
5650 assembly = ab->dynamic_assembly;
5651 image->assembly = (MonoAssembly*)assembly;
5653 module_count = image->assembly->image->module_count;
5654 new_modules = g_new0 (MonoImage *, module_count + 1);
5655 new_modules_loaded = g_new0 (gboolean, module_count + 1);
5657 if (image->assembly->image->modules)
5658 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5659 if (image->assembly->image->modules_loaded)
5660 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
5661 new_modules [module_count] = image;
5662 new_modules_loaded [module_count] = TRUE;
5663 mono_image_addref (image);
5665 g_free (image->assembly->image->modules);
5666 image->assembly->image->modules = new_modules;
5667 image->assembly->image->modules_loaded = new_modules_loaded;
5668 image->assembly->image->module_count ++;
5670 mono_assembly_load_references (image, &status);
5671 if (status) {
5672 mono_image_close (image);
5673 mono_raise_exception (mono_get_exception_file_not_found (fileName));
5676 return mono_module_get_object (mono_domain_get (), image);
5679 #endif /* DISABLE_REFLECTION_EMIT */
5682 * We need to return always the same object for MethodInfo, FieldInfo etc..
5683 * but we need to consider the reflected type.
5684 * type uses a different hash, since it uses custom hash/equal functions.
5687 typedef struct {
5688 gpointer item;
5689 MonoClass *refclass;
5690 } ReflectedEntry;
5692 static gboolean
5693 reflected_equal (gconstpointer a, gconstpointer b) {
5694 const ReflectedEntry *ea = a;
5695 const ReflectedEntry *eb = b;
5697 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
5700 static guint
5701 reflected_hash (gconstpointer a) {
5702 const ReflectedEntry *ea = a;
5703 return mono_aligned_addr_hash (ea->item);
5706 #define CHECK_OBJECT(t,p,k) \
5707 do { \
5708 t _obj; \
5709 ReflectedEntry e; \
5710 e.item = (p); \
5711 e.refclass = (k); \
5712 mono_domain_lock (domain); \
5713 if (!domain->refobject_hash) \
5714 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5715 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
5716 mono_domain_unlock (domain); \
5717 return _obj; \
5719 mono_domain_unlock (domain); \
5720 } while (0)
5722 #ifdef HAVE_BOEHM_GC
5723 #define ALLOC_REFENTRY mono_gc_alloc_fixed (sizeof (ReflectedEntry), NULL)
5724 #else
5725 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5726 #endif
5728 #define CACHE_OBJECT(t,p,o,k) \
5729 do { \
5730 t _obj; \
5731 ReflectedEntry pe; \
5732 pe.item = (p); \
5733 pe.refclass = (k); \
5734 mono_domain_lock (domain); \
5735 if (!domain->refobject_hash) \
5736 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5737 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
5738 if (!_obj) { \
5739 ReflectedEntry *e = ALLOC_REFENTRY; \
5740 e->item = (p); \
5741 e->refclass = (k); \
5742 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
5743 _obj = o; \
5745 mono_domain_unlock (domain); \
5746 return _obj; \
5747 } while (0)
5749 static gpointer
5750 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
5752 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5755 static gpointer
5756 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5758 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
5761 #ifndef DISABLE_REFLECTION_EMIT
5763 void
5764 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5766 MonoDynamicImage *image = moduleb->dynamic_image;
5767 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5768 if (!image) {
5769 int module_count;
5770 MonoImage **new_modules;
5771 MonoImage *ass;
5773 * FIXME: we already created an image in mono_image_basic_init (), but
5774 * we don't know which module it belongs to, since that is only
5775 * determined at assembly save time.
5777 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5778 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5780 moduleb->module.image = &image->image;
5781 moduleb->dynamic_image = image;
5782 register_module (mono_object_domain (moduleb), moduleb, image);
5784 /* register the module with the assembly */
5785 ass = ab->dynamic_assembly->assembly.image;
5786 module_count = ass->module_count;
5787 new_modules = g_new0 (MonoImage *, module_count + 1);
5789 if (ass->modules)
5790 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
5791 new_modules [module_count] = &image->image;
5792 mono_image_addref (&image->image);
5794 g_free (ass->modules);
5795 ass->modules = new_modules;
5796 ass->module_count ++;
5800 #endif
5803 * mono_assembly_get_object:
5804 * @domain: an app domain
5805 * @assembly: an assembly
5807 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5809 MonoReflectionAssembly*
5810 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5812 static MonoClass *System_Reflection_Assembly;
5813 MonoReflectionAssembly *res;
5815 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5816 if (!System_Reflection_Assembly)
5817 System_Reflection_Assembly = mono_class_from_name (
5818 mono_defaults.corlib, "System.Reflection", "Assembly");
5819 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5820 res->assembly = assembly;
5822 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5827 MonoReflectionModule*
5828 mono_module_get_object (MonoDomain *domain, MonoImage *image)
5830 static MonoClass *System_Reflection_Module;
5831 MonoReflectionModule *res;
5832 char* basename;
5834 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5835 if (!System_Reflection_Module)
5836 System_Reflection_Module = mono_class_from_name (
5837 mono_defaults.corlib, "System.Reflection", "Module");
5838 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5840 res->image = image;
5841 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5843 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
5844 basename = g_path_get_basename (image->name);
5845 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
5846 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
5848 g_free (basename);
5850 if (image->assembly->image == image) {
5851 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5852 } else {
5853 int i;
5854 res->token = 0;
5855 if (image->assembly->image->modules) {
5856 for (i = 0; i < image->assembly->image->module_count; i++) {
5857 if (image->assembly->image->modules [i] == image)
5858 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5860 g_assert (res->token);
5864 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
5867 MonoReflectionModule*
5868 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5870 static MonoClass *System_Reflection_Module;
5871 MonoReflectionModule *res;
5872 MonoTableInfo *table;
5873 guint32 cols [MONO_FILE_SIZE];
5874 const char *name;
5875 guint32 i, name_idx;
5876 const char *val;
5878 if (!System_Reflection_Module)
5879 System_Reflection_Module = mono_class_from_name (
5880 mono_defaults.corlib, "System.Reflection", "Module");
5881 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5883 table = &image->tables [MONO_TABLE_FILE];
5884 g_assert (table_index < table->rows);
5885 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5887 res->image = NULL;
5888 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5889 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5891 /* Check whenever the row has a corresponding row in the moduleref table */
5892 table = &image->tables [MONO_TABLE_MODULEREF];
5893 for (i = 0; i < table->rows; ++i) {
5894 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5895 val = mono_metadata_string_heap (image, name_idx);
5896 if (strcmp (val, name) == 0)
5897 res->image = image->modules [i];
5900 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
5901 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
5902 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
5903 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5904 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5906 return res;
5909 static gboolean
5910 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5912 if ((t1->type != t2->type) ||
5913 (t1->byref != t2->byref))
5914 return FALSE;
5916 switch (t1->type) {
5917 case MONO_TYPE_VOID:
5918 case MONO_TYPE_BOOLEAN:
5919 case MONO_TYPE_CHAR:
5920 case MONO_TYPE_I1:
5921 case MONO_TYPE_U1:
5922 case MONO_TYPE_I2:
5923 case MONO_TYPE_U2:
5924 case MONO_TYPE_I4:
5925 case MONO_TYPE_U4:
5926 case MONO_TYPE_I8:
5927 case MONO_TYPE_U8:
5928 case MONO_TYPE_R4:
5929 case MONO_TYPE_R8:
5930 case MONO_TYPE_STRING:
5931 case MONO_TYPE_I:
5932 case MONO_TYPE_U:
5933 case MONO_TYPE_OBJECT:
5934 case MONO_TYPE_TYPEDBYREF:
5935 return TRUE;
5936 case MONO_TYPE_VALUETYPE:
5937 case MONO_TYPE_CLASS:
5938 case MONO_TYPE_SZARRAY:
5939 return t1->data.klass == t2->data.klass;
5940 case MONO_TYPE_PTR:
5941 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5942 case MONO_TYPE_ARRAY:
5943 if (t1->data.array->rank != t2->data.array->rank)
5944 return FALSE;
5945 return t1->data.array->eklass == t2->data.array->eklass;
5946 case MONO_TYPE_GENERICINST: {
5947 int i;
5948 MonoGenericInst *i1 = t1->data.generic_class->context.class_inst;
5949 MonoGenericInst *i2 = t2->data.generic_class->context.class_inst;
5950 if (i1->type_argc != i2->type_argc)
5951 return FALSE;
5952 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
5953 &t2->data.generic_class->container_class->byval_arg))
5954 return FALSE;
5955 /* FIXME: we should probably just compare the instance pointers directly. */
5956 for (i = 0; i < i1->type_argc; ++i) {
5957 if (!mono_metadata_type_equal (i1->type_argv [i], i2->type_argv [i]))
5958 return FALSE;
5960 return TRUE;
5962 case MONO_TYPE_VAR:
5963 case MONO_TYPE_MVAR:
5964 return t1->data.generic_param == t2->data.generic_param;
5965 default:
5966 g_error ("implement type compare for %0x!", t1->type);
5967 return FALSE;
5970 return FALSE;
5973 static guint
5974 mymono_metadata_type_hash (MonoType *t1)
5976 guint hash;
5978 hash = t1->type;
5980 hash |= t1->byref << 6; /* do not collide with t1->type values */
5981 switch (t1->type) {
5982 case MONO_TYPE_VALUETYPE:
5983 case MONO_TYPE_CLASS:
5984 case MONO_TYPE_SZARRAY:
5985 /* check if the distribution is good enough */
5986 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5987 case MONO_TYPE_PTR:
5988 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5989 case MONO_TYPE_GENERICINST: {
5990 int i;
5991 MonoGenericInst *inst = t1->data.generic_class->context.class_inst;
5992 hash += g_str_hash (t1->data.generic_class->container_class->name);
5993 hash *= 13;
5994 for (i = 0; i < inst->type_argc; ++i) {
5995 hash += mymono_metadata_type_hash (inst->type_argv [i]);
5996 hash *= 13;
5998 return hash;
6001 return hash;
6004 static MonoReflectionGenericClass*
6005 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
6007 static MonoClass *System_Reflection_MonoGenericClass;
6008 MonoReflectionGenericClass *res;
6009 MonoClass *klass, *gklass;
6011 if (!System_Reflection_MonoGenericClass) {
6012 System_Reflection_MonoGenericClass = mono_class_from_name (
6013 mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
6014 g_assert (System_Reflection_MonoGenericClass);
6017 klass = mono_class_from_mono_type (geninst);
6018 gklass = klass->generic_class->container_class;
6020 mono_class_init (klass);
6022 #ifdef HAVE_SGEN_GC
6023 res = (MonoReflectionGenericClass *) mono_gc_alloc_pinned_obj (mono_class_vtable (domain, System_Reflection_MonoGenericClass), mono_class_instance_size (System_Reflection_MonoGenericClass));
6024 #else
6025 res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
6026 #endif
6028 res->type.type = geninst;
6029 g_assert (gklass->reflection_info);
6030 g_assert (!strcmp (((MonoObject*)gklass->reflection_info)->vtable->klass->name, "TypeBuilder"));
6031 MONO_OBJECT_SETREF (res, generic_type, gklass->reflection_info);
6033 return res;
6036 static gboolean
6037 verify_safe_for_managed_space (MonoType *type)
6039 switch (type->type) {
6040 #ifdef DEBUG_HARDER
6041 case MONO_TYPE_ARRAY:
6042 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6043 case MONO_TYPE_PTR:
6044 return verify_safe_for_managed_space (type->data.type);
6045 case MONO_TYPE_SZARRAY:
6046 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6047 case MONO_TYPE_GENERICINST: {
6048 MonoGenericInst *inst = type->data.generic_class->inst;
6049 int i;
6050 if (!inst->is_open)
6051 break;
6052 for (i = 0; i < inst->type_argc; ++i)
6053 if (!verify_safe_for_managed_space (inst->type_argv [i]))
6054 return FALSE;
6055 break;
6057 #endif
6058 case MONO_TYPE_VAR:
6059 case MONO_TYPE_MVAR:
6060 return TRUE;
6062 return TRUE;
6066 * mono_type_get_object:
6067 * @domain: an app domain
6068 * @type: a type
6070 * Return an System.MonoType object representing the type @type.
6072 MonoReflectionType*
6073 mono_type_get_object (MonoDomain *domain, MonoType *type)
6075 MonoReflectionType *res;
6076 MonoClass *klass = mono_class_from_mono_type (type);
6078 /*we must avoid using @type as it might have come
6079 * from a mono_metadata_type_dup and the caller
6080 * expects that is can be freed.
6081 * Using the right type from
6083 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6085 /* void is very common */
6086 if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6087 return (MonoReflectionType*)domain->typeof_void;
6090 * If the vtable of the given class was already created, we can use
6091 * the MonoType from there and avoid all locking and hash table lookups.
6093 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6094 * that the resulting object is diferent.
6096 if (type == &klass->byval_arg && !klass->image->dynamic) {
6097 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6098 if (vtable && vtable->type)
6099 return vtable->type;
6102 mono_domain_lock (domain);
6103 if (!domain->type_hash)
6104 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash,
6105 (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
6106 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
6107 mono_domain_unlock (domain);
6108 return res;
6110 /* Create a MonoGenericClass object for instantiations of not finished TypeBuilders */
6111 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder) {
6112 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
6113 mono_g_hash_table_insert (domain->type_hash, type, res);
6114 mono_domain_unlock (domain);
6115 return res;
6118 if (!verify_safe_for_managed_space (type)) {
6119 mono_domain_unlock (domain);
6120 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6123 if (klass->reflection_info && !klass->wastypebuilder) {
6124 /* g_assert_not_reached (); */
6125 /* should this be considered an error condition? */
6126 if (!type->byref) {
6127 mono_domain_unlock (domain);
6128 return klass->reflection_info;
6131 // FIXME: Get rid of this, do it in the icalls for Type
6132 mono_class_init (klass);
6133 #ifdef HAVE_SGEN_GC
6134 res = (MonoReflectionType *)mono_gc_alloc_pinned_obj (mono_class_vtable (domain, mono_defaults.monotype_class), mono_class_instance_size (mono_defaults.monotype_class));
6135 #else
6136 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
6137 #endif
6138 res->type = type;
6139 mono_g_hash_table_insert (domain->type_hash, type, res);
6141 if (type->type == MONO_TYPE_VOID)
6142 MONO_OBJECT_SETREF (domain, typeof_void, res);
6144 mono_domain_unlock (domain);
6145 return res;
6149 * mono_method_get_object:
6150 * @domain: an app domain
6151 * @method: a method
6152 * @refclass: the reflected type (can be NULL)
6154 * Return an System.Reflection.MonoMethod object representing the method @method.
6156 MonoReflectionMethod*
6157 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6160 * We use the same C representation for methods and constructors, but the type
6161 * name in C# is different.
6163 static MonoClass *System_Reflection_MonoMethod = NULL;
6164 static MonoClass *System_Reflection_MonoCMethod = NULL;
6165 static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6166 static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6167 MonoClass *klass;
6168 MonoReflectionMethod *ret;
6171 * Don't let static RGCTX invoke wrappers get into
6172 * MonoReflectionMethods.
6174 if (method->wrapper_type == MONO_WRAPPER_STATIC_RGCTX_INVOKE)
6175 method = mono_marshal_method_from_wrapper (method);
6177 if (method->is_inflated) {
6178 MonoReflectionGenericMethod *gret;
6180 refclass = method->klass;
6181 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6182 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6183 if (!System_Reflection_MonoGenericCMethod)
6184 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6185 klass = System_Reflection_MonoGenericCMethod;
6186 } else {
6187 if (!System_Reflection_MonoGenericMethod)
6188 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6189 klass = System_Reflection_MonoGenericMethod;
6191 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6192 gret->method.method = method;
6193 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6194 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6195 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6198 if (!refclass)
6199 refclass = method->klass;
6201 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6202 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6203 if (!System_Reflection_MonoCMethod)
6204 System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6205 klass = System_Reflection_MonoCMethod;
6207 else {
6208 if (!System_Reflection_MonoMethod)
6209 System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6210 klass = System_Reflection_MonoMethod;
6212 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6213 ret->method = method;
6214 MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6215 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6219 * mono_field_get_object:
6220 * @domain: an app domain
6221 * @klass: a type
6222 * @field: a field
6224 * Return an System.Reflection.MonoField object representing the field @field
6225 * in class @klass.
6227 MonoReflectionField*
6228 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6230 MonoReflectionField *res;
6231 static MonoClass *monofield_klass;
6233 CHECK_OBJECT (MonoReflectionField *, field, klass);
6234 if (!monofield_klass)
6235 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6236 res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6237 res->klass = klass;
6238 res->field = field;
6239 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6240 if (is_field_on_inst (field))
6241 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6242 else
6243 res->attrs = field->type->attrs;
6244 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6245 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6249 * mono_property_get_object:
6250 * @domain: an app domain
6251 * @klass: a type
6252 * @property: a property
6254 * Return an System.Reflection.MonoProperty object representing the property @property
6255 * in class @klass.
6257 MonoReflectionProperty*
6258 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6260 MonoReflectionProperty *res;
6261 static MonoClass *monoproperty_klass;
6263 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6264 if (!monoproperty_klass)
6265 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6266 res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6267 res->klass = klass;
6268 res->property = property;
6269 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6273 * mono_event_get_object:
6274 * @domain: an app domain
6275 * @klass: a type
6276 * @event: a event
6278 * Return an System.Reflection.MonoEvent object representing the event @event
6279 * in class @klass.
6281 MonoReflectionEvent*
6282 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6284 MonoReflectionEvent *res;
6285 static MonoClass *monoevent_klass;
6287 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6288 if (!monoevent_klass)
6289 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6290 res = (MonoReflectionEvent *)mono_object_new (domain, monoevent_klass);
6291 res->klass = klass;
6292 res->event = event;
6293 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6297 * mono_get_reflection_missing_object:
6298 * @domain: Domain where the object lives
6300 * Returns the System.Reflection.Missing.Value singleton object
6301 * (of type System.Reflection.Missing).
6303 * Used as the value for ParameterInfo.DefaultValue when Optional
6304 * is present
6306 static MonoObject *
6307 mono_get_reflection_missing_object (MonoDomain *domain)
6309 MonoObject *obj;
6310 static MonoClassField *missing_value_field = NULL;
6312 if (!missing_value_field) {
6313 MonoClass *missing_klass;
6314 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6315 mono_class_init (missing_klass);
6316 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6317 g_assert (missing_value_field);
6319 obj = mono_field_get_value_object (domain, missing_value_field, NULL);
6320 g_assert (obj);
6321 return obj;
6324 static MonoObject*
6325 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6327 if (!*dbnull)
6328 *dbnull = mono_get_dbnull_object (domain);
6329 return *dbnull;
6332 static MonoObject*
6333 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6335 if (!*reflection_missing)
6336 *reflection_missing = mono_get_reflection_missing_object (domain);
6337 return *reflection_missing;
6341 * mono_param_get_objects:
6342 * @domain: an app domain
6343 * @method: a method
6345 * Return an System.Reflection.ParameterInfo array object representing the parameters
6346 * in the method @method.
6348 MonoArray*
6349 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
6351 static MonoClass *System_Reflection_ParameterInfo;
6352 static MonoClass *System_Reflection_ParameterInfo_array;
6353 MonoArray *res = NULL;
6354 MonoReflectionMethod *member = NULL;
6355 MonoReflectionParameter *param = NULL;
6356 char **names, **blobs = NULL;
6357 guint32 *types = NULL;
6358 MonoType *type = NULL;
6359 MonoObject *dbnull = NULL;
6360 MonoObject *missing = NULL;
6361 MonoMarshalSpec **mspecs;
6362 MonoMethodSignature *sig;
6363 MonoVTable *pinfo_vtable;
6364 int i;
6366 if (!System_Reflection_ParameterInfo_array) {
6367 MonoClass *klass;
6369 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6370 mono_memory_barrier ();
6371 System_Reflection_ParameterInfo = klass;
6373 klass = mono_array_class_get (klass, 1);
6374 mono_memory_barrier ();
6375 System_Reflection_ParameterInfo_array = klass;
6378 if (!mono_method_signature (method)->param_count)
6379 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6381 /* Note: the cache is based on the address of the signature into the method
6382 * since we already cache MethodInfos with the method as keys.
6384 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
6386 sig = mono_method_signature (method);
6387 member = mono_method_get_object (domain, method, NULL);
6388 names = g_new (char *, sig->param_count);
6389 mono_method_get_param_names (method, (const char **) names);
6391 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
6392 mono_method_get_marshal_info (method, mspecs);
6394 res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
6395 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
6396 for (i = 0; i < sig->param_count; ++i) {
6397 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
6398 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
6399 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
6400 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
6401 param->PositionImpl = i;
6402 param->AttrsImpl = sig->params [i]->attrs;
6404 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
6405 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6406 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6407 else
6408 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6409 } else {
6411 if (!blobs) {
6412 blobs = g_new0 (char *, sig->param_count);
6413 types = g_new0 (guint32, sig->param_count);
6414 get_default_param_value_blobs (method, blobs, types);
6417 /* Build MonoType for the type from the Constant Table */
6418 if (!type)
6419 type = g_new0 (MonoType, 1);
6420 type->type = types [i];
6421 type->data.klass = NULL;
6422 if (types [i] == MONO_TYPE_CLASS)
6423 type->data.klass = mono_defaults.object_class;
6424 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
6425 /* For enums, types [i] contains the base type */
6427 type->type = MONO_TYPE_VALUETYPE;
6428 type->data.klass = mono_class_from_mono_type (sig->params [i]);
6429 } else
6430 type->data.klass = mono_class_from_mono_type (type);
6432 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
6434 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6435 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
6436 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6437 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6438 else
6439 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6444 if (mspecs [i + 1])
6445 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
6447 mono_array_setref (res, i, param);
6449 g_free (names);
6450 g_free (blobs);
6451 g_free (types);
6452 g_free (type);
6454 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
6455 if (mspecs [i])
6456 mono_metadata_free_marshal_spec (mspecs [i]);
6457 g_free (mspecs);
6459 CACHE_OBJECT (MonoArray *, &(method->signature), res, NULL);
6463 * mono_method_body_get_object:
6464 * @domain: an app domain
6465 * @method: a method
6467 * Return an System.Reflection.MethodBody object representing the method @method.
6469 MonoReflectionMethodBody*
6470 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
6472 static MonoClass *System_Reflection_MethodBody = NULL;
6473 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
6474 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
6475 MonoReflectionMethodBody *ret;
6476 MonoMethodNormal *mn;
6477 MonoMethodHeader *header;
6478 guint32 method_rva, local_var_sig_token;
6479 char *ptr;
6480 unsigned char format, flags;
6481 int i;
6483 if (!System_Reflection_MethodBody)
6484 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
6485 if (!System_Reflection_LocalVariableInfo)
6486 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
6487 if (!System_Reflection_ExceptionHandlingClause)
6488 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
6490 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
6492 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6493 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
6494 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
6495 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
6496 return NULL;
6497 mn = (MonoMethodNormal *)method;
6498 header = mono_method_get_header (method);
6500 /* Obtain local vars signature token */
6501 method_rva = mono_metadata_decode_row_col (&method->klass->image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
6502 ptr = mono_image_rva_map (method->klass->image, method_rva);
6503 flags = *(const unsigned char *) ptr;
6504 format = flags & METHOD_HEADER_FORMAT_MASK;
6505 switch (format){
6506 case METHOD_HEADER_TINY_FORMAT:
6507 case METHOD_HEADER_TINY_FORMAT1:
6508 local_var_sig_token = 0;
6509 break;
6510 case METHOD_HEADER_FAT_FORMAT:
6511 ptr += 2;
6512 ptr += 2;
6513 ptr += 4;
6514 local_var_sig_token = read32 (ptr);
6515 break;
6516 default:
6517 g_assert_not_reached ();
6520 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
6522 ret->init_locals = header->init_locals;
6523 ret->max_stack = header->max_stack;
6524 ret->local_var_sig_token = local_var_sig_token;
6525 MONO_OBJECT_SETREF (ret, il, mono_array_new (domain, mono_defaults.byte_class, header->code_size));
6526 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
6528 /* Locals */
6529 MONO_OBJECT_SETREF (ret, locals, mono_array_new (domain, System_Reflection_LocalVariableInfo, header->num_locals));
6530 for (i = 0; i < header->num_locals; ++i) {
6531 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
6532 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
6533 info->is_pinned = header->locals [i]->pinned;
6534 info->local_index = i;
6535 mono_array_setref (ret->locals, i, info);
6538 /* Exceptions */
6539 MONO_OBJECT_SETREF (ret, clauses, mono_array_new (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
6540 for (i = 0; i < header->num_clauses; ++i) {
6541 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
6542 MonoExceptionClause *clause = &header->clauses [i];
6544 info->flags = clause->flags;
6545 info->try_offset = clause->try_offset;
6546 info->try_length = clause->try_len;
6547 info->handler_offset = clause->handler_offset;
6548 info->handler_length = clause->handler_len;
6549 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
6550 info->filter_offset = clause->data.filter_offset;
6551 else if (clause->data.catch_class)
6552 MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
6554 mono_array_setref (ret->clauses, i, info);
6557 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
6558 return ret;
6562 * mono_get_dbnull_object:
6563 * @domain: Domain where the object lives
6565 * Returns the System.DBNull.Value singleton object
6567 * Used as the value for ParameterInfo.DefaultValue
6569 MonoObject *
6570 mono_get_dbnull_object (MonoDomain *domain)
6572 MonoObject *obj;
6573 static MonoClassField *dbnull_value_field = NULL;
6575 if (!dbnull_value_field) {
6576 MonoClass *dbnull_klass;
6577 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
6578 mono_class_init (dbnull_klass);
6579 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
6580 g_assert (dbnull_value_field);
6582 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
6583 g_assert (obj);
6584 return obj;
6587 static void
6588 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
6590 guint32 param_index, i, lastp, crow = 0;
6591 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
6592 gint32 idx;
6594 MonoClass *klass = method->klass;
6595 MonoImage *image = klass->image;
6596 MonoMethodSignature *methodsig = mono_method_signature (method);
6598 MonoTableInfo *constt;
6599 MonoTableInfo *methodt;
6600 MonoTableInfo *paramt;
6602 if (!methodsig->param_count)
6603 return;
6605 mono_class_init (klass);
6607 if (klass->image->dynamic) {
6608 MonoReflectionMethodAux *aux;
6609 if (method->is_inflated)
6610 method = ((MonoMethodInflated*)method)->declaring;
6611 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6612 if (aux && aux->param_defaults) {
6613 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
6614 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
6616 return;
6619 methodt = &klass->image->tables [MONO_TABLE_METHOD];
6620 paramt = &klass->image->tables [MONO_TABLE_PARAM];
6621 constt = &image->tables [MONO_TABLE_CONSTANT];
6623 idx = mono_method_get_index (method) - 1;
6624 g_assert (idx != -1);
6626 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
6627 if (idx + 1 < methodt->rows)
6628 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
6629 else
6630 lastp = paramt->rows + 1;
6632 for (i = param_index; i < lastp; ++i) {
6633 guint32 paramseq;
6635 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
6636 paramseq = param_cols [MONO_PARAM_SEQUENCE];
6638 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT)
6639 continue;
6641 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
6642 if (!crow) {
6643 continue;
6646 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
6647 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
6648 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
6651 return;
6654 static MonoObject *
6655 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
6657 void *retval;
6658 MonoClass *klass;
6659 MonoObject *object;
6660 MonoType *basetype = type;
6662 if (!blob)
6663 return NULL;
6665 klass = mono_class_from_mono_type (type);
6666 if (klass->valuetype) {
6667 object = mono_object_new (domain, klass);
6668 retval = ((gchar *) object + sizeof (MonoObject));
6669 if (klass->enumtype)
6670 basetype = klass->enum_basetype;
6671 } else {
6672 retval = &object;
6675 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
6676 return object;
6677 else
6678 return NULL;
6681 static int
6682 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
6683 int found_sep;
6684 char *s;
6686 memset (assembly, 0, sizeof (MonoAssemblyName));
6687 assembly->name = p;
6688 assembly->culture = "";
6689 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
6691 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
6692 p++;
6693 found_sep = 0;
6694 while (g_ascii_isspace (*p) || *p == ',') {
6695 *p++ = 0;
6696 found_sep = 1;
6697 continue;
6699 /* failed */
6700 if (!found_sep)
6701 return 1;
6702 while (*p) {
6703 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
6704 p += 8;
6705 assembly->major = strtoul (p, &s, 10);
6706 if (s == p || *s != '.')
6707 return 1;
6708 p = ++s;
6709 assembly->minor = strtoul (p, &s, 10);
6710 if (s == p || *s != '.')
6711 return 1;
6712 p = ++s;
6713 assembly->build = strtoul (p, &s, 10);
6714 if (s == p || *s != '.')
6715 return 1;
6716 p = ++s;
6717 assembly->revision = strtoul (p, &s, 10);
6718 if (s == p)
6719 return 1;
6720 p = s;
6721 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
6722 p += 8;
6723 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
6724 assembly->culture = "";
6725 p += 7;
6726 } else {
6727 assembly->culture = p;
6728 while (*p && *p != ',') {
6729 p++;
6732 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
6733 p += 15;
6734 if (strncmp (p, "null", 4) == 0) {
6735 p += 4;
6736 } else {
6737 int len;
6738 gchar *start = p;
6739 while (*p && *p != ',') {
6740 p++;
6742 len = (p - start + 1);
6743 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
6744 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
6745 g_strlcpy ((char*)assembly->public_key_token, start, len);
6747 } else {
6748 while (*p && *p != ',')
6749 p++;
6751 found_sep = 0;
6752 while (g_ascii_isspace (*p) || *p == ',') {
6753 *p++ = 0;
6754 found_sep = 1;
6755 continue;
6757 /* failed */
6758 if (!found_sep)
6759 return 1;
6762 return 0;
6766 * mono_reflection_parse_type:
6767 * @name: type name
6769 * Parse a type name as accepted by the GetType () method and output the info
6770 * extracted in the info structure.
6771 * the name param will be mangled, so, make a copy before passing it to this function.
6772 * The fields in info will be valid until the memory pointed to by name is valid.
6774 * See also mono_type_get_name () below.
6776 * Returns: 0 on parse error.
6778 static int
6779 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
6780 MonoTypeNameParse *info)
6782 char *start, *p, *w, *temp, *last_point, *startn;
6783 int in_modifiers = 0;
6784 int isbyref = 0, rank, arity = 0, i;
6786 start = p = w = name;
6788 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
6789 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
6790 info->name = info->name_space = NULL;
6791 info->nested = NULL;
6792 info->modifiers = NULL;
6793 info->type_arguments = NULL;
6795 /* last_point separates the namespace from the name */
6796 last_point = NULL;
6797 /* Skips spaces */
6798 while (*p == ' ') p++, start++, w++, name++;
6800 while (*p) {
6801 switch (*p) {
6802 case '+':
6803 *p = 0; /* NULL terminate the name */
6804 startn = p + 1;
6805 info->nested = g_list_append (info->nested, startn);
6806 /* we have parsed the nesting namespace + name */
6807 if (info->name)
6808 break;
6809 if (last_point) {
6810 info->name_space = start;
6811 *last_point = 0;
6812 info->name = last_point + 1;
6813 } else {
6814 info->name_space = (char *)"";
6815 info->name = start;
6817 break;
6818 case '.':
6819 last_point = p;
6820 break;
6821 case '\\':
6822 ++p;
6823 break;
6824 case '&':
6825 case '*':
6826 case '[':
6827 case ',':
6828 case ']':
6829 in_modifiers = 1;
6830 break;
6831 case '`':
6832 ++p;
6833 i = strtol (p, &temp, 10);
6834 arity += i;
6835 if (p == temp)
6836 return 0;
6837 p = temp-1;
6838 break;
6839 default:
6840 break;
6842 if (in_modifiers)
6843 break;
6844 // *w++ = *p++;
6845 p++;
6848 if (!info->name) {
6849 if (last_point) {
6850 info->name_space = start;
6851 *last_point = 0;
6852 info->name = last_point + 1;
6853 } else {
6854 info->name_space = (char *)"";
6855 info->name = start;
6858 while (*p) {
6859 switch (*p) {
6860 case '&':
6861 if (isbyref) /* only one level allowed by the spec */
6862 return 0;
6863 isbyref = 1;
6864 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
6865 *p++ = 0;
6866 break;
6867 case '*':
6868 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
6869 *p++ = 0;
6870 break;
6871 case '[':
6872 if (arity != 0) {
6873 *p++ = 0;
6874 info->type_arguments = g_ptr_array_new ();
6875 for (i = 0; i < arity; i++) {
6876 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
6877 gboolean fqname = FALSE;
6879 g_ptr_array_add (info->type_arguments, subinfo);
6881 if (*p == '[') {
6882 p++;
6883 fqname = TRUE;
6886 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
6887 return 0;
6889 if (fqname) {
6890 char *aname;
6892 if (*p != ',')
6893 return 0;
6894 *p++ = 0;
6896 aname = p;
6897 while (*p && (*p != ']'))
6898 p++;
6900 if (*p != ']')
6901 return 0;
6903 *p++ = 0;
6904 while (*aname) {
6905 if (g_ascii_isspace (*aname)) {
6906 ++aname;
6907 continue;
6909 break;
6911 if (!*aname ||
6912 !assembly_name_to_aname (&subinfo->assembly, aname))
6913 return 0;
6916 if (i + 1 < arity) {
6917 if (*p != ',')
6918 return 0;
6919 } else {
6920 if (*p != ']')
6921 return 0;
6923 *p++ = 0;
6926 arity = 0;
6927 break;
6929 rank = 1;
6930 *p++ = 0;
6931 while (*p) {
6932 if (*p == ']')
6933 break;
6934 if (*p == ',')
6935 rank++;
6936 else if (*p == '*') /* '*' means unknown lower bound */
6937 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
6938 else
6939 return 0;
6940 ++p;
6942 if (*p++ != ']')
6943 return 0;
6944 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
6945 break;
6946 case ']':
6947 if (is_recursed)
6948 goto end;
6949 return 0;
6950 case ',':
6951 if (is_recursed)
6952 goto end;
6953 *p++ = 0;
6954 while (*p) {
6955 if (g_ascii_isspace (*p)) {
6956 ++p;
6957 continue;
6959 break;
6961 if (!*p)
6962 return 0; /* missing assembly name */
6963 if (!assembly_name_to_aname (&info->assembly, p))
6964 return 0;
6965 break;
6966 default:
6967 return 0;
6969 if (info->assembly.name)
6970 break;
6972 // *w = 0; /* terminate class name */
6973 end:
6974 if (!info->name || !*info->name)
6975 return 0;
6976 if (endptr)
6977 *endptr = p;
6978 /* add other consistency checks */
6979 return 1;
6983 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
6985 return _mono_reflection_parse_type (name, NULL, FALSE, info);
6988 static MonoType*
6989 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
6991 gboolean type_resolve = FALSE;
6992 MonoType *type;
6993 MonoImage *rootimage = image;
6995 if (info->assembly.name) {
6996 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
6997 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
6999 * This could happen in the AOT compiler case when the search hook is not
7000 * installed.
7002 assembly = image->assembly;
7003 if (!assembly) {
7004 /* then we must load the assembly ourselve - see #60439 */
7005 assembly = mono_assembly_load (&info->assembly, NULL, NULL);
7006 if (!assembly)
7007 return NULL;
7009 image = assembly->image;
7010 } else if (!image) {
7011 image = mono_defaults.corlib;
7014 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7015 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7016 image = mono_defaults.corlib;
7017 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7020 return type;
7023 static MonoType*
7024 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7026 MonoClass *klass;
7027 GList *mod;
7028 int modval;
7029 gboolean bounded = FALSE;
7031 if (!image)
7032 image = mono_defaults.corlib;
7034 if (ignorecase)
7035 klass = mono_class_from_name_case (image, info->name_space, info->name);
7036 else
7037 klass = mono_class_from_name (image, info->name_space, info->name);
7038 if (!klass)
7039 return NULL;
7040 for (mod = info->nested; mod; mod = mod->next) {
7041 gpointer iter = NULL;
7042 MonoClass *parent;
7044 parent = klass;
7045 mono_class_init (parent);
7047 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7048 if (ignorecase) {
7049 if (g_strcasecmp (klass->name, mod->data) == 0)
7050 break;
7051 } else {
7052 if (strcmp (klass->name, mod->data) == 0)
7053 break;
7056 if (!klass)
7057 break;
7059 if (!klass)
7060 return NULL;
7061 mono_class_init (klass);
7063 if (info->type_arguments) {
7064 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7065 MonoReflectionType *the_type;
7066 MonoType *instance;
7067 int i;
7069 for (i = 0; i < info->type_arguments->len; i++) {
7070 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7072 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7073 if (!type_args [i]) {
7074 g_free (type_args);
7075 return NULL;
7079 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7081 instance = mono_reflection_bind_generic_parameters (
7082 the_type, info->type_arguments->len, type_args);
7084 g_free (type_args);
7085 if (!instance)
7086 return NULL;
7088 klass = mono_class_from_mono_type (instance);
7091 for (mod = info->modifiers; mod; mod = mod->next) {
7092 modval = GPOINTER_TO_UINT (mod->data);
7093 if (!modval) { /* byref: must be last modifier */
7094 return &klass->this_arg;
7095 } else if (modval == -1) {
7096 klass = mono_ptr_class_get (&klass->byval_arg);
7097 } else if (modval == -2) {
7098 bounded = TRUE;
7099 } else { /* array rank */
7100 klass = mono_bounded_array_class_get (klass, modval, bounded);
7102 mono_class_init (klass);
7105 return &klass->byval_arg;
7109 * mono_reflection_get_type:
7110 * @image: a metadata context
7111 * @info: type description structure
7112 * @ignorecase: flag for case-insensitive string compares
7113 * @type_resolve: whenever type resolve was already tried
7115 * Build a MonoType from the type description in @info.
7119 MonoType*
7120 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7121 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7124 static MonoType*
7125 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7127 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (mono_domain_get (), assembly);
7128 MonoType *type;
7129 int i;
7131 g_assert (assembly->dynamic);
7133 /* Enumerate all modules */
7135 type = NULL;
7136 if (abuilder->modules) {
7137 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7138 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7139 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7140 if (type)
7141 break;
7145 if (!type && abuilder->loaded_modules) {
7146 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7147 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7148 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7149 if (type)
7150 break;
7154 return type;
7157 MonoType*
7158 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7160 MonoType *type;
7161 MonoReflectionAssembly *assembly;
7162 GString *fullName;
7163 GList *mod;
7165 if (image && image->dynamic)
7166 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7167 else
7168 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7169 if (type)
7170 return type;
7171 if (!mono_domain_has_type_resolve (mono_domain_get ()))
7172 return NULL;
7174 if (type_resolve) {
7175 if (*type_resolve)
7176 return NULL;
7177 else
7178 *type_resolve = TRUE;
7181 /* Reconstruct the type name */
7182 fullName = g_string_new ("");
7183 if (info->name_space && (info->name_space [0] != '\0'))
7184 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7185 else
7186 g_string_printf (fullName, info->name);
7187 for (mod = info->nested; mod; mod = mod->next)
7188 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7190 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7191 if (assembly) {
7192 if (assembly->assembly->dynamic)
7193 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7194 else
7195 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
7196 info, ignorecase);
7198 g_string_free (fullName, TRUE);
7199 return type;
7202 void
7203 mono_reflection_free_type_info (MonoTypeNameParse *info)
7205 g_list_free (info->modifiers);
7206 g_list_free (info->nested);
7208 if (info->type_arguments) {
7209 int i;
7211 for (i = 0; i < info->type_arguments->len; i++) {
7212 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7214 mono_reflection_free_type_info (subinfo);
7215 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7216 g_free (subinfo);
7219 g_ptr_array_free (info->type_arguments, TRUE);
7224 * mono_reflection_type_from_name:
7225 * @name: type name.
7226 * @image: a metadata context (can be NULL).
7228 * Retrieves a MonoType from its @name. If the name is not fully qualified,
7229 * it defaults to get the type from @image or, if @image is NULL or loading
7230 * from it fails, uses corlib.
7233 MonoType*
7234 mono_reflection_type_from_name (char *name, MonoImage *image)
7236 MonoType *type = NULL;
7237 MonoTypeNameParse info;
7238 char *tmp;
7240 /* Make a copy since parse_type modifies its argument */
7241 tmp = g_strdup (name);
7243 /*g_print ("requested type %s\n", str);*/
7244 if (mono_reflection_parse_type (tmp, &info)) {
7245 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7248 g_free (tmp);
7249 mono_reflection_free_type_info (&info);
7250 return type;
7254 * mono_reflection_get_token:
7256 * Return the metadata token of OBJ which should be an object
7257 * representing a metadata element.
7259 guint32
7260 mono_reflection_get_token (MonoObject *obj)
7262 MonoClass *klass;
7263 guint32 token = 0;
7265 klass = obj->vtable->klass;
7267 if (strcmp (klass->name, "MethodBuilder") == 0) {
7268 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7270 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7271 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7272 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7274 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7275 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7276 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7278 /* Call mono_image_create_token so the object gets added to the tokens hash table */
7279 token = mono_image_create_token (((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image, obj, FALSE, TRUE);
7280 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7281 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7282 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7283 } else if (strcmp (klass->name, "MonoType") == 0) {
7284 MonoReflectionType *tb = (MonoReflectionType *)obj;
7285 token = mono_class_from_mono_type (tb->type)->type_token;
7286 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7287 strcmp (klass->name, "MonoMethod") == 0 ||
7288 strcmp (klass->name, "MonoGenericMethod") == 0 ||
7289 strcmp (klass->name, "MonoGenericCMethod") == 0) {
7290 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7291 if (m->method->is_inflated) {
7292 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7293 return inflated->declaring->token;
7294 } else {
7295 token = m->method->token;
7297 } else if (strcmp (klass->name, "MonoField") == 0) {
7298 MonoReflectionField *f = (MonoReflectionField*)obj;
7300 if (is_field_on_inst (f->field)) {
7301 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
7302 int field_index = f->field - dgclass->fields;
7303 MonoObject *obj;
7305 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
7306 obj = dgclass->field_objects [field_index];
7307 return mono_reflection_get_token (obj);
7309 token = mono_class_get_field_token (f->field);
7310 } else if (strcmp (klass->name, "MonoProperty") == 0) {
7311 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7313 token = mono_class_get_property_token (p->property);
7314 } else if (strcmp (klass->name, "MonoEvent") == 0) {
7315 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
7317 token = mono_class_get_event_token (p->event);
7318 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
7319 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7321 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7322 } else if (strcmp (klass->name, "Module") == 0) {
7323 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7325 token = m->token;
7326 } else if (strcmp (klass->name, "Assembly") == 0) {
7327 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7328 } else {
7329 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7330 MonoException *ex = mono_get_exception_not_implemented (msg);
7331 g_free (msg);
7332 mono_raise_exception (ex);
7335 return token;
7338 static void*
7339 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
7341 int slen, type = t->type;
7342 MonoClass *tklass = t->data.klass;
7344 handle_enum:
7345 switch (type) {
7346 case MONO_TYPE_U1:
7347 case MONO_TYPE_I1:
7348 case MONO_TYPE_BOOLEAN: {
7349 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7350 *bval = *p;
7351 *end = p + 1;
7352 return bval;
7354 case MONO_TYPE_CHAR:
7355 case MONO_TYPE_U2:
7356 case MONO_TYPE_I2: {
7357 guint16 *val = g_malloc (sizeof (guint16));
7358 *val = read16 (p);
7359 *end = p + 2;
7360 return val;
7362 #if SIZEOF_VOID_P == 4
7363 case MONO_TYPE_U:
7364 case MONO_TYPE_I:
7365 #endif
7366 case MONO_TYPE_R4:
7367 case MONO_TYPE_U4:
7368 case MONO_TYPE_I4: {
7369 guint32 *val = g_malloc (sizeof (guint32));
7370 *val = read32 (p);
7371 *end = p + 4;
7372 return val;
7374 #if SIZEOF_VOID_P == 8
7375 case MONO_TYPE_U: /* error out instead? this should probably not happen */
7376 case MONO_TYPE_I:
7377 #endif
7378 case MONO_TYPE_U8:
7379 case MONO_TYPE_I8: {
7380 guint64 *val = g_malloc (sizeof (guint64));
7381 *val = read64 (p);
7382 *end = p + 8;
7383 return val;
7385 case MONO_TYPE_R8: {
7386 double *val = g_malloc (sizeof (double));
7387 readr8 (p, val);
7388 *end = p + 8;
7389 return val;
7391 case MONO_TYPE_VALUETYPE:
7392 if (t->data.klass->enumtype) {
7393 type = t->data.klass->enum_basetype->type;
7394 goto handle_enum;
7395 } else {
7396 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7398 break;
7399 case MONO_TYPE_STRING:
7400 if (*p == (char)0xFF) {
7401 *end = p + 1;
7402 return NULL;
7404 slen = mono_metadata_decode_value (p, &p);
7405 *end = p + slen;
7406 return mono_string_new_len (mono_domain_get (), p, slen);
7407 case MONO_TYPE_CLASS: {
7408 char *n;
7409 MonoType *t;
7410 if (*p == (char)0xFF) {
7411 *end = p + 1;
7412 return NULL;
7414 handle_type:
7415 slen = mono_metadata_decode_value (p, &p);
7416 n = g_memdup (p, slen + 1);
7417 n [slen] = 0;
7418 t = mono_reflection_type_from_name (n, image);
7419 if (!t)
7420 g_warning ("Cannot load type '%s'", n);
7421 g_free (n);
7422 *end = p + slen;
7423 if (t)
7424 return mono_type_get_object (mono_domain_get (), t);
7425 else
7426 return NULL;
7428 case MONO_TYPE_OBJECT: {
7429 char subt = *p++;
7430 MonoObject *obj;
7431 MonoClass *subc = NULL;
7432 void *val;
7434 if (subt == 0x50) {
7435 goto handle_type;
7436 } else if (subt == 0x0E) {
7437 type = MONO_TYPE_STRING;
7438 goto handle_enum;
7439 } else if (subt == 0x1D) {
7440 MonoType simple_type = {{0}};
7441 int etype = *p;
7442 p ++;
7444 if (etype == 0x51)
7445 /* See Partition II, Appendix B3 */
7446 etype = MONO_TYPE_OBJECT;
7447 type = MONO_TYPE_SZARRAY;
7448 simple_type.type = etype;
7449 tklass = mono_class_from_mono_type (&simple_type);
7450 goto handle_enum;
7451 } else if (subt == 0x55) {
7452 char *n;
7453 MonoType *t;
7454 slen = mono_metadata_decode_value (p, &p);
7455 n = g_memdup (p, slen + 1);
7456 n [slen] = 0;
7457 t = mono_reflection_type_from_name (n, image);
7458 if (!t)
7459 g_error ("Cannot load type '%s'", n);
7460 g_free (n);
7461 p += slen;
7462 subc = mono_class_from_mono_type (t);
7463 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
7464 MonoType simple_type = {{0}};
7465 simple_type.type = subt;
7466 subc = mono_class_from_mono_type (&simple_type);
7467 } else {
7468 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
7470 val = load_cattr_value (image, &subc->byval_arg, p, end);
7471 obj = mono_object_new (mono_domain_get (), subc);
7472 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
7473 g_free (val);
7474 return obj;
7476 case MONO_TYPE_SZARRAY: {
7477 MonoArray *arr;
7478 guint32 i, alen, basetype;
7479 alen = read32 (p);
7480 p += 4;
7481 if (alen == 0xffffffff) {
7482 *end = p;
7483 return NULL;
7485 arr = mono_array_new (mono_domain_get(), tklass, alen);
7486 basetype = tklass->byval_arg.type;
7487 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
7488 basetype = tklass->enum_basetype->type;
7489 switch (basetype)
7491 case MONO_TYPE_U1:
7492 case MONO_TYPE_I1:
7493 case MONO_TYPE_BOOLEAN:
7494 for (i = 0; i < alen; i++) {
7495 MonoBoolean val = *p++;
7496 mono_array_set (arr, MonoBoolean, i, val);
7498 break;
7499 case MONO_TYPE_CHAR:
7500 case MONO_TYPE_U2:
7501 case MONO_TYPE_I2:
7502 for (i = 0; i < alen; i++) {
7503 guint16 val = read16 (p);
7504 mono_array_set (arr, guint16, i, val);
7505 p += 2;
7507 break;
7508 case MONO_TYPE_R4:
7509 case MONO_TYPE_U4:
7510 case MONO_TYPE_I4:
7511 for (i = 0; i < alen; i++) {
7512 guint32 val = read32 (p);
7513 mono_array_set (arr, guint32, i, val);
7514 p += 4;
7516 break;
7517 case MONO_TYPE_R8:
7518 for (i = 0; i < alen; i++) {
7519 double val;
7520 readr8 (p, &val);
7521 mono_array_set (arr, double, i, val);
7522 p += 8;
7524 break;
7525 case MONO_TYPE_U8:
7526 case MONO_TYPE_I8:
7527 for (i = 0; i < alen; i++) {
7528 guint64 val = read64 (p);
7529 mono_array_set (arr, guint64, i, val);
7530 p += 8;
7532 break;
7533 case MONO_TYPE_CLASS:
7534 case MONO_TYPE_OBJECT:
7535 case MONO_TYPE_STRING:
7536 for (i = 0; i < alen; i++) {
7537 MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
7538 mono_array_setref (arr, i, item);
7540 break;
7541 default:
7542 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
7544 *end=p;
7545 return arr;
7547 default:
7548 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
7550 return NULL;
7553 static MonoObject*
7554 create_cattr_typed_arg (MonoType *t, MonoObject *val)
7556 static MonoClass *klass;
7557 static MonoMethod *ctor;
7558 MonoObject *retval;
7559 void *params [2], *unboxed;
7561 if (!klass)
7562 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
7563 if (!ctor)
7564 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7566 params [0] = mono_type_get_object (mono_domain_get (), t);
7567 params [1] = val;
7568 retval = mono_object_new (mono_domain_get (), klass);
7569 unboxed = mono_object_unbox (retval);
7570 mono_runtime_invoke (ctor, unboxed, params, NULL);
7572 return retval;
7575 static MonoObject*
7576 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
7578 static MonoClass *klass;
7579 static MonoMethod *ctor;
7580 MonoObject *retval;
7581 void *unboxed, *params [2];
7583 if (!klass)
7584 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
7585 if (!ctor)
7586 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7588 params [0] = minfo;
7589 params [1] = typedarg;
7590 retval = mono_object_new (mono_domain_get (), klass);
7591 unboxed = mono_object_unbox (retval);
7592 mono_runtime_invoke (ctor, unboxed, params, NULL);
7594 return retval;
7597 static gboolean
7598 type_is_reference (MonoType *type)
7600 switch (type->type) {
7601 case MONO_TYPE_BOOLEAN:
7602 case MONO_TYPE_CHAR:
7603 case MONO_TYPE_U:
7604 case MONO_TYPE_I:
7605 case MONO_TYPE_U1:
7606 case MONO_TYPE_I1:
7607 case MONO_TYPE_U2:
7608 case MONO_TYPE_I2:
7609 case MONO_TYPE_U4:
7610 case MONO_TYPE_I4:
7611 case MONO_TYPE_U8:
7612 case MONO_TYPE_I8:
7613 case MONO_TYPE_R8:
7614 case MONO_TYPE_R4:
7615 case MONO_TYPE_VALUETYPE:
7616 return FALSE;
7617 default:
7618 return TRUE;
7622 static void
7623 free_param_data (MonoMethodSignature *sig, void **params) {
7624 int i;
7625 for (i = 0; i < sig->param_count; ++i) {
7626 if (!type_is_reference (sig->params [i]))
7627 g_free (params [i]);
7632 * Find the field index in the metadata FieldDef table.
7634 static guint32
7635 find_field_index (MonoClass *klass, MonoClassField *field) {
7636 int i;
7638 for (i = 0; i < klass->field.count; ++i) {
7639 if (field == &klass->fields [i])
7640 return klass->field.first + 1 + i;
7642 return 0;
7646 * Find the property index in the metadata Property table.
7648 static guint32
7649 find_property_index (MonoClass *klass, MonoProperty *property) {
7650 int i;
7652 for (i = 0; i < klass->property.count; ++i) {
7653 if (property == &klass->properties [i])
7654 return klass->property.first + 1 + i;
7656 return 0;
7660 * Find the event index in the metadata Event table.
7662 static guint32
7663 find_event_index (MonoClass *klass, MonoEvent *event) {
7664 int i;
7666 for (i = 0; i < klass->event.count; ++i) {
7667 if (event == &klass->events [i])
7668 return klass->event.first + 1 + i;
7670 return 0;
7673 static MonoObject*
7674 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7676 const char *p = (const char*)data;
7677 const char *named;
7678 guint32 i, j, num_named;
7679 MonoObject *attr;
7680 void **params;
7682 mono_class_init (method->klass);
7684 if (len == 0) {
7685 attr = mono_object_new (mono_domain_get (), method->klass);
7686 mono_runtime_invoke (method, attr, NULL, NULL);
7687 return attr;
7690 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7691 return NULL;
7693 /*g_print ("got attr %s\n", method->klass->name);*/
7695 /* Allocate using alloca so it gets GC tracking */
7696 params = alloca (mono_method_signature (method)->param_count * sizeof (void*));
7698 /* skip prolog */
7699 p += 2;
7700 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7701 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7704 named = p;
7705 attr = mono_object_new (mono_domain_get (), method->klass);
7706 mono_runtime_invoke (method, attr, params, NULL);
7707 free_param_data (method->signature, params);
7708 num_named = read16 (named);
7709 named += 2;
7710 for (j = 0; j < num_named; j++) {
7711 gint name_len;
7712 char *name, named_type, data_type;
7713 named_type = *named++;
7714 data_type = *named++; /* type of data */
7715 if (data_type == MONO_TYPE_SZARRAY)
7716 data_type = *named++;
7717 if (data_type == MONO_TYPE_ENUM) {
7718 gint type_len;
7719 char *type_name;
7720 type_len = mono_metadata_decode_blob_size (named, &named);
7721 type_name = g_malloc (type_len + 1);
7722 memcpy (type_name, named, type_len);
7723 type_name [type_len] = 0;
7724 named += type_len;
7725 /* FIXME: lookup the type and check type consistency */
7726 g_free (type_name);
7728 name_len = mono_metadata_decode_blob_size (named, &named);
7729 name = g_malloc (name_len + 1);
7730 memcpy (name, named, name_len);
7731 name [name_len] = 0;
7732 named += name_len;
7733 if (named_type == 0x53) {
7734 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
7735 void *val = load_cattr_value (image, field->type, named, &named);
7736 mono_field_set_value (attr, field, val);
7737 if (!type_is_reference (field->type))
7738 g_free (val);
7739 } else if (named_type == 0x54) {
7740 MonoProperty *prop;
7741 void *pparams [1];
7742 MonoType *prop_type;
7744 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
7745 /* can we have more that 1 arg in a custom attr named property? */
7746 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7747 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7748 pparams [0] = load_cattr_value (image, prop_type, named, &named);
7749 mono_property_set_value (prop, attr, pparams, NULL);
7750 if (!type_is_reference (prop_type))
7751 g_free (pparams [0]);
7753 g_free (name);
7756 return attr;
7759 static MonoObject*
7760 create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7762 MonoArray *typedargs, *namedargs;
7763 MonoClass *attrklass;
7764 static MonoMethod *ctor;
7765 MonoDomain *domain;
7766 MonoObject *attr;
7767 const char *p = (const char*)data;
7768 const char *named;
7769 guint32 i, j, num_named;
7770 void *params [3];
7772 mono_class_init (method->klass);
7774 if (!ctor)
7775 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 3);
7777 domain = mono_domain_get ();
7778 if (len == 0) {
7779 /* This is for Attributes with no parameters */
7780 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
7781 params [0] = mono_method_get_object (domain, method, NULL);
7782 params [1] = params [2] = NULL;
7783 mono_runtime_invoke (method, attr, params, NULL);
7784 return attr;
7787 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7788 return NULL;
7790 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
7792 /* skip prolog */
7793 p += 2;
7794 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7795 MonoObject *obj, *typedarg;
7796 void *val;
7798 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7799 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
7800 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
7801 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
7802 mono_array_setref (typedargs, i, typedarg);
7804 if (!type_is_reference (mono_method_signature (method)->params [i]))
7805 g_free (val);
7808 named = p;
7809 num_named = read16 (named);
7810 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
7811 named += 2;
7812 attrklass = method->klass;
7813 for (j = 0; j < num_named; j++) {
7814 gint name_len;
7815 char *name, named_type, data_type;
7816 named_type = *named++;
7817 data_type = *named++; /* type of data */
7818 if (data_type == MONO_TYPE_SZARRAY)
7819 data_type = *named++;
7820 if (data_type == MONO_TYPE_ENUM) {
7821 gint type_len;
7822 char *type_name;
7823 type_len = mono_metadata_decode_blob_size (named, &named);
7824 type_name = g_malloc (type_len + 1);
7825 memcpy (type_name, named, type_len);
7826 type_name [type_len] = 0;
7827 named += type_len;
7828 /* FIXME: lookup the type and check type consistency */
7829 g_free (type_name);
7831 name_len = mono_metadata_decode_blob_size (named, &named);
7832 name = g_malloc (name_len + 1);
7833 memcpy (name, named, name_len);
7834 name [name_len] = 0;
7835 named += name_len;
7836 if (named_type == 0x53) {
7837 MonoObject *obj, *typedarg, *namedarg;
7838 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
7839 void *minfo, *val = load_cattr_value (image, field->type, named, &named);
7841 minfo = mono_field_get_object (domain, NULL, field);
7842 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
7843 typedarg = create_cattr_typed_arg (field->type, obj);
7844 namedarg = create_cattr_named_arg (minfo, typedarg);
7845 mono_array_setref (namedargs, j, namedarg);
7846 if (!type_is_reference (field->type))
7847 g_free (val);
7848 } else if (named_type == 0x54) {
7849 MonoObject *obj, *typedarg, *namedarg;
7850 MonoType *prop_type;
7851 void *val, *minfo;
7852 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
7854 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7855 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7856 minfo = mono_property_get_object (domain, NULL, prop);
7857 val = load_cattr_value (image, prop_type, named, &named);
7858 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
7859 typedarg = create_cattr_typed_arg (prop_type, obj);
7860 namedarg = create_cattr_named_arg (minfo, typedarg);
7861 mono_array_setref (namedargs, j, namedarg);
7862 if (!type_is_reference (prop_type))
7863 g_free (val);
7865 g_free (name);
7867 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
7868 params [0] = mono_method_get_object (domain, method, NULL);
7869 params [1] = typedargs;
7870 params [2] = namedargs;
7871 mono_runtime_invoke (ctor, attr, params, NULL);
7872 return attr;
7875 MonoArray*
7876 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
7878 MonoArray *result;
7879 MonoObject *attr;
7880 int i;
7882 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, cinfo->num_attrs);
7883 for (i = 0; i < cinfo->num_attrs; ++i) {
7884 if (!cinfo->attrs [i].ctor)
7885 /* The cattr type is not finished yet */
7886 /* We should include the type name but cinfo doesn't contain it */
7887 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
7888 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7889 mono_array_setref (result, i, attr);
7891 return result;
7894 static MonoArray*
7895 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass)
7897 MonoArray *result;
7898 MonoObject *attr;
7899 int i, n;
7901 n = 0;
7902 for (i = 0; i < cinfo->num_attrs; ++i) {
7903 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
7904 n ++;
7907 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, n);
7908 n = 0;
7909 for (i = 0; i < cinfo->num_attrs; ++i) {
7910 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
7911 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7912 mono_array_setref (result, n, attr);
7913 n ++;
7916 return result;
7919 static MonoArray*
7920 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
7922 MonoArray *result;
7923 MonoObject *attr;
7924 int i;
7926 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
7927 for (i = 0; i < cinfo->num_attrs; ++i) {
7928 attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7929 mono_array_setref (result, i, attr);
7931 return result;
7935 * mono_custom_attrs_from_index:
7937 * Returns: NULL if no attributes are found or if a loading error occurs.
7939 MonoCustomAttrInfo*
7940 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
7942 guint32 mtoken, i, len;
7943 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
7944 MonoTableInfo *ca;
7945 MonoCustomAttrInfo *ainfo;
7946 GList *tmp, *list = NULL;
7947 const char *data;
7949 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
7951 i = mono_metadata_custom_attrs_from_index (image, idx);
7952 if (!i)
7953 return NULL;
7954 i --;
7955 while (i < ca->rows) {
7956 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
7957 break;
7958 list = g_list_prepend (list, GUINT_TO_POINTER (i));
7959 ++i;
7961 len = g_list_length (list);
7962 if (!len)
7963 return NULL;
7964 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
7965 ainfo->num_attrs = len;
7966 ainfo->image = image;
7967 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
7968 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
7969 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
7970 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
7971 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
7972 mtoken |= MONO_TOKEN_METHOD_DEF;
7973 break;
7974 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
7975 mtoken |= MONO_TOKEN_MEMBER_REF;
7976 break;
7977 default:
7978 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
7979 break;
7981 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
7982 if (!ainfo->attrs [i].ctor) {
7983 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
7984 g_list_free (list);
7985 g_free (ainfo);
7986 return NULL;
7988 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
7989 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
7990 ainfo->attrs [i].data = (guchar*)data;
7992 g_list_free (list);
7994 return ainfo;
7997 MonoCustomAttrInfo*
7998 mono_custom_attrs_from_method (MonoMethod *method)
8000 guint32 idx;
8003 * An instantiated method has the same cattrs as the generic method definition.
8005 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8006 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8008 if (method->is_inflated)
8009 method = ((MonoMethodInflated *) method)->declaring;
8011 if (method->dynamic || method->klass->image->dynamic)
8012 return lookup_custom_attr (method->klass->image, method);
8014 idx = mono_method_get_index (method);
8015 idx <<= MONO_CUSTOM_ATTR_BITS;
8016 idx |= MONO_CUSTOM_ATTR_METHODDEF;
8017 return mono_custom_attrs_from_index (method->klass->image, idx);
8020 MonoCustomAttrInfo*
8021 mono_custom_attrs_from_class (MonoClass *klass)
8023 guint32 idx;
8025 if (klass->generic_class)
8026 klass = klass->generic_class->container_class;
8028 if (klass->image->dynamic)
8029 return lookup_custom_attr (klass->image, klass);
8031 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
8032 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
8033 idx <<= MONO_CUSTOM_ATTR_BITS;
8034 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
8035 } else {
8036 idx = mono_metadata_token_index (klass->type_token);
8037 idx <<= MONO_CUSTOM_ATTR_BITS;
8038 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
8040 return mono_custom_attrs_from_index (klass->image, idx);
8043 MonoCustomAttrInfo*
8044 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
8046 guint32 idx;
8048 if (assembly->image->dynamic)
8049 return lookup_custom_attr (assembly->image, assembly);
8050 idx = 1; /* there is only one assembly */
8051 idx <<= MONO_CUSTOM_ATTR_BITS;
8052 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
8053 return mono_custom_attrs_from_index (assembly->image, idx);
8056 static MonoCustomAttrInfo*
8057 mono_custom_attrs_from_module (MonoImage *image)
8059 guint32 idx;
8061 if (image->dynamic)
8062 return lookup_custom_attr (image, image);
8063 idx = 1; /* there is only one module */
8064 idx <<= MONO_CUSTOM_ATTR_BITS;
8065 idx |= MONO_CUSTOM_ATTR_MODULE;
8066 return mono_custom_attrs_from_index (image, idx);
8069 MonoCustomAttrInfo*
8070 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
8072 guint32 idx;
8074 if (klass->image->dynamic) {
8075 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
8076 return lookup_custom_attr (klass->image, property);
8078 idx = find_property_index (klass, property);
8079 idx <<= MONO_CUSTOM_ATTR_BITS;
8080 idx |= MONO_CUSTOM_ATTR_PROPERTY;
8081 return mono_custom_attrs_from_index (klass->image, idx);
8084 MonoCustomAttrInfo*
8085 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
8087 guint32 idx;
8089 if (klass->image->dynamic) {
8090 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
8091 return lookup_custom_attr (klass->image, event);
8093 idx = find_event_index (klass, event);
8094 idx <<= MONO_CUSTOM_ATTR_BITS;
8095 idx |= MONO_CUSTOM_ATTR_EVENT;
8096 return mono_custom_attrs_from_index (klass->image, idx);
8099 MonoCustomAttrInfo*
8100 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
8102 guint32 idx;
8103 if (klass->image->dynamic) {
8104 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
8105 return lookup_custom_attr (klass->image, field);
8107 idx = find_field_index (klass, field);
8108 idx <<= MONO_CUSTOM_ATTR_BITS;
8109 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
8110 return mono_custom_attrs_from_index (klass->image, idx);
8113 MonoCustomAttrInfo*
8114 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
8116 MonoTableInfo *ca;
8117 guint32 i, idx, method_index;
8118 guint32 param_list, param_last, param_pos, found;
8119 MonoImage *image;
8120 MonoReflectionMethodAux *aux;
8123 * An instantiated method has the same cattrs as the generic method definition.
8125 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8126 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8128 if (method->is_inflated)
8129 method = ((MonoMethodInflated *) method)->declaring;
8131 if (method->klass->image->dynamic) {
8132 MonoCustomAttrInfo *res, *ainfo;
8133 int size;
8135 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8136 if (!aux || !aux->param_cattr)
8137 return NULL;
8139 /* Need to copy since it will be freed later */
8140 ainfo = aux->param_cattr [param];
8141 size = sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (ainfo->num_attrs - MONO_ZERO_LEN_ARRAY);
8142 res = g_malloc0 (size);
8143 memcpy (res, ainfo, size);
8144 return res;
8147 image = method->klass->image;
8148 method_index = mono_method_get_index (method);
8149 ca = &image->tables [MONO_TABLE_METHOD];
8151 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
8152 if (method_index == ca->rows) {
8153 ca = &image->tables [MONO_TABLE_PARAM];
8154 param_last = ca->rows + 1;
8155 } else {
8156 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
8157 ca = &image->tables [MONO_TABLE_PARAM];
8159 found = FALSE;
8160 for (i = param_list; i < param_last; ++i) {
8161 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
8162 if (param_pos == param) {
8163 found = TRUE;
8164 break;
8167 if (!found)
8168 return NULL;
8169 idx = i;
8170 idx <<= MONO_CUSTOM_ATTR_BITS;
8171 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
8172 return mono_custom_attrs_from_index (image, idx);
8175 gboolean
8176 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8178 int i;
8179 MonoClass *klass;
8180 for (i = 0; i < ainfo->num_attrs; ++i) {
8181 klass = ainfo->attrs [i].ctor->klass;
8182 if (mono_class_has_parent (klass, attr_klass))
8183 return TRUE;
8185 return FALSE;
8188 MonoObject*
8189 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8191 int i, attr_index;
8192 MonoClass *klass;
8193 MonoArray *attrs;
8195 attr_index = -1;
8196 for (i = 0; i < ainfo->num_attrs; ++i) {
8197 klass = ainfo->attrs [i].ctor->klass;
8198 if (mono_class_has_parent (klass, attr_klass)) {
8199 attr_index = i;
8200 break;
8203 if (attr_index == -1)
8204 return NULL;
8206 attrs = mono_custom_attrs_construct (ainfo);
8207 if (attrs)
8208 return mono_array_get (attrs, MonoObject*, attr_index);
8209 else
8210 return NULL;
8214 * mono_reflection_get_custom_attrs_info:
8215 * @obj: a reflection object handle
8217 * Return the custom attribute info for attributes defined for the
8218 * reflection handle @obj. The objects.
8220 MonoCustomAttrInfo*
8221 mono_reflection_get_custom_attrs_info (MonoObject *obj)
8223 MonoClass *klass;
8224 MonoCustomAttrInfo *cinfo = NULL;
8226 klass = obj->vtable->klass;
8227 if (klass == mono_defaults.monotype_class) {
8228 MonoReflectionType *rtype = (MonoReflectionType*)obj;
8229 klass = mono_class_from_mono_type (rtype->type);
8230 cinfo = mono_custom_attrs_from_class (klass);
8231 } else if (strcmp ("Assembly", klass->name) == 0) {
8232 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
8233 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
8234 } else if (strcmp ("Module", klass->name) == 0) {
8235 MonoReflectionModule *module = (MonoReflectionModule*)obj;
8236 cinfo = mono_custom_attrs_from_module (module->image);
8237 } else if (strcmp ("MonoProperty", klass->name) == 0) {
8238 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
8239 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
8240 } else if (strcmp ("MonoEvent", klass->name) == 0) {
8241 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
8242 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
8243 } else if (strcmp ("MonoField", klass->name) == 0) {
8244 MonoReflectionField *rfield = (MonoReflectionField*)obj;
8245 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
8246 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
8247 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8248 cinfo = mono_custom_attrs_from_method (rmethod->method);
8249 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
8250 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8251 cinfo = mono_custom_attrs_from_method (rmethod->method);
8252 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
8253 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
8254 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8255 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
8256 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
8257 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
8258 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
8259 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
8260 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8261 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
8262 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
8263 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
8264 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
8265 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
8266 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8267 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
8268 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
8269 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8270 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
8271 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
8272 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8273 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
8274 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
8275 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
8276 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
8277 } else { /* handle other types here... */
8278 g_error ("get custom attrs not yet supported for %s", klass->name);
8281 return cinfo;
8285 * mono_reflection_get_custom_attrs_by_type:
8286 * @obj: a reflection object handle
8288 * Return an array with all the custom attributes defined of the
8289 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
8290 * of that type are returned. The objects are fully build. Return NULL if a loading error
8291 * occurs.
8293 MonoArray*
8294 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass)
8296 MonoArray *result;
8297 MonoCustomAttrInfo *cinfo;
8299 cinfo = mono_reflection_get_custom_attrs_info (obj);
8300 if (cinfo) {
8301 if (attr_klass)
8302 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass);
8303 else
8304 result = mono_custom_attrs_construct (cinfo);
8305 if (!cinfo->cached)
8306 mono_custom_attrs_free (cinfo);
8307 } else {
8308 if (mono_loader_get_last_error ())
8309 return NULL;
8310 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, 0);
8313 return result;
8317 * mono_reflection_get_custom_attrs:
8318 * @obj: a reflection object handle
8320 * Return an array with all the custom attributes defined of the
8321 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
8322 * occurs.
8324 MonoArray*
8325 mono_reflection_get_custom_attrs (MonoObject *obj)
8327 return mono_reflection_get_custom_attrs_by_type (obj, NULL);
8331 * mono_reflection_get_custom_attrs_data:
8332 * @obj: a reflection obj handle
8334 * Returns an array of System.Reflection.CustomAttributeData,
8335 * which include information about attributes reflected on
8336 * types loaded using the Reflection Only methods
8338 MonoArray*
8339 mono_reflection_get_custom_attrs_data (MonoObject *obj)
8341 MonoArray *result;
8342 MonoCustomAttrInfo *cinfo;
8344 cinfo = mono_reflection_get_custom_attrs_info (obj);
8345 if (cinfo) {
8346 result = mono_custom_attrs_data_construct (cinfo);
8347 if (!cinfo->cached)
8348 mono_custom_attrs_free (cinfo);
8349 } else
8350 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
8352 return result;
8355 static MonoReflectionType*
8356 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
8358 MonoMethod *method_get_underlying_system_type;
8360 method_get_underlying_system_type = mono_object_get_virtual_method ((MonoObject *) t,
8361 mono_class_get_method_from_name (mono_object_class (t),
8362 "get_UnderlyingSystemType",
8363 0));
8364 return (MonoReflectionType *) mono_runtime_invoke (method_get_underlying_system_type, t, NULL, NULL);
8367 static MonoType*
8368 mono_reflection_type_get_handle (MonoReflectionType* t)
8370 if (t->type)
8371 return t->type;
8373 t = mono_reflection_type_get_underlying_system_type (t);
8374 if (t)
8375 return t->type;
8377 return NULL;
8381 * LOCKING: Assumes the loader lock is held.
8383 static MonoMethodSignature*
8384 parameters_to_signature (MonoMemPool *mp, MonoArray *parameters) {
8385 MonoMethodSignature *sig;
8386 int count, i;
8388 count = parameters? mono_array_length (parameters): 0;
8390 sig = mp_g_malloc0 (mp, sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
8391 sig->param_count = count;
8392 sig->sentinelpos = -1; /* FIXME */
8393 for (i = 0; i < count; ++i) {
8394 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
8395 sig->params [i] = mono_reflection_type_get_handle (pt);
8397 return sig;
8401 * LOCKING: Assumes the loader lock is held.
8403 static MonoMethodSignature*
8404 ctor_builder_to_signature (MonoMemPool *mp, MonoReflectionCtorBuilder *ctor) {
8405 MonoMethodSignature *sig;
8407 sig = parameters_to_signature (mp, ctor->parameters);
8408 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8409 sig->ret = &mono_defaults.void_class->byval_arg;
8410 return sig;
8414 * LOCKING: Assumes the loader lock is held.
8416 static MonoMethodSignature*
8417 method_builder_to_signature (MonoMemPool *mp, MonoReflectionMethodBuilder *method) {
8418 MonoMethodSignature *sig;
8420 sig = parameters_to_signature (mp, method->parameters);
8421 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8422 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
8423 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
8424 return sig;
8427 static MonoMethodSignature*
8428 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
8429 MonoMethodSignature *sig;
8431 sig = parameters_to_signature (NULL, method->parameters);
8432 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8433 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
8434 sig->generic_param_count = 0;
8435 return sig;
8438 static void
8439 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
8441 MonoClass *klass = mono_object_class (prop);
8442 if (strcmp (klass->name, "PropertyBuilder") == 0) {
8443 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
8444 *name = mono_string_to_utf8 (pb->name);
8445 *type = pb->type->type;
8446 } else {
8447 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
8448 *name = g_strdup (p->property->name);
8449 if (p->property->get)
8450 *type = mono_method_signature (p->property->get)->ret;
8451 else
8452 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
8456 static void
8457 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
8459 MonoClass *klass = mono_object_class (field);
8460 if (strcmp (klass->name, "FieldBuilder") == 0) {
8461 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
8462 *name = mono_string_to_utf8 (fb->name);
8463 *type = fb->type->type;
8464 } else {
8465 MonoReflectionField *f = (MonoReflectionField *)field;
8466 *name = g_strdup (mono_field_get_name (f->field));
8467 *type = f->field->type;
8472 * Encode a value in a custom attribute stream of bytes.
8473 * The value to encode is either supplied as an object in argument val
8474 * (valuetypes are boxed), or as a pointer to the data in the
8475 * argument argval.
8476 * @type represents the type of the value
8477 * @buffer is the start of the buffer
8478 * @p the current position in the buffer
8479 * @buflen contains the size of the buffer and is used to return the new buffer size
8480 * if this needs to be realloced.
8481 * @retbuffer and @retp return the start and the position of the buffer
8483 static void
8484 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
8486 MonoTypeEnum simple_type;
8488 if ((p-buffer) + 10 >= *buflen) {
8489 char *newbuf;
8490 *buflen *= 2;
8491 newbuf = g_realloc (buffer, *buflen);
8492 p = newbuf + (p-buffer);
8493 buffer = newbuf;
8495 if (!argval)
8496 argval = ((char*)arg + sizeof (MonoObject));
8497 simple_type = type->type;
8498 handle_enum:
8499 switch (simple_type) {
8500 case MONO_TYPE_BOOLEAN:
8501 case MONO_TYPE_U1:
8502 case MONO_TYPE_I1:
8503 *p++ = *argval;
8504 break;
8505 case MONO_TYPE_CHAR:
8506 case MONO_TYPE_U2:
8507 case MONO_TYPE_I2:
8508 swap_with_size (p, argval, 2, 1);
8509 p += 2;
8510 break;
8511 case MONO_TYPE_U4:
8512 case MONO_TYPE_I4:
8513 case MONO_TYPE_R4:
8514 swap_with_size (p, argval, 4, 1);
8515 p += 4;
8516 break;
8517 case MONO_TYPE_R8:
8518 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
8519 p [0] = argval [4];
8520 p [1] = argval [5];
8521 p [2] = argval [6];
8522 p [3] = argval [7];
8523 p [4] = argval [0];
8524 p [5] = argval [1];
8525 p [6] = argval [2];
8526 p [7] = argval [3];
8527 #else
8528 swap_with_size (p, argval, 8, 1);
8529 #endif
8530 p += 8;
8531 break;
8532 case MONO_TYPE_U8:
8533 case MONO_TYPE_I8:
8534 swap_with_size (p, argval, 8, 1);
8535 p += 8;
8536 break;
8537 case MONO_TYPE_VALUETYPE:
8538 if (type->data.klass->enumtype) {
8539 simple_type = type->data.klass->enum_basetype->type;
8540 goto handle_enum;
8541 } else {
8542 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
8544 break;
8545 case MONO_TYPE_STRING: {
8546 char *str;
8547 guint32 slen;
8548 if (!arg) {
8549 *p++ = 0xFF;
8550 break;
8552 str = mono_string_to_utf8 ((MonoString*)arg);
8553 slen = strlen (str);
8554 if ((p-buffer) + 10 + slen >= *buflen) {
8555 char *newbuf;
8556 *buflen *= 2;
8557 *buflen += slen;
8558 newbuf = g_realloc (buffer, *buflen);
8559 p = newbuf + (p-buffer);
8560 buffer = newbuf;
8562 mono_metadata_encode_value (slen, p, &p);
8563 memcpy (p, str, slen);
8564 p += slen;
8565 g_free (str);
8566 break;
8568 case MONO_TYPE_CLASS: {
8569 char *str;
8570 guint32 slen;
8571 MonoClass *k;
8572 if (!arg) {
8573 *p++ = 0xFF;
8574 break;
8576 k = mono_object_class (arg);
8577 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
8578 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit"))) {
8579 MonoReflectionType* rt = mono_reflection_type_get_underlying_system_type ((MonoReflectionType*) arg);
8580 MonoClass *rtc;
8582 if (rt && (rtc = mono_object_class (rt)) &&
8583 (mono_object_isinst ((MonoObject *) rt, mono_defaults.monotype_class) ||
8584 !strcmp (rtc->name, "TypeBuilder") || !strcmp (rtc->name_space, "System.Reflection.Emit"))) {
8585 arg = (MonoObject *) rt;
8586 k = rtc;
8587 } else
8588 g_error ("Only System.Type allowed, not %s.%s", k->name_space, k->name);
8590 handle_type:
8591 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
8592 slen = strlen (str);
8593 if ((p-buffer) + 10 + slen >= *buflen) {
8594 char *newbuf;
8595 *buflen *= 2;
8596 *buflen += slen;
8597 newbuf = g_realloc (buffer, *buflen);
8598 p = newbuf + (p-buffer);
8599 buffer = newbuf;
8601 mono_metadata_encode_value (slen, p, &p);
8602 memcpy (p, str, slen);
8603 p += slen;
8604 g_free (str);
8605 break;
8607 case MONO_TYPE_SZARRAY: {
8608 int len, i;
8609 MonoClass *eclass, *arg_eclass;
8611 if (!arg) {
8612 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
8613 break;
8615 len = mono_array_length ((MonoArray*)arg);
8616 *p++ = len & 0xff;
8617 *p++ = (len >> 8) & 0xff;
8618 *p++ = (len >> 16) & 0xff;
8619 *p++ = (len >> 24) & 0xff;
8620 *retp = p;
8621 *retbuffer = buffer;
8622 eclass = type->data.klass;
8623 arg_eclass = mono_object_class (arg)->element_class;
8625 if (!eclass) {
8626 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
8627 eclass = mono_defaults.object_class;
8629 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
8630 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
8631 int elsize = mono_class_array_element_size (arg_eclass);
8632 for (i = 0; i < len; ++i) {
8633 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
8634 elptr += elsize;
8636 } else if (eclass->valuetype && arg_eclass->valuetype) {
8637 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
8638 int elsize = mono_class_array_element_size (eclass);
8639 for (i = 0; i < len; ++i) {
8640 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
8641 elptr += elsize;
8643 } else {
8644 for (i = 0; i < len; ++i) {
8645 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
8648 break;
8650 case MONO_TYPE_OBJECT: {
8651 MonoClass *klass;
8652 char *str;
8653 guint32 slen;
8656 * The parameter type is 'object' but the type of the actual
8657 * argument is not. So we have to add type information to the blob
8658 * too. This is completely undocumented in the spec.
8661 if (arg == NULL) {
8662 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
8663 *p++ = 0xFF;
8664 break;
8667 klass = mono_object_class (arg);
8669 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
8670 *p++ = 0x50;
8671 goto handle_type;
8672 } else if (klass->enumtype) {
8673 *p++ = 0x55;
8674 } else if (klass == mono_defaults.string_class) {
8675 simple_type = MONO_TYPE_STRING;
8676 *p++ = 0x0E;
8677 goto handle_enum;
8678 } else if (klass->rank == 1) {
8679 *p++ = 0x1D;
8680 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
8681 /* See Partition II, Appendix B3 */
8682 *p++ = 0x51;
8683 else
8684 *p++ = klass->element_class->byval_arg.type;
8685 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
8686 break;
8687 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
8688 *p++ = simple_type = klass->byval_arg.type;
8689 goto handle_enum;
8690 } else {
8691 g_error ("unhandled type in custom attr");
8693 str = type_get_qualified_name (mono_class_get_type(klass), 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 simple_type = klass->enum_basetype->type;
8708 goto handle_enum;
8710 default:
8711 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
8713 *retp = p;
8714 *retbuffer = buffer;
8717 static void
8718 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
8720 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
8721 char *str = type_get_qualified_name (type, NULL);
8722 int slen = strlen (str);
8724 *p++ = 0x55;
8726 * This seems to be optional...
8727 * *p++ = 0x80;
8729 mono_metadata_encode_value (slen, p, &p);
8730 memcpy (p, str, slen);
8731 p += slen;
8732 g_free (str);
8733 } else if (type->type == MONO_TYPE_OBJECT) {
8734 *p++ = 0x51;
8735 } else if (type->type == MONO_TYPE_CLASS) {
8736 /* it should be a type: encode_cattr_value () has the check */
8737 *p++ = 0x50;
8738 } else {
8739 mono_metadata_encode_value (type->type, p, &p);
8740 if (type->type == MONO_TYPE_SZARRAY)
8741 /* See the examples in Partition VI, Annex B */
8742 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
8745 *retp = p;
8748 static void
8749 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
8751 int len;
8752 /* Preallocate a large enough buffer */
8753 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
8754 char *str = type_get_qualified_name (type, NULL);
8755 len = strlen (str);
8756 g_free (str);
8757 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
8758 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
8759 len = strlen (str);
8760 g_free (str);
8761 } else {
8762 len = 0;
8764 len += strlen (name);
8766 if ((p-buffer) + 20 + len >= *buflen) {
8767 char *newbuf;
8768 *buflen *= 2;
8769 *buflen += len;
8770 newbuf = g_realloc (buffer, *buflen);
8771 p = newbuf + (p-buffer);
8772 buffer = newbuf;
8775 encode_field_or_prop_type (type, p, &p);
8777 len = strlen (name);
8778 mono_metadata_encode_value (len, p, &p);
8779 memcpy (p, name, len);
8780 p += len;
8781 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
8782 *retp = p;
8783 *retbuffer = buffer;
8786 #ifndef DISABLE_REFLECTION_EMIT
8789 * mono_reflection_get_custom_attrs_blob:
8790 * @ctor: custom attribute constructor
8791 * @ctorArgs: arguments o the constructor
8792 * @properties:
8793 * @propValues:
8794 * @fields:
8795 * @fieldValues:
8797 * Creates the blob of data that needs to be saved in the metadata and that represents
8798 * the custom attributed described by @ctor, @ctorArgs etc.
8799 * Returns: a Byte array representing the blob of data.
8801 MonoArray*
8802 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
8804 MonoArray *result;
8805 MonoMethodSignature *sig;
8806 MonoObject *arg;
8807 char *buffer, *p;
8808 guint32 buflen, i;
8810 MONO_ARCH_SAVE_REGS;
8812 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
8813 /* sig is freed later so allocate it in the heap */
8814 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
8815 } else {
8816 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
8819 g_assert (mono_array_length (ctorArgs) == sig->param_count);
8820 buflen = 256;
8821 p = buffer = g_malloc (buflen);
8822 /* write the prolog */
8823 *p++ = 1;
8824 *p++ = 0;
8825 for (i = 0; i < sig->param_count; ++i) {
8826 arg = mono_array_get (ctorArgs, MonoObject*, i);
8827 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
8829 i = 0;
8830 if (properties)
8831 i += mono_array_length (properties);
8832 if (fields)
8833 i += mono_array_length (fields);
8834 *p++ = i & 0xff;
8835 *p++ = (i >> 8) & 0xff;
8836 if (properties) {
8837 MonoObject *prop;
8838 for (i = 0; i < mono_array_length (properties); ++i) {
8839 MonoType *ptype;
8840 char *pname;
8842 prop = mono_array_get (properties, gpointer, i);
8843 get_prop_name_and_type (prop, &pname, &ptype);
8844 *p++ = 0x54; /* PROPERTY signature */
8845 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
8846 g_free (pname);
8850 if (fields) {
8851 MonoObject *field;
8852 for (i = 0; i < mono_array_length (fields); ++i) {
8853 MonoType *ftype;
8854 char *fname;
8856 field = mono_array_get (fields, gpointer, i);
8857 get_field_name_and_type (field, &fname, &ftype);
8858 *p++ = 0x53; /* FIELD signature */
8859 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
8860 g_free (fname);
8864 g_assert (p - buffer <= buflen);
8865 buflen = p - buffer;
8866 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8867 p = mono_array_addr (result, char, 0);
8868 memcpy (p, buffer, buflen);
8869 g_free (buffer);
8870 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
8871 g_free (sig);
8872 return result;
8876 * mono_reflection_setup_internal_class:
8877 * @tb: a TypeBuilder object
8879 * Creates a MonoClass that represents the TypeBuilder.
8880 * This is a trick that lets us simplify a lot of reflection code
8881 * (and will allow us to support Build and Run assemblies easier).
8883 void
8884 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
8886 MonoClass *klass, *parent;
8888 MONO_ARCH_SAVE_REGS;
8890 mono_loader_lock ();
8892 if (tb->parent) {
8893 /* check so we can compile corlib correctly */
8894 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
8895 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
8896 parent = tb->parent->type->data.klass;
8897 } else {
8898 parent = my_mono_class_from_mono_type (tb->parent->type);
8900 } else {
8901 parent = NULL;
8904 /* the type has already being created: it means we just have to change the parent */
8905 if (tb->type.type) {
8906 klass = mono_class_from_mono_type (tb->type.type);
8907 klass->parent = NULL;
8908 /* fool mono_class_setup_parent */
8909 klass->supertypes = NULL;
8910 mono_class_setup_parent (klass, parent);
8911 mono_class_setup_mono_type (klass);
8912 mono_loader_unlock ();
8913 return;
8916 klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
8918 klass->image = &tb->module->dynamic_image->image;
8920 klass->inited = 1; /* we lie to the runtime */
8921 klass->name = mono_string_to_utf8_mp (klass->image->mempool, tb->name);
8922 klass->name_space = mono_string_to_utf8_mp (klass->image->mempool, tb->nspace);
8923 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
8924 klass->flags = tb->attrs;
8926 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
8928 klass->element_class = klass;
8930 MOVING_GC_REGISTER (&klass->reflection_info);
8931 klass->reflection_info = tb;
8933 /* Put into cache so mono_class_get () will find it */
8934 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
8936 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
8937 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
8939 if (parent != NULL) {
8940 mono_class_setup_parent (klass, parent);
8941 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
8942 const char *old_n = klass->name;
8943 /* trick to get relative numbering right when compiling corlib */
8944 klass->name = "BuildingObject";
8945 mono_class_setup_parent (klass, mono_defaults.object_class);
8946 klass->name = old_n;
8949 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
8950 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
8951 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
8952 klass->instance_size = sizeof (MonoObject);
8953 klass->size_inited = 1;
8954 mono_class_setup_vtable_general (klass, NULL, 0);
8957 mono_class_setup_mono_type (klass);
8959 mono_class_setup_supertypes (klass);
8962 * FIXME: handle interfaces.
8965 tb->type.type = &klass->byval_arg;
8967 if (tb->nesting_type) {
8968 g_assert (tb->nesting_type->type);
8969 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
8972 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
8974 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
8976 mono_loader_unlock ();
8980 * mono_reflection_setup_generic_class:
8981 * @tb: a TypeBuilder object
8983 * Setup the generic class before adding the first generic parameter.
8985 void
8986 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
8991 * mono_reflection_create_generic_class:
8992 * @tb: a TypeBuilder object
8994 * Creates the generic class after all generic parameters have been added.
8996 void
8997 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
8999 MonoClass *klass;
9000 int count, i;
9002 MONO_ARCH_SAVE_REGS;
9004 klass = my_mono_class_from_mono_type (tb->type.type);
9006 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
9008 if (klass->generic_container || (count == 0))
9009 return;
9011 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
9013 klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
9015 klass->generic_container->owner.klass = klass;
9016 klass->generic_container->type_argc = count;
9017 klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParam) * count);
9019 for (i = 0; i < count; i++) {
9020 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
9021 klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
9022 /*Make sure we are a diferent type instance */
9023 klass->generic_container->type_params [i].owner = klass->generic_container;
9024 klass->generic_container->type_params [i].pklass = NULL;
9026 g_assert (klass->generic_container->type_params [i].owner);
9029 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
9033 * mono_reflection_create_internal_class:
9034 * @tb: a TypeBuilder object
9036 * Actually create the MonoClass that is associated with the TypeBuilder.
9038 void
9039 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
9041 MonoClass *klass;
9043 MONO_ARCH_SAVE_REGS;
9045 klass = my_mono_class_from_mono_type (tb->type.type);
9047 mono_loader_lock ();
9048 if (klass->enumtype && klass->enum_basetype == NULL) {
9049 MonoReflectionFieldBuilder *fb;
9050 MonoClass *ec;
9052 g_assert (tb->fields != NULL);
9053 g_assert (mono_array_length (tb->fields) >= 1);
9055 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
9057 if (!mono_type_is_valid_enum_basetype (fb->type->type)) {
9058 mono_loader_unlock ();
9059 return;
9062 klass->enum_basetype = fb->type->type;
9063 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
9064 if (!klass->element_class)
9065 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
9068 * get the element_class from the current corlib.
9070 ec = default_class_from_mono_type (klass->enum_basetype);
9071 klass->instance_size = ec->instance_size;
9072 klass->size_inited = 1;
9074 * this is almost safe to do with enums and it's needed to be able
9075 * to create objects of the enum type (for use in SetConstant).
9077 /* FIXME: Does this mean enums can't have method overrides ? */
9078 mono_class_setup_vtable_general (klass, NULL, 0);
9080 mono_loader_unlock ();
9083 #endif /* DISABLE_REFLECTION_EMIT */
9085 static MonoMarshalSpec*
9086 mono_marshal_spec_from_builder (MonoMemPool *mp, MonoAssembly *assembly,
9087 MonoReflectionMarshal *minfo)
9089 MonoMarshalSpec *res;
9091 res = mp_g_new0 (mp, MonoMarshalSpec, 1);
9092 res->native = minfo->type;
9094 switch (minfo->type) {
9095 case MONO_NATIVE_LPARRAY:
9096 res->data.array_data.elem_type = minfo->eltype;
9097 if (minfo->has_size) {
9098 res->data.array_data.param_num = minfo->param_num;
9099 res->data.array_data.num_elem = minfo->count;
9100 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
9102 else {
9103 res->data.array_data.param_num = -1;
9104 res->data.array_data.num_elem = -1;
9105 res->data.array_data.elem_mult = -1;
9107 break;
9109 case MONO_NATIVE_BYVALTSTR:
9110 case MONO_NATIVE_BYVALARRAY:
9111 res->data.array_data.num_elem = minfo->count;
9112 break;
9114 case MONO_NATIVE_CUSTOM:
9115 if (minfo->marshaltyperef)
9116 res->data.custom_data.custom_name =
9117 type_get_fully_qualified_name (minfo->marshaltyperef->type);
9118 if (minfo->mcookie)
9119 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
9120 break;
9122 default:
9123 break;
9126 return res;
9129 MonoReflectionMarshal*
9130 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
9131 MonoMarshalSpec *spec)
9133 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
9134 MonoReflectionMarshal *minfo;
9135 MonoType *mtype;
9137 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
9138 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
9139 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
9140 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
9143 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
9144 minfo->type = spec->native;
9146 switch (minfo->type) {
9147 case MONO_NATIVE_LPARRAY:
9148 minfo->eltype = spec->data.array_data.elem_type;
9149 minfo->count = spec->data.array_data.num_elem;
9150 minfo->param_num = spec->data.array_data.param_num;
9151 break;
9153 case MONO_NATIVE_BYVALTSTR:
9154 case MONO_NATIVE_BYVALARRAY:
9155 minfo->count = spec->data.array_data.num_elem;
9156 break;
9158 case MONO_NATIVE_CUSTOM:
9159 if (spec->data.custom_data.custom_name) {
9160 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
9161 if (mtype)
9162 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
9164 MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
9166 if (spec->data.custom_data.cookie)
9167 MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
9168 break;
9170 default:
9171 break;
9174 return minfo;
9177 static MonoMethod*
9178 reflection_methodbuilder_to_mono_method (MonoClass *klass,
9179 ReflectionMethodBuilder *rmb,
9180 MonoMethodSignature *sig)
9182 MonoMethod *m;
9183 MonoMethodNormal *pm;
9184 MonoMarshalSpec **specs;
9185 MonoReflectionMethodAux *method_aux;
9186 MonoMemPool *mp;
9187 gboolean dynamic;
9188 int i;
9191 * Methods created using a MethodBuilder should have their memory allocated
9192 * inside the image mempool, while dynamic methods should have their memory
9193 * malloc'd.
9195 dynamic = rmb->refs != NULL;
9196 mp = dynamic ? NULL : klass->image->mempool;
9198 if (!dynamic)
9199 g_assert (!klass->generic_class);
9201 mono_loader_lock ();
9203 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
9204 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
9205 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodPInvoke, 1);
9206 else if (rmb->refs)
9207 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodWrapper, 1);
9208 else
9209 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodNormal, 1);
9211 pm = (MonoMethodNormal*)m;
9213 m->dynamic = dynamic;
9214 m->slot = -1;
9215 m->flags = rmb->attrs;
9216 m->iflags = rmb->iattrs;
9217 m->name = mp_string_to_utf8 (mp, rmb->name);
9218 m->klass = klass;
9219 m->signature = sig;
9220 m->skip_visibility = rmb->skip_visibility;
9221 if (rmb->table_idx)
9222 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
9224 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
9225 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
9226 m->string_ctor = 1;
9228 m->signature->pinvoke = 1;
9229 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
9230 m->signature->pinvoke = 1;
9232 method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
9234 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_mp (mp, rmb->dllentry) : mono_mempool_strdup (mp, m->name);
9235 method_aux->dll = mono_string_to_utf8_mp (mp, rmb->dll);
9237 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
9239 if (klass->image->dynamic)
9240 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
9242 mono_loader_unlock ();
9244 return m;
9245 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
9246 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
9247 MonoMethodHeader *header;
9248 guint32 code_size;
9249 gint32 max_stack, i;
9250 gint32 num_locals = 0;
9251 gint32 num_clauses = 0;
9252 guint8 *code;
9254 if (rmb->ilgen) {
9255 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
9256 code_size = rmb->ilgen->code_len;
9257 max_stack = rmb->ilgen->max_stack;
9258 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
9259 if (rmb->ilgen->ex_handlers)
9260 num_clauses = method_count_clauses (rmb->ilgen);
9261 } else {
9262 if (rmb->code) {
9263 code = mono_array_addr (rmb->code, guint8, 0);
9264 code_size = mono_array_length (rmb->code);
9265 /* we probably need to run a verifier on the code... */
9266 max_stack = 8;
9268 else {
9269 code = NULL;
9270 code_size = 0;
9271 max_stack = 8;
9275 header = mp_g_malloc0 (mp, sizeof (MonoMethodHeader) +
9276 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
9277 header->code_size = code_size;
9278 header->code = mp_g_malloc (mp, code_size);
9279 memcpy ((char*)header->code, code, code_size);
9280 header->max_stack = max_stack;
9281 header->init_locals = rmb->init_locals;
9282 header->num_locals = num_locals;
9284 for (i = 0; i < num_locals; ++i) {
9285 MonoReflectionLocalBuilder *lb =
9286 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
9288 header->locals [i] = mp_g_new0 (mp, MonoType, 1);
9289 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
9292 header->num_clauses = num_clauses;
9293 if (num_clauses) {
9294 header->clauses = method_encode_clauses (mp, (MonoDynamicImage*)klass->image,
9295 rmb->ilgen, num_clauses);
9298 pm->header = header;
9301 if (rmb->generic_params) {
9302 int count = mono_array_length (rmb->generic_params);
9303 MonoGenericContainer *container;
9305 container = rmb->generic_container;
9306 if (container) {
9307 m->is_generic = TRUE;
9308 mono_method_set_generic_container (m, container);
9310 container->type_argc = count;
9311 container->type_params = mp_g_new0 (mp, MonoGenericParam, count);
9312 container->owner.method = m;
9314 for (i = 0; i < count; i++) {
9315 MonoReflectionGenericParam *gp =
9316 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
9318 container->type_params [i] = *gp->type.type->data.generic_param;
9321 if (klass->generic_container) {
9322 container->parent = klass->generic_container;
9323 container->context.class_inst = klass->generic_container->context.class_inst;
9325 container->context.method_inst = mono_get_shared_generic_inst (container);
9328 if (rmb->refs) {
9329 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
9330 int i;
9331 void **data;
9333 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
9335 mw->method_data = data = mp_g_new (mp, gpointer, rmb->nrefs + 1);
9336 data [0] = GUINT_TO_POINTER (rmb->nrefs);
9337 for (i = 0; i < rmb->nrefs; ++i)
9338 data [i + 1] = rmb->refs [i];
9341 method_aux = NULL;
9343 /* Parameter info */
9344 if (rmb->pinfo) {
9345 if (!method_aux)
9346 method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
9347 method_aux->param_names = mp_g_new0 (mp, char *, mono_method_signature (m)->param_count + 1);
9348 for (i = 0; i <= m->signature->param_count; ++i) {
9349 MonoReflectionParamBuilder *pb;
9350 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
9351 if ((i > 0) && (pb->attrs)) {
9352 /* Make a copy since it might point to a shared type structure */
9353 m->signature->params [i - 1] = mono_metadata_type_dup (mp, m->signature->params [i - 1]);
9354 m->signature->params [i - 1]->attrs = pb->attrs;
9357 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
9358 MonoDynamicImage *assembly;
9359 guint32 idx, def_type, len;
9360 char *p;
9361 const char *p2;
9363 if (!method_aux->param_defaults) {
9364 method_aux->param_defaults = mp_g_new0 (mp, guint8*, m->signature->param_count + 1);
9365 method_aux->param_default_types = mp_g_new0 (mp, guint32, m->signature->param_count + 1);
9367 assembly = (MonoDynamicImage*)klass->image;
9368 idx = encode_constant (assembly, pb->def_value, &def_type);
9369 /* Copy the data from the blob since it might get realloc-ed */
9370 p = assembly->blob.data + idx;
9371 len = mono_metadata_decode_blob_size (p, &p2);
9372 len += p2 - p;
9373 method_aux->param_defaults [i] = mp_g_malloc (mp, len);
9374 method_aux->param_default_types [i] = def_type;
9375 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
9378 if (pb->name)
9379 method_aux->param_names [i] = mp_string_to_utf8 (mp, pb->name);
9380 if (pb->cattrs) {
9381 if (!method_aux->param_cattr)
9382 method_aux->param_cattr = mp_g_new0 (mp, MonoCustomAttrInfo*, m->signature->param_count + 1);
9383 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (mp, klass->image, pb->cattrs);
9389 /* Parameter marshalling */
9390 specs = NULL;
9391 if (rmb->pinfo)
9392 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
9393 MonoReflectionParamBuilder *pb;
9394 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
9395 if (pb->marshal_info) {
9396 if (specs == NULL)
9397 specs = mp_g_new0 (mp, MonoMarshalSpec*, sig->param_count + 1);
9398 specs [pb->position] =
9399 mono_marshal_spec_from_builder (mp, klass->image->assembly, pb->marshal_info);
9403 if (specs != NULL) {
9404 if (!method_aux)
9405 method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
9406 method_aux->param_marshall = specs;
9409 if (klass->image->dynamic && method_aux)
9410 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
9412 mono_loader_unlock ();
9414 return m;
9417 static MonoMethod*
9418 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
9420 ReflectionMethodBuilder rmb;
9421 MonoMethodSignature *sig;
9423 mono_loader_lock ();
9424 sig = ctor_builder_to_signature (klass->image->mempool, mb);
9425 mono_loader_unlock ();
9427 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
9429 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
9430 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
9432 /* If we are in a generic class, we might be called multiple times from inflate_method */
9433 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
9434 /* ilgen is no longer needed */
9435 mb->ilgen = NULL;
9438 return mb->mhandle;
9441 static MonoMethod*
9442 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
9444 ReflectionMethodBuilder rmb;
9445 MonoMethodSignature *sig;
9447 mono_loader_lock ();
9448 sig = method_builder_to_signature (klass->image->mempool, mb);
9449 mono_loader_unlock ();
9451 reflection_methodbuilder_from_method_builder (&rmb, mb);
9453 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
9454 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
9456 /* If we are in a generic class, we might be called multiple times from inflate_method */
9457 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
9458 /* ilgen is no longer needed */
9459 mb->ilgen = NULL;
9461 return mb->mhandle;
9464 static MonoClassField*
9465 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
9467 MonoClassField *field;
9468 MonoType *custom;
9470 field = g_new0 (MonoClassField, 1);
9472 field->name = mono_string_to_utf8 (fb->name);
9473 if (fb->attrs || fb->modreq || fb->modopt) {
9474 field->type = mono_metadata_type_dup (NULL, fb->type->type);
9475 field->type->attrs = fb->attrs;
9477 g_assert (klass->image->dynamic);
9478 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
9479 g_free (field->type);
9480 field->type = custom;
9481 } else {
9482 field->type = fb->type->type;
9484 if (fb->offset != -1)
9485 field->offset = fb->offset;
9486 field->parent = klass;
9487 mono_save_custom_attrs (klass->image, field, fb->cattrs);
9489 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
9491 return field;
9494 MonoType*
9495 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
9497 MonoClass *klass;
9498 MonoReflectionTypeBuilder *tb = NULL;
9499 gboolean is_dynamic = FALSE;
9500 MonoDomain *domain;
9501 MonoClass *geninst;
9503 mono_loader_lock ();
9505 domain = mono_object_domain (type);
9507 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
9508 tb = (MonoReflectionTypeBuilder *) type;
9510 is_dynamic = TRUE;
9511 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
9512 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
9514 tb = rgi->generic_type;
9515 is_dynamic = TRUE;
9518 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
9519 if (tb && tb->generic_container)
9520 mono_reflection_create_generic_class (tb);
9522 klass = mono_class_from_mono_type (type->type);
9523 if (!klass->generic_container) {
9524 mono_loader_unlock ();
9525 return NULL;
9528 if (klass->wastypebuilder) {
9529 tb = (MonoReflectionTypeBuilder *) klass->reflection_info;
9531 is_dynamic = TRUE;
9534 mono_loader_unlock ();
9536 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
9538 return &geninst->byval_arg;
9541 MonoClass*
9542 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
9544 MonoGenericClass *gclass;
9545 MonoGenericInst *inst;
9547 g_assert (klass->generic_container);
9549 inst = mono_metadata_get_generic_inst (type_argc, types);
9550 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
9552 return mono_generic_class_get_class (gclass);
9555 MonoReflectionMethod*
9556 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
9558 MonoClass *klass;
9559 MonoMethod *method, *inflated;
9560 MonoMethodInflated *imethod;
9561 MonoReflectionMethodBuilder *mb = NULL;
9562 MonoGenericContext tmp_context;
9563 MonoGenericInst *ginst;
9564 MonoType **type_argv;
9565 int count, i;
9567 MONO_ARCH_SAVE_REGS;
9569 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
9570 #ifndef DISABLE_REFLECTION_EMIT
9571 MonoReflectionTypeBuilder *tb;
9572 MonoClass *klass;
9574 mb = (MonoReflectionMethodBuilder *) rmethod;
9575 tb = (MonoReflectionTypeBuilder *) mb->type;
9576 klass = mono_class_from_mono_type (tb->type.type);
9578 method = methodbuilder_to_mono_method (klass, mb);
9579 #else
9580 g_assert_not_reached ();
9581 method = NULL;
9582 #endif
9583 } else {
9584 method = rmethod->method;
9587 klass = method->klass;
9589 if (method->is_inflated)
9590 method = ((MonoMethodInflated *) method)->declaring;
9592 count = mono_method_signature (method)->generic_param_count;
9593 if (count != mono_array_length (types))
9594 return NULL;
9596 type_argv = g_new0 (MonoType *, count);
9597 for (i = 0; i < count; i++) {
9598 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
9599 type_argv [i] = garg->type;
9601 ginst = mono_metadata_get_generic_inst (count, type_argv);
9602 g_free (type_argv);
9604 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
9605 tmp_context.method_inst = ginst;
9607 inflated = mono_class_inflate_generic_method (method, &tmp_context);
9608 imethod = (MonoMethodInflated *) inflated;
9610 if (method->klass->image->dynamic) {
9611 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
9613 * This table maps metadata structures representing inflated methods/fields
9614 * to the reflection objects representing their generic definitions.
9616 mono_loader_lock ();
9617 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
9618 mono_loader_unlock ();
9621 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
9624 #ifndef DISABLE_REFLECTION_EMIT
9626 static MonoMethod *
9627 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
9629 MonoMethodInflated *imethod;
9630 MonoGenericContext *context;
9631 int i;
9634 * With generic code sharing the klass might not be inflated.
9635 * This can happen because classes inflated with their own
9636 * type arguments are "normalized" to the uninflated class.
9638 if (!klass->generic_class)
9639 return method;
9641 context = mono_class_get_context (klass);
9643 if (klass->method.count) {
9644 /* Find the already created inflated method */
9645 for (i = 0; i < klass->method.count; ++i) {
9646 g_assert (klass->methods [i]->is_inflated);
9647 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
9648 break;
9650 g_assert (i < klass->method.count);
9651 imethod = (MonoMethodInflated*)klass->methods [i];
9652 } else {
9653 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
9656 if (method->is_generic && method->klass->image->dynamic) {
9657 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
9659 mono_loader_lock ();
9660 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
9661 mono_loader_unlock ();
9663 return (MonoMethod *) imethod;
9666 static MonoMethod *
9667 inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
9669 MonoMethod *method;
9670 MonoClass *gklass;
9672 gklass = mono_class_from_mono_type (type->generic_type->type.type);
9674 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
9675 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
9676 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
9677 else
9678 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
9679 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
9680 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
9681 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
9682 method = ((MonoReflectionMethod *) obj)->method;
9683 else {
9684 method = NULL; /* prevent compiler warning */
9685 g_assert_not_reached ();
9688 return inflate_mono_method (mono_class_from_mono_type (type->type.type), method, obj);
9691 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
9692 void
9693 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
9694 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
9695 MonoArray *events)
9697 MonoGenericClass *gclass;
9698 MonoDynamicGenericClass *dgclass;
9699 MonoClass *klass, *gklass;
9700 int i;
9702 MONO_ARCH_SAVE_REGS;
9704 klass = mono_class_from_mono_type (type->type.type);
9705 g_assert (type->type.type->type == MONO_TYPE_GENERICINST);
9706 gclass = type->type.type->data.generic_class;
9708 g_assert (gclass->is_dynamic);
9709 dgclass = (MonoDynamicGenericClass *) gclass;
9711 if (dgclass->initialized)
9712 return;
9714 gklass = gclass->container_class;
9715 mono_class_init (gklass);
9717 dgclass->count_methods = methods ? mono_array_length (methods) : 0;
9718 dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
9719 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
9720 dgclass->count_properties = properties ? mono_array_length (properties) : 0;
9721 dgclass->count_events = events ? mono_array_length (events) : 0;
9723 dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
9724 dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
9725 dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
9726 dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
9727 dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
9728 dgclass->field_objects = g_new0 (MonoObject*, dgclass->count_fields);
9729 dgclass->field_generic_types = g_new0 (MonoType*, dgclass->count_fields);
9731 for (i = 0; i < dgclass->count_methods; i++) {
9732 MonoObject *obj = mono_array_get (methods, gpointer, i);
9734 dgclass->methods [i] = inflate_method (type, obj);
9737 for (i = 0; i < dgclass->count_ctors; i++) {
9738 MonoObject *obj = mono_array_get (ctors, gpointer, i);
9740 dgclass->ctors [i] = inflate_method (type, obj);
9743 for (i = 0; i < dgclass->count_fields; i++) {
9744 MonoObject *obj = mono_array_get (fields, gpointer, i);
9745 MonoClassField *field, *inflated_field = NULL;
9747 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
9748 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
9749 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
9750 field = ((MonoReflectionField *) obj)->field;
9751 else {
9752 field = NULL; /* prevent compiler warning */
9753 g_assert_not_reached ();
9756 dgclass->fields [i] = *field;
9757 dgclass->fields [i].parent = klass;
9758 dgclass->fields [i].type = mono_class_inflate_generic_type (
9759 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
9760 dgclass->field_generic_types [i] = field->type;
9761 MOVING_GC_REGISTER (&dgclass->field_objects [i]);
9762 dgclass->field_objects [i] = obj;
9764 if (inflated_field) {
9765 g_free (inflated_field);
9766 } else {
9767 dgclass->fields [i].name = g_strdup (dgclass->fields [i].name);
9771 for (i = 0; i < dgclass->count_properties; i++) {
9772 MonoObject *obj = mono_array_get (properties, gpointer, i);
9773 MonoProperty *property = &dgclass->properties [i];
9775 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
9776 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
9778 property->parent = klass;
9779 property->attrs = pb->attrs;
9780 property->name = mono_string_to_utf8 (pb->name);
9781 if (pb->get_method)
9782 property->get = inflate_method (type, (MonoObject *) pb->get_method);
9783 if (pb->set_method)
9784 property->set = inflate_method (type, (MonoObject *) pb->set_method);
9785 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
9786 *property = *((MonoReflectionProperty *) obj)->property;
9787 property->name = g_strdup (property->name);
9789 if (property->get)
9790 property->get = inflate_mono_method (klass, property->get, NULL);
9791 if (property->set)
9792 property->set = inflate_mono_method (klass, property->set, NULL);
9793 } else
9794 g_assert_not_reached ();
9797 for (i = 0; i < dgclass->count_events; i++) {
9798 MonoObject *obj = mono_array_get (events, gpointer, i);
9799 MonoEvent *event = &dgclass->events [i];
9801 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
9802 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
9804 event->parent = klass;
9805 event->attrs = eb->attrs;
9806 event->name = mono_string_to_utf8 (eb->name);
9807 if (eb->add_method)
9808 event->add = inflate_method (type, (MonoObject *) eb->add_method);
9809 if (eb->remove_method)
9810 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
9811 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
9812 *event = *((MonoReflectionEvent *) obj)->event;
9813 event->name = g_strdup (event->name);
9815 if (event->add)
9816 event->add = inflate_mono_method (klass, event->add, NULL);
9817 if (event->remove)
9818 event->remove = inflate_mono_method (klass, event->remove, NULL);
9819 } else
9820 g_assert_not_reached ();
9823 dgclass->initialized = TRUE;
9826 static void
9827 ensure_generic_class_runtime_vtable (MonoClass *klass)
9829 MonoClass *gklass = klass->generic_class->container_class;
9830 int i;
9832 if (klass->wastypebuilder)
9833 return;
9835 ensure_runtime_vtable (gklass);
9837 klass->method.count = gklass->method.count;
9838 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
9840 for (i = 0; i < klass->method.count; i++) {
9841 klass->methods [i] = mono_class_inflate_generic_method_full (
9842 gklass->methods [i], klass, mono_class_get_context (klass));
9845 klass->interface_count = gklass->interface_count;
9846 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
9847 for (i = 0; i < klass->interface_count; ++i) {
9848 MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
9849 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
9850 mono_metadata_free_type (iface_type);
9852 ensure_runtime_vtable (klass->interfaces [i]);
9854 /*We can only finish with this klass once it's parent has as well*/
9855 if (gklass->wastypebuilder)
9856 klass->wastypebuilder = TRUE;
9857 return;
9860 static void
9861 ensure_runtime_vtable (MonoClass *klass)
9863 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9864 int i, num, j;
9866 if (!klass->image->dynamic || (!tb && !klass->generic_class) || klass->wastypebuilder)
9867 return;
9868 if (klass->parent)
9869 ensure_runtime_vtable (klass->parent);
9871 if (tb) {
9872 num = tb->ctors? mono_array_length (tb->ctors): 0;
9873 num += tb->num_methods;
9874 klass->method.count = num;
9875 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
9876 num = tb->ctors? mono_array_length (tb->ctors): 0;
9877 for (i = 0; i < num; ++i)
9878 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
9879 num = tb->num_methods;
9880 j = i;
9881 for (i = 0; i < num; ++i)
9882 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
9884 if (tb->interfaces) {
9885 klass->interface_count = mono_array_length (tb->interfaces);
9886 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
9887 for (i = 0; i < klass->interface_count; ++i) {
9888 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
9889 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
9890 ensure_runtime_vtable (klass->interfaces [i]);
9893 } else if (klass->generic_class){
9894 ensure_generic_class_runtime_vtable (klass);
9897 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
9898 for (i = 0; i < klass->method.count; ++i)
9899 klass->methods [i]->slot = i;
9901 mono_class_setup_interface_offsets (klass);
9902 mono_class_setup_interface_id (klass);
9906 * The generic vtable is needed even if image->run is not set since some
9907 * runtime code like ves_icall_Type_GetMethodsByName depends on
9908 * method->slot being defined.
9912 * tb->methods could not be freed since it is used for determining
9913 * overrides during dynamic vtable construction.
9917 void
9918 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
9920 MonoReflectionTypeBuilder *tb;
9921 int i, onum;
9923 *overrides = NULL;
9924 *num_overrides = 0;
9926 g_assert (klass->image->dynamic);
9928 if (!klass->reflection_info)
9929 return;
9931 g_assert (strcmp (((MonoObject*)klass->reflection_info)->vtable->klass->name, "TypeBuilder") == 0);
9933 tb = (MonoReflectionTypeBuilder*)klass->reflection_info;
9935 onum = 0;
9936 if (tb->methods) {
9937 for (i = 0; i < tb->num_methods; ++i) {
9938 MonoReflectionMethodBuilder *mb =
9939 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9940 if (mb->override_method)
9941 onum ++;
9945 if (onum) {
9946 *overrides = g_new0 (MonoMethod*, onum * 2);
9948 onum = 0;
9949 for (i = 0; i < tb->num_methods; ++i) {
9950 MonoReflectionMethodBuilder *mb =
9951 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9952 if (mb->override_method) {
9953 (*overrides) [onum * 2] =
9954 mb->override_method->method;
9955 (*overrides) [onum * 2 + 1] =
9956 mb->mhandle;
9958 /* FIXME: What if 'override_method' is a MethodBuilder ? */
9959 g_assert (mb->override_method->method);
9960 g_assert (mb->mhandle);
9962 onum ++;
9967 *num_overrides = onum;
9970 static void
9971 typebuilder_setup_fields (MonoClass *klass)
9973 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9974 MonoReflectionFieldBuilder *fb;
9975 MonoClassField *field;
9976 MonoMemPool *mp = klass->image->mempool;
9977 const char *p, *p2;
9978 int i;
9979 guint32 len, idx, real_size = 0;
9981 klass->field.count = tb->num_fields;
9982 klass->field.first = 0;
9984 if (tb->class_size) {
9985 g_assert ((tb->packing_size & 0xfffffff0) == 0);
9986 klass->packing_size = tb->packing_size;
9987 real_size = klass->instance_size + tb->class_size;
9990 if (!klass->field.count) {
9991 klass->instance_size = MAX (klass->instance_size, real_size);
9992 return;
9995 klass->fields = mp_g_new0 (mp, MonoClassField, klass->field.count);
9996 klass->field_def_values = mp_g_new0 (mp, MonoFieldDefaultValue, klass->field.count);
9998 for (i = 0; i < klass->field.count; ++i) {
9999 fb = mono_array_get (tb->fields, gpointer, i);
10000 field = &klass->fields [i];
10001 field->name = mp_string_to_utf8 (mp, fb->name);
10002 if (fb->attrs) {
10003 field->type = mono_metadata_type_dup (mp, fb->type->type);
10004 field->type->attrs = fb->attrs;
10005 } else {
10006 field->type = fb->type->type;
10008 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
10009 klass->field_def_values [i].data = mono_array_addr (fb->rva_data, char, 0);
10010 if (fb->offset != -1)
10011 field->offset = fb->offset;
10012 field->parent = klass;
10013 fb->handle = field;
10014 mono_save_custom_attrs (klass->image, field, fb->cattrs);
10016 if (fb->def_value) {
10017 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
10018 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
10019 idx = encode_constant (assembly, fb->def_value, &klass->field_def_values [i].def_type);
10020 /* Copy the data from the blob since it might get realloc-ed */
10021 p = assembly->blob.data + idx;
10022 len = mono_metadata_decode_blob_size (p, &p2);
10023 len += p2 - p;
10024 klass->field_def_values [i].data = mono_mempool_alloc (mp, len);
10025 memcpy ((gpointer)klass->field_def_values [i].data, p, len);
10029 klass->instance_size = MAX (klass->instance_size, real_size);
10030 mono_class_layout_fields (klass);
10033 static void
10034 typebuilder_setup_properties (MonoClass *klass)
10036 MonoReflectionTypeBuilder *tb = klass->reflection_info;
10037 MonoReflectionPropertyBuilder *pb;
10038 MonoMemPool *mp = klass->image->mempool;
10039 int i;
10041 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
10042 klass->property.first = 0;
10044 klass->properties = mp_g_new0 (mp, MonoProperty, klass->property.count);
10045 for (i = 0; i < klass->property.count; ++i) {
10046 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
10047 klass->properties [i].parent = klass;
10048 klass->properties [i].attrs = pb->attrs;
10049 klass->properties [i].name = mp_string_to_utf8 (mp, pb->name);
10050 if (pb->get_method)
10051 klass->properties [i].get = pb->get_method->mhandle;
10052 if (pb->set_method)
10053 klass->properties [i].set = pb->set_method->mhandle;
10055 mono_save_custom_attrs (klass->image, &klass->properties [i], pb->cattrs);
10059 MonoReflectionEvent *
10060 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
10062 MonoEvent *event = g_new0 (MonoEvent, 1);
10063 MonoClass *klass;
10064 int j;
10066 klass = my_mono_class_from_mono_type (tb->type.type);
10068 event->parent = klass;
10069 event->attrs = eb->attrs;
10070 event->name = mono_string_to_utf8 (eb->name);
10071 if (eb->add_method)
10072 event->add = eb->add_method->mhandle;
10073 if (eb->remove_method)
10074 event->remove = eb->remove_method->mhandle;
10075 if (eb->raise_method)
10076 event->raise = eb->raise_method->mhandle;
10078 if (eb->other_methods) {
10079 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
10080 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
10081 MonoReflectionMethodBuilder *mb =
10082 mono_array_get (eb->other_methods,
10083 MonoReflectionMethodBuilder*, j);
10084 event->other [j] = mb->mhandle;
10088 return mono_event_get_object (mono_object_domain (tb), klass, event);
10091 static void
10092 typebuilder_setup_events (MonoClass *klass)
10094 MonoReflectionTypeBuilder *tb = klass->reflection_info;
10095 MonoReflectionEventBuilder *eb;
10096 MonoMemPool *mp = klass->image->mempool;
10097 int i, j;
10099 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
10100 klass->event.first = 0;
10102 klass->events = mp_g_new0 (mp, MonoEvent, klass->event.count);
10103 for (i = 0; i < klass->event.count; ++i) {
10104 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
10105 klass->events [i].parent = klass;
10106 klass->events [i].attrs = eb->attrs;
10107 klass->events [i].name = mp_string_to_utf8 (mp, eb->name);
10108 if (eb->add_method)
10109 klass->events [i].add = eb->add_method->mhandle;
10110 if (eb->remove_method)
10111 klass->events [i].remove = eb->remove_method->mhandle;
10112 if (eb->raise_method)
10113 klass->events [i].raise = eb->raise_method->mhandle;
10115 if (eb->other_methods) {
10116 klass->events [i].other = mp_g_new0 (mp, MonoMethod*, mono_array_length (eb->other_methods) + 1);
10117 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
10118 MonoReflectionMethodBuilder *mb =
10119 mono_array_get (eb->other_methods,
10120 MonoReflectionMethodBuilder*, j);
10121 klass->events [i].other [j] = mb->mhandle;
10124 mono_save_custom_attrs (klass->image, &klass->events [i], eb->cattrs);
10128 static gboolean
10129 remove_instantiations_of (gpointer key,
10130 gpointer value,
10131 gpointer user_data)
10133 MonoType *type = (MonoType*)key;
10134 MonoClass *klass = (MonoClass*)user_data;
10136 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass))
10137 return TRUE;
10138 else
10139 return FALSE;
10142 MonoReflectionType*
10143 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
10145 MonoClass *klass;
10146 MonoDomain* domain;
10147 MonoReflectionType* res;
10148 int i;
10150 MONO_ARCH_SAVE_REGS;
10152 domain = mono_object_domain (tb);
10153 klass = my_mono_class_from_mono_type (tb->type.type);
10155 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
10158 * we need to lock the domain because the lock will be taken inside
10159 * So, we need to keep the locking order correct.
10161 mono_domain_lock (domain);
10162 mono_loader_lock ();
10163 if (klass->wastypebuilder) {
10164 mono_loader_unlock ();
10165 mono_domain_unlock (domain);
10166 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10169 * Fields to set in klass:
10170 * the various flags: delegate/unicode/contextbound etc.
10172 klass->flags = tb->attrs;
10173 klass->has_cctor = 1;
10174 klass->has_finalize = 1;
10176 #if 0
10177 if (!((MonoDynamicImage*)klass->image)->run) {
10178 if (klass->generic_container) {
10179 /* FIXME: The code below can't handle generic classes */
10180 klass->wastypebuilder = TRUE;
10181 mono_loader_unlock ();
10182 mono_domain_unlock (domain);
10183 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10186 #endif
10188 /* enums are done right away */
10189 if (!klass->enumtype)
10190 ensure_runtime_vtable (klass);
10192 if (tb->subtypes) {
10193 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
10194 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
10195 klass->nested_classes = g_list_prepend_mempool (klass->image->mempool, klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
10199 klass->nested_classes_inited = TRUE;
10201 /* fields and object layout */
10202 if (klass->parent) {
10203 if (!klass->parent->size_inited)
10204 mono_class_init (klass->parent);
10205 klass->instance_size = klass->parent->instance_size;
10206 klass->sizes.class_size = 0;
10207 klass->min_align = klass->parent->min_align;
10208 /* if the type has no fields we won't call the field_setup
10209 * routine which sets up klass->has_references.
10211 klass->has_references |= klass->parent->has_references;
10212 } else {
10213 klass->instance_size = sizeof (MonoObject);
10214 klass->min_align = 1;
10217 /* FIXME: handle packing_size and instance_size */
10218 typebuilder_setup_fields (klass);
10220 typebuilder_setup_properties (klass);
10222 typebuilder_setup_events (klass);
10224 klass->wastypebuilder = TRUE;
10227 * If we are a generic TypeBuilder, there might be instantiations in the type cache
10228 * which have type System.Reflection.MonoGenericClass, but after the type is created,
10229 * we want to return normal System.MonoType objects, so clear these out from the cache.
10231 if (domain->type_hash && klass->generic_container)
10232 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of, klass);
10234 mono_loader_unlock ();
10235 mono_domain_unlock (domain);
10237 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
10238 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10239 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
10242 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10243 g_assert (res != (MonoReflectionType*)tb);
10245 return res;
10248 void
10249 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
10251 MonoGenericParam *param;
10252 MonoImage *image;
10254 MONO_ARCH_SAVE_REGS;
10256 param = g_new0 (MonoGenericParam, 1);
10258 if (gparam->mbuilder) {
10259 if (!gparam->mbuilder->generic_container) {
10260 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
10261 MonoClass *klass = my_mono_class_from_mono_type (tb->type.type);
10262 gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10263 gparam->mbuilder->generic_container->is_method = TRUE;
10265 param->owner = gparam->mbuilder->generic_container;
10266 } else if (gparam->tbuilder) {
10267 if (!gparam->tbuilder->generic_container) {
10268 MonoClass *klass = my_mono_class_from_mono_type (gparam->tbuilder->type.type);
10269 gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10270 gparam->tbuilder->generic_container->owner.klass = klass;
10272 param->owner = gparam->tbuilder->generic_container;
10275 param->name = mono_string_to_utf8 (gparam->name);
10276 param->num = gparam->index;
10278 image = &gparam->tbuilder->module->dynamic_image->image;
10279 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
10281 gparam->type.type = &param->pklass->byval_arg;
10283 MOVING_GC_REGISTER (&param->pklass->reflection_info);
10284 param->pklass->reflection_info = gparam; /* FIXME: GC pin gparam */
10287 MonoArray *
10288 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
10290 MonoDynamicImage *assembly = sig->module->dynamic_image;
10291 guint32 na = mono_array_length (sig->arguments);
10292 guint32 buflen, i;
10293 MonoArray *result;
10294 SigBuffer buf;
10296 sigbuffer_init (&buf, 32);
10298 sigbuffer_add_value (&buf, 0x07);
10299 sigbuffer_add_value (&buf, na);
10300 for (i = 0; i < na; ++i) {
10301 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
10302 encode_reflection_type (assembly, type, &buf);
10305 buflen = buf.p - buf.buf;
10306 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10307 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
10308 sigbuffer_free (&buf);
10310 return result;
10313 MonoArray *
10314 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
10316 MonoDynamicImage *assembly = sig->module->dynamic_image;
10317 guint32 na = mono_array_length (sig->arguments);
10318 guint32 buflen, i;
10319 MonoArray *result;
10320 SigBuffer buf;
10322 sigbuffer_init (&buf, 32);
10324 sigbuffer_add_value (&buf, 0x06);
10325 for (i = 0; i < na; ++i) {
10326 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
10327 encode_reflection_type (assembly, type, &buf);
10330 buflen = buf.p - buf.buf;
10331 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10332 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
10333 sigbuffer_free (&buf);
10335 return result;
10338 void
10339 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
10341 ReflectionMethodBuilder rmb;
10342 MonoMethodSignature *sig;
10343 MonoClass *klass;
10344 GSList *l;
10345 int i;
10347 sig = dynamic_method_to_signature (mb);
10349 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
10352 * Resolve references.
10355 * Every second entry in the refs array is reserved for storing handle_class,
10356 * which is needed by the ldtoken implementation in the JIT.
10358 rmb.nrefs = mb->nrefs;
10359 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
10360 for (i = 0; i < mb->nrefs; i += 2) {
10361 MonoClass *handle_class;
10362 gpointer ref;
10363 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
10365 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
10366 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
10368 * The referenced DynamicMethod should already be created by the managed
10369 * code, except in the case of circular references. In that case, we store
10370 * method in the refs array, and fix it up later when the referenced
10371 * DynamicMethod is created.
10373 if (method->mhandle) {
10374 ref = method->mhandle;
10375 } else {
10376 /* FIXME: GC object stored in unmanaged memory */
10377 ref = method;
10379 /* FIXME: GC object stored in unmanaged memory */
10380 method->referenced_by = g_slist_append (method->referenced_by, mb);
10382 handle_class = mono_defaults.methodhandle_class;
10383 } else {
10384 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
10385 if (!ref) {
10386 g_free (rmb.refs);
10387 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
10388 return;
10392 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
10393 rmb.refs [i + 1] = handle_class;
10396 klass = mb->owner ? mono_class_from_mono_type (mb->owner->type) : mono_defaults.object_class;
10398 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10400 /* Fix up refs entries pointing at us */
10401 for (l = mb->referenced_by; l; l = l->next) {
10402 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
10403 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
10404 gpointer *data;
10406 g_assert (method->mhandle);
10408 data = (gpointer*)wrapper->method_data;
10409 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
10410 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
10411 data [i + 1] = mb->mhandle;
10414 g_slist_free (mb->referenced_by);
10416 g_free (rmb.refs);
10418 /* ilgen is no longer needed */
10419 mb->ilgen = NULL;
10422 #endif /* DISABLE_REFLECTION_EMIT */
10424 void
10425 mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod *mb)
10427 g_assert (mb);
10429 if (mb->mhandle)
10430 mono_runtime_free_method (
10431 mono_object_get_domain ((MonoObject*)mb), mb->mhandle);
10436 * mono_reflection_is_valid_dynamic_token:
10438 * Returns TRUE if token is valid.
10441 gboolean
10442 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
10444 return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
10447 #ifndef DISABLE_REFLECTION_EMIT
10450 * mono_reflection_lookup_dynamic_token:
10452 * Finish the Builder object pointed to by TOKEN and return the corresponding
10453 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
10454 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
10455 * mapping table.
10457 gpointer
10458 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
10460 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
10461 MonoObject *obj;
10462 MonoClass *klass;
10464 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
10465 if (!obj) {
10466 if (valid_token)
10467 g_assert_not_reached ();
10468 else
10469 return NULL;
10472 if (!handle_class)
10473 handle_class = &klass;
10474 return resolve_object (image, obj, handle_class, context);
10477 static gpointer
10478 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
10480 gpointer result = NULL;
10482 if (strcmp (obj->vtable->klass->name, "String") == 0) {
10483 result = mono_string_intern ((MonoString*)obj);
10484 *handle_class = NULL;
10485 g_assert (result);
10486 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
10487 MonoReflectionType *tb = (MonoReflectionType*)obj;
10488 if (context) {
10489 MonoType *inflated = mono_class_inflate_generic_type (tb->type, context);
10490 result = mono_class_from_mono_type (inflated);
10491 mono_metadata_free_type (inflated);
10492 } else {
10493 result = mono_class_from_mono_type (tb->type);
10495 *handle_class = mono_defaults.typehandle_class;
10496 g_assert (result);
10497 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
10498 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
10499 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
10500 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
10501 result = ((MonoReflectionMethod*)obj)->method;
10502 if (context)
10503 result = mono_class_inflate_generic_method (result, context);
10504 *handle_class = mono_defaults.methodhandle_class;
10505 g_assert (result);
10506 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
10507 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
10508 result = mb->mhandle;
10509 if (!result) {
10510 /* Type is not yet created */
10511 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
10513 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10516 * Hopefully this has been filled in by calling CreateType() on the
10517 * TypeBuilder.
10520 * TODO: This won't work if the application finishes another
10521 * TypeBuilder instance instead of this one.
10523 result = mb->mhandle;
10525 if (context)
10526 result = mono_class_inflate_generic_method (result, context);
10527 *handle_class = mono_defaults.methodhandle_class;
10528 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
10529 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
10531 result = cb->mhandle;
10532 if (!result) {
10533 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
10535 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10536 result = cb->mhandle;
10538 if (context)
10539 result = mono_class_inflate_generic_method (result, context);
10540 *handle_class = mono_defaults.methodhandle_class;
10541 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
10542 MonoClassField *field = ((MonoReflectionField*)obj)->field;
10543 if (context) {
10544 MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
10545 MonoClass *class = mono_class_from_mono_type (inflated);
10546 MonoClassField *inflated_field;
10547 gpointer iter = NULL;
10548 mono_metadata_free_type (inflated);
10549 while ((inflated_field = mono_class_get_fields (class, &iter))) {
10550 if (!strcmp (field->name, inflated_field->name))
10551 break;
10553 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
10554 result = inflated_field;
10555 } else {
10556 result = field;
10558 *handle_class = mono_defaults.fieldhandle_class;
10559 g_assert (result);
10560 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
10561 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
10562 result = fb->handle;
10564 if (!result) {
10565 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
10567 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10568 result = fb->handle;
10571 if (fb->handle && fb->handle->parent->generic_container) {
10572 MonoClass *klass = fb->handle->parent;
10573 MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
10574 MonoClass *inflated = mono_class_from_mono_type (type);
10576 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
10577 g_assert (result);
10578 mono_metadata_free_type (type);
10580 *handle_class = mono_defaults.fieldhandle_class;
10581 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
10582 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
10583 MonoClass *klass;
10585 klass = tb->type.type->data.klass;
10586 if (klass->wastypebuilder) {
10587 /* Already created */
10588 result = klass;
10590 else {
10591 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10592 result = tb->type.type->data.klass;
10593 g_assert (result);
10595 *handle_class = mono_defaults.typehandle_class;
10596 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
10597 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
10598 MonoMethodSignature *sig;
10599 int nargs, i;
10601 if (helper->arguments)
10602 nargs = mono_array_length (helper->arguments);
10603 else
10604 nargs = 0;
10606 sig = mono_metadata_signature_alloc (image, nargs);
10607 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
10608 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
10610 if (helper->call_conv == 0) /* unmanaged */
10611 sig->call_convention = helper->unmanaged_call_conv - 1;
10612 else
10613 if (helper->call_conv & 0x02)
10614 sig->call_convention = MONO_CALL_VARARG;
10615 else
10616 sig->call_convention = MONO_CALL_DEFAULT;
10618 sig->param_count = nargs;
10619 /* TODO: Copy type ? */
10620 sig->ret = helper->return_type->type;
10621 for (i = 0; i < nargs; ++i) {
10622 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
10623 sig->params [i] = rt->type;
10626 result = sig;
10627 *handle_class = NULL;
10628 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
10629 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
10630 /* Already created by the managed code */
10631 g_assert (method->mhandle);
10632 result = method->mhandle;
10633 *handle_class = mono_defaults.methodhandle_class;
10634 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
10635 MonoReflectionType *tb = (MonoReflectionType*)obj;
10636 MonoType *type = mono_class_inflate_generic_type (tb->type, context);
10637 result = mono_class_from_mono_type (type);
10638 *handle_class = mono_defaults.typehandle_class;
10639 g_assert (result);
10640 mono_metadata_free_type (type);
10641 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
10642 MonoReflectionGenericClass *ref = (MonoReflectionGenericClass*)obj;
10643 MonoType *type = mono_class_inflate_generic_type (ref->type.type, context);
10644 result = mono_class_from_mono_type (type);
10645 *handle_class = mono_defaults.typehandle_class;
10646 g_assert (result);
10647 mono_metadata_free_type (type);
10648 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
10649 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
10650 MonoClass *inflated;
10651 MonoType *type;
10653 type = mono_class_inflate_generic_type (f->inst->type.type, context);
10654 inflated = mono_class_from_mono_type (type);
10656 g_assert (f->fb->handle);
10657 result = mono_class_get_field_from_name (inflated, mono_field_get_name (f->fb->handle));
10658 g_assert (result);
10659 mono_metadata_free_type (type);
10660 *handle_class = mono_defaults.fieldhandle_class;
10661 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
10662 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
10663 MonoType *type = mono_class_inflate_generic_type (c->inst->type.type, context);
10664 MonoClass *inflated_klass = mono_class_from_mono_type (type);
10665 g_assert (c->cb->mhandle);
10666 result = inflate_mono_method (inflated_klass, c->cb->mhandle, (MonoObject*)c->cb);
10667 *handle_class = mono_defaults.methodhandle_class;
10668 mono_metadata_free_type (type);
10669 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
10670 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
10671 MonoType *type = mono_class_inflate_generic_type (m->inst->type.type, context);
10672 MonoClass *inflated_klass = mono_class_from_mono_type (type);
10673 g_assert (m->mb->mhandle);
10674 result = inflate_mono_method (inflated_klass, m->mb->mhandle, (MonoObject*)m->mb);
10675 *handle_class = mono_defaults.methodhandle_class;
10676 mono_metadata_free_type (type);
10677 } else {
10678 g_print (obj->vtable->klass->name);
10679 g_assert_not_reached ();
10681 return result;
10684 #else /* DISABLE_REFLECTION_EMIT */
10686 MonoArray*
10687 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
10689 g_assert_not_reached ();
10690 return NULL;
10693 void
10694 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
10696 g_assert_not_reached ();
10699 void
10700 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
10702 g_assert_not_reached ();
10705 void
10706 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
10708 g_assert_not_reached ();
10711 void
10712 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
10714 g_assert_not_reached ();
10717 void
10718 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
10720 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
10723 void
10724 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
10726 g_assert_not_reached ();
10729 MonoReflectionModule *
10730 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
10732 g_assert_not_reached ();
10733 return NULL;
10736 guint32
10737 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
10739 g_assert_not_reached ();
10740 return 0;
10743 guint32
10744 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
10746 g_assert_not_reached ();
10747 return 0;
10750 guint32
10751 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
10752 gboolean create_methodspec, gboolean register_token)
10754 g_assert_not_reached ();
10755 return 0;
10758 void
10759 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
10763 void
10764 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
10765 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
10766 MonoArray *events)
10768 g_assert_not_reached ();
10771 void
10772 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
10774 *overrides = NULL;
10775 *num_overrides = 0;
10778 MonoReflectionEvent *
10779 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
10781 g_assert_not_reached ();
10782 return NULL;
10785 MonoReflectionType*
10786 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
10788 g_assert_not_reached ();
10789 return NULL;
10792 void
10793 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
10795 g_assert_not_reached ();
10798 MonoArray *
10799 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
10801 g_assert_not_reached ();
10802 return NULL;
10805 MonoArray *
10806 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
10808 g_assert_not_reached ();
10809 return NULL;
10812 void
10813 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
10817 gpointer
10818 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
10820 return NULL;
10823 #endif /* DISABLE_REFLECTION_EMIT */
10825 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
10826 const static guint32 declsec_flags_map[] = {
10827 0x00000000, /* empty */
10828 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
10829 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
10830 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
10831 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
10832 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
10833 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
10834 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
10835 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
10836 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
10837 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
10838 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
10839 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
10840 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
10841 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
10842 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
10843 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
10844 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
10845 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
10849 * Returns flags that includes all available security action associated to the handle.
10850 * @token: metadata token (either for a class or a method)
10851 * @image: image where resides the metadata.
10853 static guint32
10854 mono_declsec_get_flags (MonoImage *image, guint32 token)
10856 int index = mono_metadata_declsec_from_index (image, token);
10857 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
10858 guint32 result = 0;
10859 guint32 action;
10860 int i;
10862 /* HasSecurity can be present for other, not specially encoded, attributes,
10863 e.g. SuppressUnmanagedCodeSecurityAttribute */
10864 if (index < 0)
10865 return 0;
10867 for (i = index; i < t->rows; i++) {
10868 guint32 cols [MONO_DECL_SECURITY_SIZE];
10870 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
10871 if (cols [MONO_DECL_SECURITY_PARENT] != token)
10872 break;
10874 action = cols [MONO_DECL_SECURITY_ACTION];
10875 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
10876 result |= declsec_flags_map [action];
10877 } else {
10878 g_assert_not_reached ();
10881 return result;
10885 * Get the security actions (in the form of flags) associated with the specified method.
10887 * @method: The method for which we want the declarative security flags.
10888 * Return the declarative security flags for the method (only).
10890 * Note: To keep MonoMethod size down we do not cache the declarative security flags
10891 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
10893 guint32
10894 mono_declsec_flags_from_method (MonoMethod *method)
10896 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10897 /* FIXME: No cache (for the moment) */
10898 guint32 idx = mono_method_get_index (method);
10899 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10900 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
10901 return mono_declsec_get_flags (method->klass->image, idx);
10903 return 0;
10907 * Get the security actions (in the form of flags) associated with the specified class.
10909 * @klass: The class for which we want the declarative security flags.
10910 * Return the declarative security flags for the class.
10912 * Note: We cache the flags inside the MonoClass structure as this will get
10913 * called very often (at least for each method).
10915 guint32
10916 mono_declsec_flags_from_class (MonoClass *klass)
10918 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
10919 if (!klass->declsec_flags) {
10920 guint32 idx = mono_metadata_token_index (klass->type_token);
10921 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10922 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
10923 /* we cache the flags on classes */
10924 klass->declsec_flags = mono_declsec_get_flags (klass->image, idx);
10926 return klass->declsec_flags;
10928 return 0;
10932 * Get the security actions (in the form of flags) associated with the specified assembly.
10934 * @assembly: The assembly for which we want the declarative security flags.
10935 * Return the declarative security flags for the assembly.
10937 guint32
10938 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
10940 guint32 idx = 1; /* there is only one assembly */
10941 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10942 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
10943 return mono_declsec_get_flags (assembly->image, idx);
10948 * Fill actions for the specific index (which may either be an encoded class token or
10949 * an encoded method token) from the metadata image.
10950 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
10952 static MonoBoolean
10953 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
10954 guint32 id_std, guint32 id_noncas, guint32 id_choice)
10956 MonoBoolean result = FALSE;
10957 MonoTableInfo *t;
10958 guint32 cols [MONO_DECL_SECURITY_SIZE];
10959 int index = mono_metadata_declsec_from_index (image, token);
10960 int i;
10962 t = &image->tables [MONO_TABLE_DECLSECURITY];
10963 for (i = index; i < t->rows; i++) {
10964 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
10966 if (cols [MONO_DECL_SECURITY_PARENT] != token)
10967 return result;
10969 /* if present only replace (class) permissions with method permissions */
10970 /* if empty accept either class or method permissions */
10971 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
10972 if (!actions->demand.blob) {
10973 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10974 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
10975 actions->demand.blob = (char*) (blob + 2);
10976 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
10977 result = TRUE;
10979 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
10980 if (!actions->noncasdemand.blob) {
10981 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10982 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
10983 actions->noncasdemand.blob = (char*) (blob + 2);
10984 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
10985 result = TRUE;
10987 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
10988 if (!actions->demandchoice.blob) {
10989 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10990 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
10991 actions->demandchoice.blob = (char*) (blob + 2);
10992 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
10993 result = TRUE;
10998 return result;
11001 static MonoBoolean
11002 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
11003 guint32 id_std, guint32 id_noncas, guint32 id_choice)
11005 guint32 idx = mono_metadata_token_index (klass->type_token);
11006 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11007 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
11008 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
11011 static MonoBoolean
11012 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
11013 guint32 id_std, guint32 id_noncas, guint32 id_choice)
11015 guint32 idx = mono_method_get_index (method);
11016 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11017 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
11018 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
11022 * Collect all actions (that requires to generate code in mini) assigned for
11023 * the specified method.
11024 * Note: Don't use the content of actions if the function return FALSE.
11026 MonoBoolean
11027 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
11029 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
11030 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
11031 MonoBoolean result = FALSE;
11032 guint32 flags;
11034 /* quick exit if no declarative security is present in the metadata */
11035 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11036 return FALSE;
11038 /* we want the original as the wrapper is "free" of the security informations */
11039 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
11040 method = mono_marshal_method_from_wrapper (method);
11041 if (!method)
11042 return FALSE;
11045 /* First we look for method-level attributes */
11046 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11047 mono_class_init (method->klass);
11048 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11050 result = mono_declsec_get_method_demands_params (method, demands,
11051 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
11054 /* Here we use (or create) the class declarative cache to look for demands */
11055 flags = mono_declsec_flags_from_class (method->klass);
11056 if (flags & mask) {
11057 if (!result) {
11058 mono_class_init (method->klass);
11059 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11061 result |= mono_declsec_get_class_demands_params (method->klass, demands,
11062 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
11065 /* The boolean return value is used as a shortcut in case nothing needs to
11066 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
11067 return result;
11072 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
11074 * Note: Don't use the content of actions if the function return FALSE.
11076 MonoBoolean
11077 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
11079 MonoBoolean result = FALSE;
11080 guint32 flags;
11082 /* quick exit if no declarative security is present in the metadata */
11083 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11084 return FALSE;
11086 /* we want the original as the wrapper is "free" of the security informations */
11087 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
11088 method = mono_marshal_method_from_wrapper (method);
11089 if (!method)
11090 return FALSE;
11093 /* results are independant - zeroize both */
11094 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
11095 memset (klass, 0, sizeof (MonoDeclSecurityActions));
11097 /* First we look for method-level attributes */
11098 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11099 mono_class_init (method->klass);
11101 result = mono_declsec_get_method_demands_params (method, cmethod,
11102 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
11105 /* Here we use (or create) the class declarative cache to look for demands */
11106 flags = mono_declsec_flags_from_class (method->klass);
11107 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
11108 mono_class_init (method->klass);
11110 result |= mono_declsec_get_class_demands_params (method->klass, klass,
11111 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
11114 return result;
11118 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
11120 * @klass The inherited class - this is the class that provides the security check (attributes)
11121 * @demans
11122 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
11124 * Note: Don't use the content of actions if the function return FALSE.
11126 MonoBoolean
11127 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
11129 MonoBoolean result = FALSE;
11130 guint32 flags;
11132 /* quick exit if no declarative security is present in the metadata */
11133 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11134 return FALSE;
11136 /* Here we use (or create) the class declarative cache to look for demands */
11137 flags = mono_declsec_flags_from_class (klass);
11138 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
11139 mono_class_init (klass);
11140 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11142 result |= mono_declsec_get_class_demands_params (klass, demands,
11143 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
11146 return result;
11150 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
11152 * Note: Don't use the content of actions if the function return FALSE.
11154 MonoBoolean
11155 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
11157 /* quick exit if no declarative security is present in the metadata */
11158 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11159 return FALSE;
11161 /* we want the original as the wrapper is "free" of the security informations */
11162 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
11163 method = mono_marshal_method_from_wrapper (method);
11164 if (!method)
11165 return FALSE;
11168 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11169 mono_class_init (method->klass);
11170 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11172 return mono_declsec_get_method_demands_params (method, demands,
11173 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
11175 return FALSE;
11179 static MonoBoolean
11180 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
11182 guint32 cols [MONO_DECL_SECURITY_SIZE];
11183 MonoTableInfo *t;
11184 int i;
11186 int index = mono_metadata_declsec_from_index (image, token);
11187 if (index == -1)
11188 return FALSE;
11190 t = &image->tables [MONO_TABLE_DECLSECURITY];
11191 for (i = index; i < t->rows; i++) {
11192 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
11194 /* shortcut - index are ordered */
11195 if (token != cols [MONO_DECL_SECURITY_PARENT])
11196 return FALSE;
11198 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
11199 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11200 entry->blob = (char*) (metadata + 2);
11201 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
11202 return TRUE;
11206 return FALSE;
11209 MonoBoolean
11210 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
11212 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11213 guint32 idx = mono_method_get_index (method);
11214 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11215 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
11216 return get_declsec_action (method->klass->image, idx, action, entry);
11218 return FALSE;
11221 MonoBoolean
11222 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
11224 /* use cache */
11225 guint32 flags = mono_declsec_flags_from_class (klass);
11226 if (declsec_flags_map [action] & flags) {
11227 guint32 idx = mono_metadata_token_index (klass->type_token);
11228 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11229 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
11230 return get_declsec_action (klass->image, idx, action, entry);
11232 return FALSE;
11235 MonoBoolean
11236 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
11238 guint32 idx = 1; /* there is only one assembly */
11239 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11240 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
11242 return get_declsec_action (assembly->image, idx, action, entry);
11245 gboolean
11246 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
11248 MonoObject *res, *exc;
11249 void *params [1];
11250 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
11251 static MonoMethod *method = NULL;
11253 if (!System_Reflection_Emit_TypeBuilder) {
11254 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
11255 g_assert (System_Reflection_Emit_TypeBuilder);
11257 if (method == NULL) {
11258 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
11259 g_assert (method);
11263 * The result of mono_type_get_object () might be a System.MonoType but we
11264 * need a TypeBuilder so use klass->reflection_info.
11266 g_assert (klass->reflection_info);
11267 g_assert (!strcmp (((MonoObject*)(klass->reflection_info))->vtable->klass->name, "TypeBuilder"));
11269 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
11271 res = mono_runtime_invoke (method, (MonoObject*)(klass->reflection_info), params, &exc);
11272 if (exc)
11273 return FALSE;
11274 else
11275 return *(MonoBoolean*)mono_object_unbox (res);