2009-03-10 Zoltan Varga <vargaz@gmail.com>
[mono-debugger.git] / mono / metadata / reflection.c
blob5cbe232144e3f771bad650c8da0040f311167995
1 /*
2 * reflection.c: Routines for creating an image at runtime.
3 *
4 * Author:
5 * Paolo Molaro (lupus@ximian.com)
7 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
11 #include <config.h>
12 #include "mono/utils/mono-digest.h"
13 #include "mono/utils/mono-membar.h"
14 #include "mono/metadata/reflection.h"
15 #include "mono/metadata/tabledefs.h"
16 #include "mono/metadata/metadata-internals.h"
17 #include <mono/metadata/profiler-private.h>
18 #include "mono/metadata/class-internals.h"
19 #include "mono/metadata/gc-internal.h"
20 #include "mono/metadata/tokentype.h"
21 #include "mono/metadata/domain-internals.h"
22 #include "mono/metadata/opcodes.h"
23 #include "mono/metadata/assembly.h"
24 #include "mono/metadata/object-internals.h"
25 #include <mono/metadata/exception.h>
26 #include <mono/metadata/marshal.h>
27 #include <mono/metadata/security-manager.h>
28 #include <stdio.h>
29 #include <glib.h>
30 #include <errno.h>
31 #include <time.h>
32 #include <string.h>
33 #include <ctype.h>
34 #include "image.h"
35 #include "cil-coff.h"
36 #include "mono-endian.h"
37 #include <mono/metadata/gc-internal.h>
38 #include <mono/metadata/mempool-internals.h>
40 #if HAVE_SGEN_GC
41 static void* reflection_info_desc = NULL;
42 #define MOVING_GC_REGISTER(addr) do { \
43 if (!reflection_info_desc) { \
44 gsize bmap = 1; \
45 reflection_info_desc = mono_gc_make_descr_from_bitmap (&bmap, 1); \
46 } \
47 mono_gc_register_root ((char*)(addr), sizeof (gpointer), reflection_info_desc); \
48 } while (0)
49 #else
50 #define MOVING_GC_REGISTER(addr)
51 #endif
53 static void
54 check_array_for_usertypes (MonoArray *arr)
56 int i;
58 if (!arr)
59 return;
61 for (i = 0; i < mono_array_length (arr); ++i)
62 CHECK_MONOTYPE (mono_array_get (arr, gpointer, i));
65 typedef struct {
66 char *p;
67 char *buf;
68 char *end;
69 } SigBuffer;
71 #define TEXT_OFFSET 512
72 #define CLI_H_SIZE 136
73 #define FILE_ALIGN 512
74 #define VIRT_ALIGN 8192
75 #define START_TEXT_RVA 0x00002000
77 typedef struct {
78 MonoReflectionILGen *ilgen;
79 MonoReflectionType *rtype;
80 MonoArray *parameters;
81 MonoArray *generic_params;
82 MonoGenericContainer *generic_container;
83 MonoArray *pinfo;
84 MonoArray *opt_types;
85 guint32 attrs;
86 guint32 iattrs;
87 guint32 call_conv;
88 guint32 *table_idx; /* note: it's a pointer */
89 MonoArray *code;
90 MonoObject *type;
91 MonoString *name;
92 MonoBoolean init_locals;
93 MonoBoolean skip_visibility;
94 MonoArray *return_modreq;
95 MonoArray *return_modopt;
96 MonoArray *param_modreq;
97 MonoArray *param_modopt;
98 MonoArray *permissions;
99 MonoMethod *mhandle;
100 guint32 nrefs;
101 gpointer *refs;
102 /* for PInvoke */
103 int charset, extra_flags, native_cc;
104 MonoString *dll, *dllentry;
105 } ReflectionMethodBuilder;
107 typedef struct {
108 guint32 owner;
109 MonoReflectionGenericParam *gparam;
110 } GenericParamTableEntry;
112 const unsigned char table_sizes [MONO_TABLE_NUM] = {
113 MONO_MODULE_SIZE,
114 MONO_TYPEREF_SIZE,
115 MONO_TYPEDEF_SIZE,
117 MONO_FIELD_SIZE,
119 MONO_METHOD_SIZE,
121 MONO_PARAM_SIZE,
122 MONO_INTERFACEIMPL_SIZE,
123 MONO_MEMBERREF_SIZE, /* 0x0A */
124 MONO_CONSTANT_SIZE,
125 MONO_CUSTOM_ATTR_SIZE,
126 MONO_FIELD_MARSHAL_SIZE,
127 MONO_DECL_SECURITY_SIZE,
128 MONO_CLASS_LAYOUT_SIZE,
129 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
130 MONO_STAND_ALONE_SIGNATURE_SIZE,
131 MONO_EVENT_MAP_SIZE,
133 MONO_EVENT_SIZE,
134 MONO_PROPERTY_MAP_SIZE,
136 MONO_PROPERTY_SIZE,
137 MONO_METHOD_SEMA_SIZE,
138 MONO_METHODIMPL_SIZE,
139 MONO_MODULEREF_SIZE, /* 0x1A */
140 MONO_TYPESPEC_SIZE,
141 MONO_IMPLMAP_SIZE,
142 MONO_FIELD_RVA_SIZE,
145 MONO_ASSEMBLY_SIZE, /* 0x20 */
146 MONO_ASSEMBLY_PROCESSOR_SIZE,
147 MONO_ASSEMBLYOS_SIZE,
148 MONO_ASSEMBLYREF_SIZE,
149 MONO_ASSEMBLYREFPROC_SIZE,
150 MONO_ASSEMBLYREFOS_SIZE,
151 MONO_FILE_SIZE,
152 MONO_EXP_TYPE_SIZE,
153 MONO_MANIFEST_SIZE,
154 MONO_NESTED_CLASS_SIZE,
156 MONO_GENERICPARAM_SIZE, /* 0x2A */
157 MONO_METHODSPEC_SIZE,
158 MONO_GENPARCONSTRAINT_SIZE
162 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
163 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
164 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
165 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
166 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
167 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec);
168 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
169 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
170 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
171 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
172 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
173 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
174 static void ensure_runtime_vtable (MonoClass *klass);
175 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
176 static void encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
177 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
178 static MonoObject *mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob);
179 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t);
180 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
181 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method);
182 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
184 void
185 mono_reflection_init (void)
189 static void
190 sigbuffer_init (SigBuffer *buf, int size)
192 buf->buf = g_malloc (size);
193 buf->p = buf->buf;
194 buf->end = buf->buf + size;
197 static void
198 sigbuffer_make_room (SigBuffer *buf, int size)
200 if (buf->end - buf->p < size) {
201 int new_size = buf->end - buf->buf + size + 32;
202 char *p = g_realloc (buf->buf, new_size);
203 size = buf->p - buf->buf;
204 buf->buf = p;
205 buf->p = p + size;
206 buf->end = buf->buf + new_size;
210 static void
211 sigbuffer_add_value (SigBuffer *buf, guint32 val)
213 sigbuffer_make_room (buf, 6);
214 mono_metadata_encode_value (val, buf->p, &buf->p);
217 static void
218 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
220 sigbuffer_make_room (buf, 1);
221 buf->p [0] = val;
222 buf->p++;
225 static void
226 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
228 sigbuffer_make_room (buf, size);
229 memcpy (buf->p, p, size);
230 buf->p += size;
233 static void
234 sigbuffer_free (SigBuffer *buf)
236 g_free (buf->buf);
240 * mp_g_alloc:
242 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
243 * from the C heap.
245 static gpointer
246 image_g_malloc (MonoImage *image, guint size)
248 if (image)
249 return mono_image_alloc (image, size);
250 else
251 return g_malloc (size);
255 * image_g_alloc0:
257 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
258 * from the C heap.
260 static gpointer
261 image_g_malloc0 (MonoImage *image, guint size)
263 if (image)
264 return mono_image_alloc0 (image, size);
265 else
266 return g_malloc0 (size);
269 static char*
270 image_strdup (MonoImage *image, const char *s)
272 if (image)
273 return mono_image_strdup (image, s);
274 else
275 return g_strdup (s);
278 #define image_g_new(image,struct_type, n_structs) \
279 ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
281 #define image_g_new0(image,struct_type, n_structs) \
282 ((struct_type *) image_g_malloc0 (image, ((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_type_array_get (modreq, 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_type_array_get (modopt, 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_type_array_get (mb->parameters, 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_type_array_get (mb->opt_types, 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, monotype_cast (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 (MonoImage *image, 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 = image_g_new0 (image, 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 (monotype_cast (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, monotype_cast (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 res = mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1125 if (!res)
1126 return NULL;
1128 return g_memdup (res, sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (res->num_attrs - MONO_ZERO_LEN_ARRAY));
1131 static gboolean
1132 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1134 /* FIXME: Need to do more checks */
1135 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1136 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1138 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1139 return FALSE;
1142 return TRUE;
1145 static MonoCustomAttrInfo*
1146 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1148 int i, index, count, not_visible;
1149 MonoCustomAttrInfo *ainfo;
1150 MonoReflectionCustomAttr *cattr;
1152 if (!cattrs)
1153 return NULL;
1154 /* FIXME: check in assembly the Run flag is set */
1156 count = mono_array_length (cattrs);
1158 /* Skip nonpublic attributes since MS.NET seems to do the same */
1159 /* FIXME: This needs to be done more globally */
1160 not_visible = 0;
1161 for (i = 0; i < count; ++i) {
1162 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1163 if (!custom_attr_visible (image, cattr))
1164 not_visible ++;
1166 count -= not_visible;
1168 ainfo = image_g_malloc0 (alloc_img, sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
1170 ainfo->image = image;
1171 ainfo->num_attrs = count;
1172 ainfo->cached = alloc_img != NULL;
1173 index = 0;
1174 for (i = 0; i < count; ++i) {
1175 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1176 if (custom_attr_visible (image, cattr)) {
1177 unsigned char *saved = mono_image_alloc (image, mono_array_length (cattr->data));
1178 memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1179 ainfo->attrs [index].ctor = cattr->ctor->method;
1180 ainfo->attrs [index].data = saved;
1181 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1182 index ++;
1186 return ainfo;
1190 * LOCKING: Acquires the loader lock.
1192 static void
1193 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1195 MonoCustomAttrInfo *ainfo, *tmp;
1197 if (!cattrs || !mono_array_length (cattrs))
1198 return;
1200 ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1202 mono_loader_lock ();
1203 tmp = mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1204 if (tmp)
1205 mono_custom_attrs_free (tmp);
1206 mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1207 mono_loader_unlock ();
1211 void
1212 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1214 if (!ainfo->cached)
1215 g_free (ainfo);
1219 * idx is the table index of the object
1220 * type is one of MONO_CUSTOM_ATTR_*
1222 static void
1223 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1225 MonoDynamicTable *table;
1226 MonoReflectionCustomAttr *cattr;
1227 guint32 *values;
1228 guint32 count, i, token;
1229 char blob_size [6];
1230 char *p = blob_size;
1232 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1233 if (!cattrs)
1234 return;
1235 count = mono_array_length (cattrs);
1236 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1237 table->rows += count;
1238 alloc_table (table, table->rows);
1239 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1240 idx <<= MONO_CUSTOM_ATTR_BITS;
1241 idx |= type;
1242 for (i = 0; i < count; ++i) {
1243 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1244 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1245 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE);
1246 type = mono_metadata_token_index (token);
1247 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1248 switch (mono_metadata_token_table (token)) {
1249 case MONO_TABLE_METHOD:
1250 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1251 break;
1252 case MONO_TABLE_MEMBERREF:
1253 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1254 break;
1255 default:
1256 g_warning ("got wrong token in custom attr");
1257 continue;
1259 values [MONO_CUSTOM_ATTR_TYPE] = type;
1260 p = blob_size;
1261 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1262 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1263 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1264 values += MONO_CUSTOM_ATTR_SIZE;
1265 ++table->next_idx;
1269 static void
1270 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1272 MonoDynamicTable *table;
1273 guint32 *values;
1274 guint32 count, i, idx;
1275 MonoReflectionPermissionSet *perm;
1277 if (!permissions)
1278 return;
1280 count = mono_array_length (permissions);
1281 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1282 table->rows += count;
1283 alloc_table (table, table->rows);
1285 for (i = 0; i < mono_array_length (permissions); ++i) {
1286 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1288 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1290 idx = mono_metadata_token_index (parent_token);
1291 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1292 switch (mono_metadata_token_table (parent_token)) {
1293 case MONO_TABLE_TYPEDEF:
1294 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1295 break;
1296 case MONO_TABLE_METHOD:
1297 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1298 break;
1299 case MONO_TABLE_ASSEMBLY:
1300 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1301 break;
1302 default:
1303 g_assert_not_reached ();
1306 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1307 values [MONO_DECL_SECURITY_PARENT] = idx;
1308 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1310 ++table->next_idx;
1315 * Fill in the MethodDef and ParamDef tables for a method.
1316 * This is used for both normal methods and constructors.
1318 static void
1319 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1321 MonoDynamicTable *table;
1322 guint32 *values;
1323 guint i, count;
1325 /* room in this table is already allocated */
1326 table = &assembly->tables [MONO_TABLE_METHOD];
1327 *mb->table_idx = table->next_idx ++;
1328 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1329 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1330 values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1331 values [MONO_METHOD_FLAGS] = mb->attrs;
1332 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1333 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1334 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1336 table = &assembly->tables [MONO_TABLE_PARAM];
1337 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1339 mono_image_add_decl_security (assembly,
1340 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1342 if (mb->pinfo) {
1343 MonoDynamicTable *mtable;
1344 guint32 *mvalues;
1346 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1347 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1349 count = 0;
1350 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1351 if (mono_array_get (mb->pinfo, gpointer, i))
1352 count++;
1354 table->rows += count;
1355 alloc_table (table, table->rows);
1356 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1357 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1358 MonoReflectionParamBuilder *pb;
1359 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1360 values [MONO_PARAM_FLAGS] = pb->attrs;
1361 values [MONO_PARAM_SEQUENCE] = i;
1362 if (pb->name != NULL) {
1363 values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1364 } else {
1365 values [MONO_PARAM_NAME] = 0;
1367 values += MONO_PARAM_SIZE;
1368 if (pb->marshal_info) {
1369 mtable->rows++;
1370 alloc_table (mtable, mtable->rows);
1371 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1372 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1373 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1375 pb->table_idx = table->next_idx++;
1376 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1377 guint32 field_type = 0;
1378 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1379 mtable->rows ++;
1380 alloc_table (mtable, mtable->rows);
1381 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1382 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1383 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1384 mvalues [MONO_CONSTANT_TYPE] = field_type;
1385 mvalues [MONO_CONSTANT_PADDING] = 0;
1392 static void
1393 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1395 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1397 rmb->ilgen = mb->ilgen;
1398 rmb->rtype = monotype_cast (mb->rtype);
1399 rmb->parameters = mb->parameters;
1400 rmb->generic_params = mb->generic_params;
1401 rmb->generic_container = mb->generic_container;
1402 rmb->opt_types = NULL;
1403 rmb->pinfo = mb->pinfo;
1404 rmb->attrs = mb->attrs;
1405 rmb->iattrs = mb->iattrs;
1406 rmb->call_conv = mb->call_conv;
1407 rmb->code = mb->code;
1408 rmb->type = mb->type;
1409 rmb->name = mb->name;
1410 rmb->table_idx = &mb->table_idx;
1411 rmb->init_locals = mb->init_locals;
1412 rmb->skip_visibility = FALSE;
1413 rmb->return_modreq = mb->return_modreq;
1414 rmb->return_modopt = mb->return_modopt;
1415 rmb->param_modreq = mb->param_modreq;
1416 rmb->param_modopt = mb->param_modopt;
1417 rmb->permissions = mb->permissions;
1418 rmb->mhandle = mb->mhandle;
1419 rmb->nrefs = 0;
1420 rmb->refs = NULL;
1422 if (mb->dll) {
1423 rmb->charset = mb->charset;
1424 rmb->extra_flags = mb->extra_flags;
1425 rmb->native_cc = mb->native_cc;
1426 rmb->dllentry = mb->dllentry;
1427 rmb->dll = mb->dll;
1431 static void
1432 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1434 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1436 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1438 rmb->ilgen = mb->ilgen;
1439 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1440 rmb->parameters = mb->parameters;
1441 rmb->generic_params = NULL;
1442 rmb->generic_container = NULL;
1443 rmb->opt_types = NULL;
1444 rmb->pinfo = mb->pinfo;
1445 rmb->attrs = mb->attrs;
1446 rmb->iattrs = mb->iattrs;
1447 rmb->call_conv = mb->call_conv;
1448 rmb->code = NULL;
1449 rmb->type = mb->type;
1450 rmb->name = mono_string_new (mono_domain_get (), name);
1451 rmb->table_idx = &mb->table_idx;
1452 rmb->init_locals = mb->init_locals;
1453 rmb->skip_visibility = FALSE;
1454 rmb->return_modreq = NULL;
1455 rmb->return_modopt = NULL;
1456 rmb->param_modreq = mb->param_modreq;
1457 rmb->param_modopt = mb->param_modopt;
1458 rmb->permissions = mb->permissions;
1459 rmb->mhandle = mb->mhandle;
1460 rmb->nrefs = 0;
1461 rmb->refs = NULL;
1464 static void
1465 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1467 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1469 rmb->ilgen = mb->ilgen;
1470 rmb->rtype = mb->rtype;
1471 rmb->parameters = mb->parameters;
1472 rmb->generic_params = NULL;
1473 rmb->generic_container = NULL;
1474 rmb->opt_types = NULL;
1475 rmb->pinfo = NULL;
1476 rmb->attrs = mb->attrs;
1477 rmb->iattrs = 0;
1478 rmb->call_conv = mb->call_conv;
1479 rmb->code = NULL;
1480 rmb->type = (MonoObject *) mb->owner;
1481 rmb->name = mb->name;
1482 rmb->table_idx = NULL;
1483 rmb->init_locals = mb->init_locals;
1484 rmb->skip_visibility = mb->skip_visibility;
1485 rmb->return_modreq = NULL;
1486 rmb->return_modopt = NULL;
1487 rmb->param_modreq = NULL;
1488 rmb->param_modopt = NULL;
1489 rmb->permissions = NULL;
1490 rmb->mhandle = mb->mhandle;
1491 rmb->nrefs = 0;
1492 rmb->refs = NULL;
1495 static void
1496 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1498 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1499 MonoDynamicTable *table;
1500 guint32 *values;
1501 guint32 tok;
1503 if (!mb->override_method)
1504 return;
1506 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1507 table->rows ++;
1508 alloc_table (table, table->rows);
1509 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1510 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1511 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1513 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE, FALSE);
1514 switch (mono_metadata_token_table (tok)) {
1515 case MONO_TABLE_MEMBERREF:
1516 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1517 break;
1518 case MONO_TABLE_METHOD:
1519 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1520 break;
1521 default:
1522 g_assert_not_reached ();
1524 values [MONO_METHODIMPL_DECLARATION] = tok;
1527 static void
1528 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1530 MonoDynamicTable *table;
1531 guint32 *values;
1532 ReflectionMethodBuilder rmb;
1533 int i;
1535 reflection_methodbuilder_from_method_builder (&rmb, mb);
1537 mono_image_basic_method (&rmb, assembly);
1538 mb->table_idx = *rmb.table_idx;
1540 if (mb->dll) { /* It's a P/Invoke method */
1541 guint32 moduleref;
1542 /* map CharSet values to on-disk values */
1543 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1544 int extra_flags = mb->extra_flags;
1545 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1546 table->rows ++;
1547 alloc_table (table, table->rows);
1548 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1550 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1551 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1552 if (mb->dllentry)
1553 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1554 else
1555 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1556 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1557 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1558 table = &assembly->tables [MONO_TABLE_MODULEREF];
1559 table->rows ++;
1560 alloc_table (table, table->rows);
1561 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1562 values [MONO_IMPLMAP_SCOPE] = table->rows;
1566 if (mb->generic_params) {
1567 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1568 table->rows += mono_array_length (mb->generic_params);
1569 alloc_table (table, table->rows);
1570 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1571 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1573 mono_image_get_generic_param_info (
1574 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1580 static void
1581 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1583 ReflectionMethodBuilder rmb;
1585 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1587 mono_image_basic_method (&rmb, assembly);
1588 mb->table_idx = *rmb.table_idx;
1591 static char*
1592 type_get_fully_qualified_name (MonoType *type)
1594 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1597 static char*
1598 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1599 MonoClass *klass;
1600 MonoAssembly *ta;
1602 klass = my_mono_class_from_mono_type (type);
1603 if (!klass)
1604 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1605 ta = klass->image->assembly;
1606 if (ta->dynamic || (ta == ass)) {
1607 if (klass->generic_class || klass->generic_container)
1608 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1609 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1610 else
1611 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1614 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1617 static guint32
1618 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
1620 SigBuffer buf;
1621 guint32 idx, i;
1623 if (!assembly->save)
1624 return 0;
1626 sigbuffer_init (&buf, 32);
1628 sigbuffer_add_value (&buf, 0x06);
1629 /* encode custom attributes before the type */
1630 /* FIXME: This should probably go in encode_type () */
1631 if (type->num_mods) {
1632 for (i = 0; i < type->num_mods; ++i) {
1633 if (type->modifiers [i].required)
1634 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1635 else
1636 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1637 sigbuffer_add_value (&buf, type->modifiers [i].token);
1640 encode_type (assembly, type, &buf);
1641 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1642 sigbuffer_free (&buf);
1643 return idx;
1646 static guint32
1647 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1649 SigBuffer buf;
1650 guint32 idx;
1652 sigbuffer_init (&buf, 32);
1654 sigbuffer_add_value (&buf, 0x06);
1655 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1656 /* encode custom attributes before the type */
1657 encode_reflection_type (assembly, monotype_cast (fb->type), &buf);
1658 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1659 sigbuffer_free (&buf);
1660 return idx;
1663 static guint32
1664 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1665 char blob_size [64];
1666 char *b = blob_size;
1667 char *p, *box_val;
1668 char* buf;
1669 guint32 idx = 0, len = 0, dummy = 0;
1670 #ifdef ARM_FPU_FPA
1671 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1672 guint32 fpa_double [2];
1673 guint32 *fpa_p;
1674 #endif
1675 #endif
1677 p = buf = g_malloc (64);
1678 if (!val) {
1679 *ret_type = MONO_TYPE_CLASS;
1680 len = 4;
1681 box_val = (char*)&dummy;
1682 } else {
1683 box_val = ((char*)val) + sizeof (MonoObject);
1684 *ret_type = val->vtable->klass->byval_arg.type;
1686 handle_enum:
1687 switch (*ret_type) {
1688 case MONO_TYPE_BOOLEAN:
1689 case MONO_TYPE_U1:
1690 case MONO_TYPE_I1:
1691 len = 1;
1692 break;
1693 case MONO_TYPE_CHAR:
1694 case MONO_TYPE_U2:
1695 case MONO_TYPE_I2:
1696 len = 2;
1697 break;
1698 case MONO_TYPE_U4:
1699 case MONO_TYPE_I4:
1700 case MONO_TYPE_R4:
1701 len = 4;
1702 break;
1703 case MONO_TYPE_U8:
1704 case MONO_TYPE_I8:
1705 len = 8;
1706 break;
1707 case MONO_TYPE_R8:
1708 len = 8;
1709 #ifdef ARM_FPU_FPA
1710 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1711 fpa_p = (guint32*)box_val;
1712 fpa_double [0] = fpa_p [1];
1713 fpa_double [1] = fpa_p [0];
1714 box_val = (char*)fpa_double;
1715 #endif
1716 #endif
1717 break;
1718 case MONO_TYPE_VALUETYPE:
1719 if (val->vtable->klass->enumtype) {
1720 *ret_type = mono_class_enum_basetype (val->vtable->klass)->type;
1721 goto handle_enum;
1722 } else
1723 g_error ("we can't encode valuetypes");
1724 case MONO_TYPE_CLASS:
1725 break;
1726 case MONO_TYPE_STRING: {
1727 MonoString *str = (MonoString*)val;
1728 /* there is no signature */
1729 len = str->length * 2;
1730 mono_metadata_encode_value (len, b, &b);
1731 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1733 char *swapped = g_malloc (2 * mono_string_length (str));
1734 const char *p = (const char*)mono_string_chars (str);
1736 swap_with_size (swapped, p, 2, mono_string_length (str));
1737 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1738 g_free (swapped);
1740 #else
1741 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1742 #endif
1744 g_free (buf);
1745 return idx;
1747 case MONO_TYPE_GENERICINST:
1748 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
1749 goto handle_enum;
1750 default:
1751 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1754 /* there is no signature */
1755 mono_metadata_encode_value (len, b, &b);
1756 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1757 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1758 swap_with_size (blob_size, box_val, len, 1);
1759 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1760 #else
1761 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1762 #endif
1764 g_free (buf);
1765 return idx;
1768 static guint32
1769 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1770 char *str;
1771 SigBuffer buf;
1772 guint32 idx, len;
1774 sigbuffer_init (&buf, 32);
1776 sigbuffer_add_value (&buf, minfo->type);
1778 switch (minfo->type) {
1779 case MONO_NATIVE_BYVALTSTR:
1780 case MONO_NATIVE_BYVALARRAY:
1781 sigbuffer_add_value (&buf, minfo->count);
1782 break;
1783 case MONO_NATIVE_LPARRAY:
1784 if (minfo->eltype || minfo->has_size) {
1785 sigbuffer_add_value (&buf, minfo->eltype);
1786 if (minfo->has_size) {
1787 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
1788 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
1790 /* LAMESPEC: ElemMult is undocumented */
1791 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1794 break;
1795 case MONO_NATIVE_CUSTOM:
1796 if (minfo->guid) {
1797 str = mono_string_to_utf8 (minfo->guid);
1798 len = strlen (str);
1799 sigbuffer_add_value (&buf, len);
1800 sigbuffer_add_mem (&buf, str, len);
1801 g_free (str);
1802 } else {
1803 sigbuffer_add_value (&buf, 0);
1805 /* native type name */
1806 sigbuffer_add_value (&buf, 0);
1807 /* custom marshaler type name */
1808 if (minfo->marshaltype || minfo->marshaltyperef) {
1809 if (minfo->marshaltyperef)
1810 str = type_get_fully_qualified_name (monotype_cast (minfo->marshaltyperef)->type);
1811 else
1812 str = mono_string_to_utf8 (minfo->marshaltype);
1813 len = strlen (str);
1814 sigbuffer_add_value (&buf, len);
1815 sigbuffer_add_mem (&buf, str, len);
1816 g_free (str);
1817 } else {
1818 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
1819 sigbuffer_add_value (&buf, 0);
1821 if (minfo->mcookie) {
1822 str = mono_string_to_utf8 (minfo->mcookie);
1823 len = strlen (str);
1824 sigbuffer_add_value (&buf, len);
1825 sigbuffer_add_mem (&buf, str, len);
1826 g_free (str);
1827 } else {
1828 sigbuffer_add_value (&buf, 0);
1830 break;
1831 default:
1832 break;
1834 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1835 sigbuffer_free (&buf);
1836 return idx;
1839 static void
1840 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1842 MonoDynamicTable *table;
1843 guint32 *values;
1845 /* maybe this fixup should be done in the C# code */
1846 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1847 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1848 table = &assembly->tables [MONO_TABLE_FIELD];
1849 fb->table_idx = table->next_idx ++;
1850 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1851 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1852 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
1853 values [MONO_FIELD_FLAGS] = fb->attrs;
1854 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1856 if (fb->offset != -1) {
1857 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1858 table->rows ++;
1859 alloc_table (table, table->rows);
1860 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1861 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1862 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1864 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1865 guint32 field_type = 0;
1866 table = &assembly->tables [MONO_TABLE_CONSTANT];
1867 table->rows ++;
1868 alloc_table (table, table->rows);
1869 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1870 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1871 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1872 values [MONO_CONSTANT_TYPE] = field_type;
1873 values [MONO_CONSTANT_PADDING] = 0;
1875 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1876 guint32 rva_idx;
1877 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1878 table->rows ++;
1879 alloc_table (table, table->rows);
1880 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1881 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1883 * We store it in the code section because it's simpler for now.
1885 if (fb->rva_data) {
1886 if (mono_array_length (fb->rva_data) >= 10)
1887 stream_data_align (&assembly->code);
1888 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1889 } else
1890 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1891 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1893 if (fb->marshal_info) {
1894 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1895 table->rows ++;
1896 alloc_table (table, table->rows);
1897 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1898 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1899 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1903 static guint32
1904 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1906 SigBuffer buf;
1907 guint32 nparams = 0;
1908 MonoReflectionMethodBuilder *mb = fb->get_method;
1909 MonoReflectionMethodBuilder *smb = fb->set_method;
1910 guint32 idx, i;
1912 if (mb && mb->parameters)
1913 nparams = mono_array_length (mb->parameters);
1914 if (!mb && smb && smb->parameters)
1915 nparams = mono_array_length (smb->parameters) - 1;
1916 sigbuffer_init (&buf, 32);
1917 sigbuffer_add_byte (&buf, 0x08);
1918 sigbuffer_add_value (&buf, nparams);
1919 if (mb) {
1920 encode_reflection_type (assembly, monotype_cast (mb->rtype), &buf);
1921 for (i = 0; i < nparams; ++i) {
1922 MonoReflectionType *pt = mono_type_array_get (mb->parameters, i);
1923 encode_reflection_type (assembly, pt, &buf);
1925 } else if (smb && smb->parameters) {
1926 /* the property type is the last param */
1927 encode_reflection_type (assembly, mono_type_array_get (smb->parameters, nparams), &buf);
1928 for (i = 0; i < nparams; ++i) {
1929 MonoReflectionType *pt = mono_type_array_get (smb->parameters, i);
1930 encode_reflection_type (assembly, pt, &buf);
1932 } else {
1933 encode_reflection_type (assembly, monotype_cast (fb->type), &buf);
1936 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1937 sigbuffer_free (&buf);
1938 return idx;
1941 static void
1942 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1944 MonoDynamicTable *table;
1945 guint32 *values;
1946 guint num_methods = 0;
1947 guint32 semaidx;
1950 * we need to set things in the following tables:
1951 * PROPERTYMAP (info already filled in _get_type_info ())
1952 * PROPERTY (rows already preallocated in _get_type_info ())
1953 * METHOD (method info already done with the generic method code)
1954 * METHODSEMANTICS
1956 table = &assembly->tables [MONO_TABLE_PROPERTY];
1957 pb->table_idx = table->next_idx ++;
1958 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1959 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1960 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1961 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1963 /* FIXME: we still don't handle 'other' methods */
1964 if (pb->get_method) num_methods ++;
1965 if (pb->set_method) num_methods ++;
1967 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1968 table->rows += num_methods;
1969 alloc_table (table, table->rows);
1971 if (pb->get_method) {
1972 semaidx = table->next_idx ++;
1973 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1974 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1975 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1976 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1978 if (pb->set_method) {
1979 semaidx = table->next_idx ++;
1980 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1981 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1982 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1983 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1987 static void
1988 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1990 MonoDynamicTable *table;
1991 guint32 *values;
1992 guint num_methods = 0;
1993 guint32 semaidx;
1996 * we need to set things in the following tables:
1997 * EVENTMAP (info already filled in _get_type_info ())
1998 * EVENT (rows already preallocated in _get_type_info ())
1999 * METHOD (method info already done with the generic method code)
2000 * METHODSEMANTICS
2002 table = &assembly->tables [MONO_TABLE_EVENT];
2003 eb->table_idx = table->next_idx ++;
2004 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2005 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2006 values [MONO_EVENT_FLAGS] = eb->attrs;
2007 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
2010 * FIXME: we still don't handle 'other' methods
2012 if (eb->add_method) num_methods ++;
2013 if (eb->remove_method) num_methods ++;
2014 if (eb->raise_method) num_methods ++;
2016 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2017 table->rows += num_methods;
2018 alloc_table (table, table->rows);
2020 if (eb->add_method) {
2021 semaidx = table->next_idx ++;
2022 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2023 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2024 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2025 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2027 if (eb->remove_method) {
2028 semaidx = table->next_idx ++;
2029 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2030 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2031 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2032 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2034 if (eb->raise_method) {
2035 semaidx = table->next_idx ++;
2036 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2037 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2038 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2039 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2043 static void
2044 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2046 MonoDynamicTable *table;
2047 guint32 num_constraints, i;
2048 guint32 *values;
2049 guint32 table_idx;
2051 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2052 num_constraints = gparam->iface_constraints ?
2053 mono_array_length (gparam->iface_constraints) : 0;
2054 table->rows += num_constraints;
2055 if (gparam->base_type)
2056 table->rows++;
2057 alloc_table (table, table->rows);
2059 if (gparam->base_type) {
2060 table_idx = table->next_idx ++;
2061 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2063 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2064 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2065 assembly, gparam->base_type->type);
2068 for (i = 0; i < num_constraints; i++) {
2069 MonoReflectionType *constraint = mono_array_get (
2070 gparam->iface_constraints, gpointer, i);
2072 table_idx = table->next_idx ++;
2073 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2075 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2076 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2077 assembly, constraint->type);
2081 static void
2082 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2084 GenericParamTableEntry *entry;
2087 * The GenericParam table must be sorted according to the `owner' field.
2088 * We need to do this sorting prior to writing the GenericParamConstraint
2089 * table, since we have to use the final GenericParam table indices there
2090 * and they must also be sorted.
2093 entry = g_new0 (GenericParamTableEntry, 1);
2094 entry->owner = owner;
2095 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2096 MOVING_GC_REGISTER (&entry->gparam);
2097 entry->gparam = gparam;
2099 g_ptr_array_add (assembly->gen_params, entry);
2102 static void
2103 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2105 MonoDynamicTable *table;
2106 MonoGenericParam *param;
2107 guint32 *values;
2108 guint32 table_idx;
2110 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2111 table_idx = table->next_idx ++;
2112 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2114 param = entry->gparam->type.type->data.generic_param;
2116 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2117 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2118 values [MONO_GENERICPARAM_NUMBER] = param->num;
2119 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
2121 mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2123 encode_constraints (entry->gparam, table_idx, assembly);
2126 static guint32
2127 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2129 MonoDynamicTable *table;
2130 guint32 token;
2131 guint32 *values;
2132 guint32 cols [MONO_ASSEMBLY_SIZE];
2133 const char *pubkey;
2134 guint32 publen;
2136 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2137 return token;
2139 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2140 table = &assembly->tables [MONO_TABLE_MODULEREF];
2141 token = table->next_idx ++;
2142 table->rows ++;
2143 alloc_table (table, table->rows);
2144 values = table->values + token * MONO_MODULEREF_SIZE;
2145 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2147 token <<= MONO_RESOLTION_SCOPE_BITS;
2148 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2149 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2151 return token;
2154 if (image->assembly->dynamic)
2155 /* FIXME: */
2156 memset (cols, 0, sizeof (cols));
2157 else {
2158 /* image->assembly->image is the manifest module */
2159 image = image->assembly->image;
2160 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2163 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2164 token = table->next_idx ++;
2165 table->rows ++;
2166 alloc_table (table, table->rows);
2167 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2168 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2169 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2170 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2171 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2172 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2173 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2174 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2175 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2177 if (strcmp ("", image->assembly->aname.culture)) {
2178 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2179 image->assembly->aname.culture);
2182 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2183 guchar pubtoken [9];
2184 pubtoken [0] = 8;
2185 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2186 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2187 } else {
2188 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2190 token <<= MONO_RESOLTION_SCOPE_BITS;
2191 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2192 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2193 return token;
2196 static guint32
2197 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2199 MonoDynamicTable *table;
2200 guint32 *values;
2201 guint32 token;
2202 SigBuffer buf;
2204 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2205 return token;
2207 sigbuffer_init (&buf, 32);
2208 switch (type->type) {
2209 case MONO_TYPE_FNPTR:
2210 case MONO_TYPE_PTR:
2211 case MONO_TYPE_SZARRAY:
2212 case MONO_TYPE_ARRAY:
2213 case MONO_TYPE_VAR:
2214 case MONO_TYPE_MVAR:
2215 case MONO_TYPE_GENERICINST:
2216 encode_type (assembly, type, &buf);
2217 break;
2218 case MONO_TYPE_CLASS:
2219 case MONO_TYPE_VALUETYPE: {
2220 MonoClass *k = mono_class_from_mono_type (type);
2221 if (!k || !k->generic_container) {
2222 sigbuffer_free (&buf);
2223 return 0;
2225 encode_type (assembly, type, &buf);
2226 break;
2228 default:
2229 sigbuffer_free (&buf);
2230 return 0;
2233 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2234 if (assembly->save) {
2235 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2236 alloc_table (table, table->rows + 1);
2237 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2238 values [MONO_TYPESPEC_SIGNATURE] = token;
2240 sigbuffer_free (&buf);
2242 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2243 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2244 table->next_idx ++;
2245 return token;
2248 static guint32
2249 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2251 MonoDynamicTable *table;
2252 guint32 *values;
2253 guint32 token, scope, enclosing;
2254 MonoClass *klass;
2256 /* if the type requires a typespec, we must try that first*/
2257 if (try_typespec && (token = create_typespec (assembly, type)))
2258 return token;
2259 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2260 if (token)
2261 return token;
2262 klass = my_mono_class_from_mono_type (type);
2263 if (!klass)
2264 klass = mono_class_from_mono_type (type);
2267 * If it's in the same module and not a generic type parameter:
2269 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2270 (type->type != MONO_TYPE_MVAR)) {
2271 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2272 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2273 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2274 return token;
2277 if (klass->nested_in) {
2278 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2279 /* get the typeref idx of the enclosing type */
2280 enclosing >>= MONO_TYPEDEFORREF_BITS;
2281 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2282 } else {
2283 scope = resolution_scope_from_image (assembly, klass->image);
2285 table = &assembly->tables [MONO_TABLE_TYPEREF];
2286 if (assembly->save) {
2287 alloc_table (table, table->rows + 1);
2288 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2289 values [MONO_TYPEREF_SCOPE] = scope;
2290 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2291 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2293 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2294 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2295 table->next_idx ++;
2296 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2297 return token;
2301 * Despite the name, we handle also TypeSpec (with the above helper).
2303 static guint32
2304 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2306 return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2310 * Insert a memberef row into the metadata: the token that point to the memberref
2311 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2312 * mono_image_get_fieldref_token()).
2313 * The sig param is an index to an already built signature.
2315 static guint32
2316 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2318 MonoDynamicTable *table;
2319 guint32 *values;
2320 guint32 token, pclass;
2321 guint32 parent;
2323 parent = mono_image_typedef_or_ref (assembly, type);
2324 switch (parent & MONO_TYPEDEFORREF_MASK) {
2325 case MONO_TYPEDEFORREF_TYPEREF:
2326 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2327 break;
2328 case MONO_TYPEDEFORREF_TYPESPEC:
2329 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2330 break;
2331 case MONO_TYPEDEFORREF_TYPEDEF:
2332 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2333 break;
2334 default:
2335 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2336 return 0;
2338 /* extract the index */
2339 parent >>= MONO_TYPEDEFORREF_BITS;
2341 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2343 if (assembly->save) {
2344 alloc_table (table, table->rows + 1);
2345 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2346 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2347 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2348 values [MONO_MEMBERREF_SIGNATURE] = sig;
2351 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2352 table->next_idx ++;
2354 return token;
2357 static guint32
2358 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2360 guint32 token;
2361 MonoMethodSignature *sig;
2363 create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2365 if (create_typespec) {
2366 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2367 if (token)
2368 return token;
2371 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2372 if (token && !create_typespec)
2373 return token;
2375 g_assert (!method->is_inflated);
2376 if (!token) {
2378 * A methodref signature can't contain an unmanaged calling convention.
2380 sig = mono_metadata_signature_dup (mono_method_signature (method));
2381 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2382 sig->call_convention = MONO_CALL_DEFAULT;
2383 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2384 method->name, method_encode_signature (assembly, sig));
2385 g_free (sig);
2386 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2389 if (create_typespec) {
2390 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2391 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2392 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2394 if (assembly->save) {
2395 guint32 *values;
2397 alloc_table (table, table->rows + 1);
2398 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2399 values [MONO_METHODSPEC_METHOD] = token;
2400 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2403 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2404 table->next_idx ++;
2405 /*methodspec and memberef tokens are diferent, */
2406 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2407 return token;
2409 return token;
2412 static guint32
2413 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2415 guint32 token;
2416 ReflectionMethodBuilder rmb;
2417 char *name;
2419 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2420 if (token)
2421 return token;
2423 name = mono_string_to_utf8 (method->name);
2424 reflection_methodbuilder_from_method_builder (&rmb, method);
2427 * A methodref signature can't contain an unmanaged calling convention.
2428 * Since some flags are encoded as part of call_conv, we need to check against it.
2430 if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2431 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2432 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2433 name, method_builder_encode_signature (assembly, &rmb));
2435 g_free (name);
2436 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2437 return token;
2440 static guint32
2441 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2442 const gchar *name, guint32 sig)
2444 MonoDynamicTable *table;
2445 guint32 token;
2446 guint32 *values;
2448 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2450 if (assembly->save) {
2451 alloc_table (table, table->rows + 1);
2452 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2453 values [MONO_MEMBERREF_CLASS] = original;
2454 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2455 values [MONO_MEMBERREF_SIGNATURE] = sig;
2458 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2459 table->next_idx ++;
2461 return token;
2464 static guint32
2465 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2467 SigBuffer buf;
2468 int i;
2469 guint32 nparams = mono_array_length (mb->generic_params);
2470 guint32 idx;
2472 if (!assembly->save)
2473 return 0;
2475 sigbuffer_init (&buf, 32);
2477 sigbuffer_add_value (&buf, 0xa);
2478 sigbuffer_add_value (&buf, nparams);
2480 for (i = 0; i < nparams; i++) {
2481 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2482 sigbuffer_add_value (&buf, i);
2485 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2486 sigbuffer_free (&buf);
2487 return idx;
2490 static guint32
2491 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2493 MonoDynamicTable *table;
2494 guint32 *values;
2495 guint32 token, mtoken = 0;
2497 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2498 if (token)
2499 return token;
2501 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2503 mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2504 switch (mono_metadata_token_table (mtoken)) {
2505 case MONO_TABLE_MEMBERREF:
2506 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2507 break;
2508 case MONO_TABLE_METHOD:
2509 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2510 break;
2511 default:
2512 g_assert_not_reached ();
2515 if (assembly->save) {
2516 alloc_table (table, table->rows + 1);
2517 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2518 values [MONO_METHODSPEC_METHOD] = mtoken;
2519 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2522 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2523 table->next_idx ++;
2525 mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2526 return token;
2529 static guint32
2530 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2532 guint32 token;
2534 if (mb->generic_params && create_methodspec)
2535 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2537 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2538 if (token)
2539 return token;
2541 token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2542 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2543 return token;
2546 static guint32
2547 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2549 guint32 token;
2550 ReflectionMethodBuilder rmb;
2551 char *name;
2553 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2554 if (token)
2555 return token;
2557 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2559 name = mono_string_to_utf8 (rmb.name);
2560 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2561 name, method_builder_encode_signature (assembly, &rmb));
2563 g_free (name);
2564 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2565 return token;
2568 static gboolean
2569 is_field_on_inst (MonoClassField *field)
2571 return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2575 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2577 static MonoType*
2578 get_field_on_inst_generic_type (MonoClassField *field)
2580 MonoDynamicGenericClass *dgclass;
2581 int field_index;
2583 g_assert (is_field_on_inst (field));
2585 dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2586 field_index = field - dgclass->fields;
2588 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
2589 return dgclass->field_generic_types [field_index];
2592 static guint32
2593 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2595 MonoType *type;
2596 guint32 token;
2597 MonoClassField *field;
2599 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2600 if (token)
2601 return token;
2602 g_assert (f->field->parent);
2604 field = f->field;
2605 if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2606 int index = field - field->parent->fields;
2607 type = field->parent->generic_class->container_class->fields [index].type;
2608 } else {
2609 if (is_field_on_inst (f->field))
2610 type = get_field_on_inst_generic_type (f->field);
2611 else
2612 type = f->field->type;
2614 token = mono_image_get_memberref_token (assembly, &f->field->parent->byval_arg,
2615 mono_field_get_name (f->field),
2616 fieldref_encode_signature (assembly, type));
2617 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2618 return token;
2621 static guint32
2622 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
2624 guint32 token;
2625 MonoClass *klass;
2626 MonoGenericClass *gclass;
2627 MonoDynamicGenericClass *dgclass;
2628 MonoReflectionFieldBuilder *fb = f->fb;
2629 char *name;
2631 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2632 if (token)
2633 return token;
2634 klass = mono_class_from_mono_type (f->inst->type.type);
2635 gclass = f->inst->type.type->data.generic_class;
2636 g_assert (gclass->is_dynamic);
2637 dgclass = (MonoDynamicGenericClass *) gclass;
2639 name = mono_string_to_utf8 (fb->name);
2640 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name,
2641 field_encode_signature (assembly, fb));
2642 g_free (name);
2643 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER (token));
2644 return token;
2647 static guint32
2648 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
2650 guint32 sig, token;
2651 MonoClass *klass;
2652 MonoGenericClass *gclass;
2653 MonoDynamicGenericClass *dgclass;
2654 MonoReflectionCtorBuilder *cb = c->cb;
2655 ReflectionMethodBuilder rmb;
2656 char *name;
2658 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
2660 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, c));
2661 if (token)
2662 return token;
2663 klass = mono_class_from_mono_type (c->inst->type.type);
2664 gclass = c->inst->type.type->data.generic_class;
2665 g_assert (gclass->is_dynamic);
2666 dgclass = (MonoDynamicGenericClass *) gclass;
2668 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
2670 name = mono_string_to_utf8 (rmb.name);
2672 sig = method_builder_encode_signature (assembly, &rmb);
2674 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2675 g_free (name);
2677 g_hash_table_insert (assembly->handleref, c, GUINT_TO_POINTER (token));
2678 return token;
2681 static guint32
2682 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
2684 guint32 sig, token;
2685 MonoClass *klass;
2686 MonoGenericClass *gclass;
2687 MonoReflectionMethodBuilder *mb = m->mb;
2688 ReflectionMethodBuilder rmb;
2689 char *name;
2691 if (create_methodspec && mb->generic_params)
2692 // FIXME:
2693 g_assert_not_reached ();
2695 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
2696 if (token)
2697 return token;
2698 klass = mono_class_from_mono_type (m->inst->type.type);
2699 gclass = m->inst->type.type->data.generic_class;
2700 g_assert (gclass->is_dynamic);
2702 reflection_methodbuilder_from_method_builder (&rmb, mb);
2704 name = mono_string_to_utf8 (rmb.name);
2706 sig = method_builder_encode_signature (assembly, &rmb);
2708 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2709 g_free (name);
2711 g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER (token));
2712 return token;
2715 static guint32
2716 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
2718 SigBuffer buf;
2719 int i;
2720 guint32 nparams = context->method_inst->type_argc;
2721 guint32 idx;
2723 if (!assembly->save)
2724 return 0;
2726 sigbuffer_init (&buf, 32);
2728 * FIXME: vararg, explicit_this, differenc call_conv values...
2730 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
2731 sigbuffer_add_value (&buf, nparams);
2733 for (i = 0; i < nparams; i++)
2734 encode_type (assembly, context->method_inst->type_argv [i], &buf);
2736 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2737 sigbuffer_free (&buf);
2738 return idx;
2741 static guint32
2742 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2744 MonoDynamicTable *table;
2745 guint32 *values;
2746 guint32 token, mtoken = 0, sig;
2747 MonoMethodInflated *imethod;
2748 MonoMethod *declaring;
2750 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2752 g_assert (method->is_inflated);
2753 imethod = (MonoMethodInflated *) method;
2754 declaring = imethod->declaring;
2756 sig = method_encode_signature (assembly, mono_method_signature (declaring));
2757 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2759 if (!mono_method_signature (declaring)->generic_param_count)
2760 return mtoken;
2762 switch (mono_metadata_token_table (mtoken)) {
2763 case MONO_TABLE_MEMBERREF:
2764 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2765 break;
2766 case MONO_TABLE_METHOD:
2767 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2768 break;
2769 default:
2770 g_assert_not_reached ();
2773 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
2775 if (assembly->save) {
2776 alloc_table (table, table->rows + 1);
2777 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2778 values [MONO_METHODSPEC_METHOD] = mtoken;
2779 values [MONO_METHODSPEC_SIGNATURE] = sig;
2782 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2783 table->next_idx ++;
2785 return token;
2788 static guint32
2789 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
2791 MonoMethodInflated *imethod;
2792 guint32 token;
2794 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2795 if (token)
2796 return token;
2798 g_assert (method->is_inflated);
2799 imethod = (MonoMethodInflated *) method;
2801 if (mono_method_signature (imethod->declaring)->generic_param_count) {
2802 token = method_encode_methodspec (assembly, method);
2803 } else {
2804 guint32 sig = method_encode_signature (
2805 assembly, mono_method_signature (imethod->declaring));
2806 token = mono_image_get_memberref_token (
2807 assembly, &method->klass->byval_arg, method->name, sig);
2810 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2811 return token;
2814 static guint32
2815 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
2817 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
2818 guint32 sig, token;
2820 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
2821 token = mono_image_get_memberref_token (
2822 assembly, &m->klass->byval_arg, m->name, sig);
2824 return token;
2827 static guint32
2828 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2830 MonoDynamicTable *table;
2831 MonoClass *klass;
2832 guint32 *values;
2833 guint32 token;
2834 SigBuffer buf;
2835 int count, i;
2838 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2839 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2840 * Because of this, we must not insert it into the `typeref' hash table.
2843 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2844 if (token)
2845 return token;
2847 sigbuffer_init (&buf, 32);
2849 g_assert (tb->generic_params);
2850 klass = mono_class_from_mono_type (tb->type.type);
2852 if (tb->generic_container)
2853 mono_reflection_create_generic_class (tb);
2855 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
2856 g_assert (klass->generic_container);
2857 sigbuffer_add_value (&buf, klass->byval_arg.type);
2858 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
2860 count = mono_array_length (tb->generic_params);
2861 sigbuffer_add_value (&buf, count);
2862 for (i = 0; i < count; i++) {
2863 MonoReflectionGenericParam *gparam;
2865 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2867 encode_type (assembly, gparam->type.type, &buf);
2870 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2872 if (assembly->save) {
2873 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2874 alloc_table (table, table->rows + 1);
2875 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2876 values [MONO_TYPESPEC_SIGNATURE] = token;
2878 sigbuffer_free (&buf);
2880 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2881 g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2882 table->next_idx ++;
2883 return token;
2887 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
2889 static MonoType*
2890 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
2892 int i, count, len, pos;
2893 MonoType *t;
2895 count = 0;
2896 if (modreq)
2897 count += mono_array_length (modreq);
2898 if (modopt)
2899 count += mono_array_length (modopt);
2901 if (count == 0)
2902 return mono_metadata_type_dup (NULL, type);
2904 len = sizeof (MonoType) + ((gint32)count - MONO_ZERO_LEN_ARRAY) * sizeof (MonoCustomMod);
2905 t = g_malloc (len);
2906 memcpy (t, type, len);
2908 t->num_mods = count;
2909 pos = 0;
2910 if (modreq) {
2911 for (i = 0; i < mono_array_length (modreq); ++i) {
2912 MonoReflectionType *mod = mono_type_array_get (modreq, i);
2913 t->modifiers [pos].required = 1;
2914 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod->type);
2915 pos ++;
2918 if (modopt) {
2919 for (i = 0; i < mono_array_length (modopt); ++i) {
2920 MonoReflectionType *mod = mono_type_array_get (modopt, i);
2921 t->modifiers [pos].required = 0;
2922 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod->type);
2923 pos ++;
2927 return t;
2930 static guint32
2931 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2933 MonoDynamicTable *table;
2934 MonoClass *klass;
2935 MonoType *custom = NULL;
2936 guint32 *values;
2937 guint32 token, pclass, parent, sig;
2938 gchar *name;
2940 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2941 if (token)
2942 return token;
2944 klass = mono_class_from_mono_type (fb->typeb->type);
2945 name = mono_string_to_utf8 (fb->name);
2947 /* fb->type does not include the custom modifiers */
2948 /* FIXME: We should do this in one place when a fieldbuilder is created */
2949 if (fb->modreq || fb->modopt) {
2950 custom = add_custom_modifiers (assembly, monotype_cast (fb->type)->type, fb->modreq, fb->modopt);
2951 sig = fieldref_encode_signature (assembly, custom);
2952 g_free (custom);
2953 } else {
2954 sig = fieldref_encode_signature (assembly, monotype_cast (fb->type)->type);
2957 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2958 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
2960 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2961 parent >>= MONO_TYPEDEFORREF_BITS;
2963 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2965 if (assembly->save) {
2966 alloc_table (table, table->rows + 1);
2967 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2968 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2969 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2970 values [MONO_MEMBERREF_SIGNATURE] = sig;
2973 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2974 table->next_idx ++;
2975 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2976 g_free (name);
2977 return token;
2980 static guint32
2981 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2983 SigBuffer buf;
2984 guint32 nargs;
2985 guint32 size;
2986 guint32 i, idx;
2988 if (!assembly->save)
2989 return 0;
2991 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
2992 g_assert (helper->type == 2);
2994 if (helper->arguments)
2995 nargs = mono_array_length (helper->arguments);
2996 else
2997 nargs = 0;
2999 size = 10 + (nargs * 10);
3001 sigbuffer_init (&buf, 32);
3003 /* Encode calling convention */
3004 /* Change Any to Standard */
3005 if ((helper->call_conv & 0x03) == 0x03)
3006 helper->call_conv = 0x01;
3007 /* explicit_this implies has_this */
3008 if (helper->call_conv & 0x40)
3009 helper->call_conv &= 0x20;
3011 if (helper->call_conv == 0) { /* Unmanaged */
3012 idx = helper->unmanaged_call_conv - 1;
3013 } else {
3014 /* Managed */
3015 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3016 if (helper->call_conv & 0x02) /* varargs */
3017 idx += 0x05;
3020 sigbuffer_add_byte (&buf, idx);
3021 sigbuffer_add_value (&buf, nargs);
3022 encode_reflection_type (assembly, helper->return_type, &buf);
3023 for (i = 0; i < nargs; ++i) {
3024 MonoArray *modreqs = NULL;
3025 MonoArray *modopts = NULL;
3026 MonoReflectionType *pt;
3028 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3029 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3030 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3031 modopts = mono_array_get (helper->modopts, MonoArray*, i);
3033 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3034 pt = mono_type_array_get (helper->arguments, i);
3035 encode_reflection_type (assembly, pt, &buf);
3037 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3038 sigbuffer_free (&buf);
3040 return idx;
3043 static guint32
3044 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3046 guint32 idx;
3047 MonoDynamicTable *table;
3048 guint32 *values;
3050 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3051 idx = table->next_idx ++;
3052 table->rows ++;
3053 alloc_table (table, table->rows);
3054 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3056 values [MONO_STAND_ALONE_SIGNATURE] =
3057 mono_reflection_encode_sighelper (assembly, helper);
3059 return idx;
3062 static int
3063 reflection_cc_to_file (int call_conv) {
3064 switch (call_conv & 0x3) {
3065 case 0:
3066 case 1: return MONO_CALL_DEFAULT;
3067 case 2: return MONO_CALL_VARARG;
3068 default:
3069 g_assert_not_reached ();
3071 return 0;
3074 typedef struct {
3075 MonoType *parent;
3076 MonoMethodSignature *sig;
3077 char *name;
3078 guint32 token;
3079 } ArrayMethod;
3081 static guint32
3082 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3084 guint32 nparams, i;
3085 GList *tmp;
3086 char *name;
3087 MonoMethodSignature *sig;
3088 ArrayMethod *am;
3090 name = mono_string_to_utf8 (m->name);
3091 nparams = mono_array_length (m->parameters);
3092 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
3093 sig->hasthis = 1;
3094 sig->sentinelpos = -1;
3095 sig->call_convention = reflection_cc_to_file (m->call_conv);
3096 sig->param_count = nparams;
3097 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
3098 for (i = 0; i < nparams; ++i) {
3099 MonoReflectionType *t = mono_type_array_get (m->parameters, i);
3100 sig->params [i] = t->type;
3103 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3104 am = tmp->data;
3105 if (strcmp (name, am->name) == 0 &&
3106 mono_metadata_type_equal (am->parent, m->parent->type) &&
3107 mono_metadata_signature_equal (am->sig, sig)) {
3108 g_free (name);
3109 g_free (sig);
3110 m->table_idx = am->token & 0xffffff;
3111 return am->token;
3114 am = g_new0 (ArrayMethod, 1);
3115 am->name = name;
3116 am->sig = sig;
3117 am->parent = m->parent->type;
3118 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3119 method_encode_signature (assembly, sig));
3120 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3121 m->table_idx = am->token & 0xffffff;
3122 return am->token;
3126 * Insert into the metadata tables all the info about the TypeBuilder tb.
3127 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3129 static void
3130 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3132 MonoDynamicTable *table;
3133 guint *values;
3134 int i, is_object = 0, is_system = 0;
3135 char *n;
3137 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3138 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3139 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3140 n = mono_string_to_utf8 (tb->name);
3141 if (strcmp (n, "Object") == 0)
3142 is_object++;
3143 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3144 g_free (n);
3145 n = mono_string_to_utf8 (tb->nspace);
3146 if (strcmp (n, "System") == 0)
3147 is_system++;
3148 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3149 g_free (n);
3150 if (tb->parent && !(is_system && is_object) &&
3151 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3152 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, monotype_cast (tb->parent)->type);
3153 } else {
3154 values [MONO_TYPEDEF_EXTENDS] = 0;
3156 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3157 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3160 * if we have explicitlayout or sequentiallayouts, output data in the
3161 * ClassLayout table.
3163 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3164 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3165 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3166 table->rows++;
3167 alloc_table (table, table->rows);
3168 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3169 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3170 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3171 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3174 /* handle interfaces */
3175 if (tb->interfaces) {
3176 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3177 i = table->rows;
3178 table->rows += mono_array_length (tb->interfaces);
3179 alloc_table (table, table->rows);
3180 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3181 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3182 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3183 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3184 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
3185 values += MONO_INTERFACEIMPL_SIZE;
3189 /* handle fields */
3190 if (tb->fields) {
3191 table = &assembly->tables [MONO_TABLE_FIELD];
3192 table->rows += tb->num_fields;
3193 alloc_table (table, table->rows);
3194 for (i = 0; i < tb->num_fields; ++i)
3195 mono_image_get_field_info (
3196 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3199 /* handle constructors */
3200 if (tb->ctors) {
3201 table = &assembly->tables [MONO_TABLE_METHOD];
3202 table->rows += mono_array_length (tb->ctors);
3203 alloc_table (table, table->rows);
3204 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3205 mono_image_get_ctor_info (domain,
3206 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3209 /* handle methods */
3210 if (tb->methods) {
3211 table = &assembly->tables [MONO_TABLE_METHOD];
3212 table->rows += tb->num_methods;
3213 alloc_table (table, table->rows);
3214 for (i = 0; i < tb->num_methods; ++i)
3215 mono_image_get_method_info (
3216 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3219 /* Do the same with properties etc.. */
3220 if (tb->events && mono_array_length (tb->events)) {
3221 table = &assembly->tables [MONO_TABLE_EVENT];
3222 table->rows += mono_array_length (tb->events);
3223 alloc_table (table, table->rows);
3224 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3225 table->rows ++;
3226 alloc_table (table, table->rows);
3227 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3228 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3229 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3230 for (i = 0; i < mono_array_length (tb->events); ++i)
3231 mono_image_get_event_info (
3232 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3234 if (tb->properties && mono_array_length (tb->properties)) {
3235 table = &assembly->tables [MONO_TABLE_PROPERTY];
3236 table->rows += mono_array_length (tb->properties);
3237 alloc_table (table, table->rows);
3238 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3239 table->rows ++;
3240 alloc_table (table, table->rows);
3241 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3242 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3243 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3244 for (i = 0; i < mono_array_length (tb->properties); ++i)
3245 mono_image_get_property_info (
3246 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3249 /* handle generic parameters */
3250 if (tb->generic_params) {
3251 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3252 table->rows += mono_array_length (tb->generic_params);
3253 alloc_table (table, table->rows);
3254 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3255 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3257 mono_image_get_generic_param_info (
3258 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3262 mono_image_add_decl_security (assembly,
3263 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3265 if (tb->subtypes) {
3266 MonoDynamicTable *ntable;
3268 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3269 ntable->rows += mono_array_length (tb->subtypes);
3270 alloc_table (ntable, ntable->rows);
3271 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3273 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3274 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3276 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3277 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3278 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3279 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3280 mono_string_to_utf8 (tb->name), tb->table_idx,
3281 ntable->next_idx, ntable->rows);*/
3282 values += MONO_NESTED_CLASS_SIZE;
3283 ntable->next_idx++;
3288 static void
3289 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
3291 int i;
3293 g_ptr_array_add (types, type); /* FIXME: GC object added to unmanaged memory */
3295 if (!type->subtypes)
3296 return;
3298 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3299 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3300 collect_types (types, subtype);
3304 static gint
3305 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3307 if ((*type1)->table_idx < (*type2)->table_idx)
3308 return -1;
3309 else
3310 if ((*type1)->table_idx > (*type2)->table_idx)
3311 return 1;
3312 else
3313 return 0;
3316 static void
3317 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3318 int i;
3320 if (!pinfo)
3321 return;
3322 for (i = 0; i < mono_array_length (pinfo); ++i) {
3323 MonoReflectionParamBuilder *pb;
3324 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3325 if (!pb)
3326 continue;
3327 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3331 static void
3332 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3333 int i;
3335 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3336 if (tb->fields) {
3337 for (i = 0; i < tb->num_fields; ++i) {
3338 MonoReflectionFieldBuilder* fb;
3339 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3340 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3343 if (tb->events) {
3344 for (i = 0; i < mono_array_length (tb->events); ++i) {
3345 MonoReflectionEventBuilder* eb;
3346 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3347 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3350 if (tb->properties) {
3351 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3352 MonoReflectionPropertyBuilder* pb;
3353 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3354 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3357 if (tb->ctors) {
3358 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3359 MonoReflectionCtorBuilder* cb;
3360 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3361 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3362 params_add_cattrs (assembly, cb->pinfo);
3366 if (tb->methods) {
3367 for (i = 0; i < tb->num_methods; ++i) {
3368 MonoReflectionMethodBuilder* mb;
3369 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3370 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3371 params_add_cattrs (assembly, mb->pinfo);
3375 if (tb->subtypes) {
3376 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3377 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3381 static void
3382 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3384 int i;
3386 mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3388 if (moduleb->global_methods) {
3389 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3390 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3391 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3392 params_add_cattrs (assembly, mb->pinfo);
3396 if (moduleb->global_fields) {
3397 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3398 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3399 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3403 if (moduleb->types) {
3404 for (i = 0; i < moduleb->num_types; ++i)
3405 type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3409 static void
3410 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3412 MonoDynamicTable *table;
3413 guint32 *values;
3414 char blob_size [6];
3415 guchar hash [20];
3416 char *b = blob_size;
3417 char *dir, *path;
3419 table = &assembly->tables [MONO_TABLE_FILE];
3420 table->rows++;
3421 alloc_table (table, table->rows);
3422 values = table->values + table->next_idx * MONO_FILE_SIZE;
3423 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3424 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3425 if (module->image->dynamic) {
3426 /* This depends on the fact that the main module is emitted last */
3427 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3428 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3429 } else {
3430 dir = NULL;
3431 path = g_strdup (module->image->name);
3433 mono_sha1_get_digest_from_file (path, hash);
3434 g_free (dir);
3435 g_free (path);
3436 mono_metadata_encode_value (20, b, &b);
3437 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3438 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3439 table->next_idx ++;
3442 static void
3443 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3445 MonoDynamicTable *table;
3446 int i;
3448 table = &assembly->tables [MONO_TABLE_MODULE];
3449 mb->table_idx = table->next_idx ++;
3450 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3451 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3452 i /= 16;
3453 ++i;
3454 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3455 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3456 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3457 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3460 static guint32
3461 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3462 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3464 MonoDynamicTable *table;
3465 guint32 *values;
3466 guint32 visib, res;
3468 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3469 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3470 return 0;
3472 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3473 table->rows++;
3474 alloc_table (table, table->rows);
3475 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3477 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3478 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3479 if (klass->nested_in)
3480 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3481 else
3482 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3483 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3484 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3486 res = table->next_idx;
3488 table->next_idx ++;
3490 /* Emit nested types */
3491 if (klass->ext && klass->ext->nested_classes) {
3492 GList *tmp;
3494 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
3495 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3498 return res;
3501 static void
3502 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3503 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3505 MonoClass *klass;
3506 guint32 idx, i;
3508 klass = mono_class_from_mono_type (tb->type.type);
3510 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3512 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3513 parent_index, assembly);
3516 * Emit nested types
3517 * We need to do this ourselves since klass->nested_classes is not set up.
3519 if (tb->subtypes) {
3520 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3521 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3525 static void
3526 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3527 guint32 module_index, MonoDynamicImage *assembly)
3529 MonoImage *image = module->image;
3530 MonoTableInfo *t;
3531 guint32 i;
3533 t = &image->tables [MONO_TABLE_TYPEDEF];
3535 for (i = 0; i < t->rows; ++i) {
3536 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3538 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3539 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3543 static void
3544 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3546 MonoDynamicTable *table;
3547 MonoClass *klass;
3548 guint32 *values;
3549 guint32 scope, idx;
3550 int i;
3552 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3554 if (assemblyb->type_forwarders) {
3555 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3556 MonoReflectionType *t = mono_type_array_get (assemblyb->type_forwarders, i);
3557 if (!t)
3558 continue;
3560 g_assert (t->type);
3562 klass = mono_class_from_mono_type (t->type);
3564 scope = resolution_scope_from_image (assembly, klass->image);
3565 g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3566 idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3568 table->rows++;
3569 alloc_table (table, table->rows);
3570 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3572 values [MONO_EXP_TYPE_FLAGS] = TYPE_ATTRIBUTE_FORWARDER;
3573 values [MONO_EXP_TYPE_TYPEDEF] = 0;
3574 values [MONO_EXP_TYPE_IMPLEMENTATION] = (idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3575 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3576 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3578 table->next_idx++;
3583 #define align_pointer(base,p)\
3584 do {\
3585 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3586 if (__diff & 3)\
3587 (p) += 4 - (__diff & 3);\
3588 } while (0)
3590 static int
3591 compare_constants (const void *a, const void *b)
3593 const guint32 *a_values = a;
3594 const guint32 *b_values = b;
3595 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3598 static int
3599 compare_semantics (const void *a, const void *b)
3601 const guint32 *a_values = a;
3602 const guint32 *b_values = b;
3603 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3604 if (assoc)
3605 return assoc;
3606 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3609 static int
3610 compare_custom_attrs (const void *a, const void *b)
3612 const guint32 *a_values = a;
3613 const guint32 *b_values = b;
3615 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3618 static int
3619 compare_field_marshal (const void *a, const void *b)
3621 const guint32 *a_values = a;
3622 const guint32 *b_values = b;
3624 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3627 static int
3628 compare_nested (const void *a, const void *b)
3630 const guint32 *a_values = a;
3631 const guint32 *b_values = b;
3633 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3636 static int
3637 compare_genericparam (const void *a, const void *b)
3639 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3640 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3642 if ((*b_entry)->owner == (*a_entry)->owner)
3643 return
3644 (*a_entry)->gparam->type.type->data.generic_param->num -
3645 (*b_entry)->gparam->type.type->data.generic_param->num;
3646 else
3647 return (*a_entry)->owner - (*b_entry)->owner;
3650 static int
3651 compare_declsecurity_attrs (const void *a, const void *b)
3653 const guint32 *a_values = a;
3654 const guint32 *b_values = b;
3656 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3659 static int
3660 compare_interface_impl (const void *a, const void *b)
3662 const guint32 *a_values = a;
3663 const guint32 *b_values = b;
3665 int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
3666 if (klass)
3667 return klass;
3669 return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
3672 static void
3673 pad_heap (MonoDynamicStream *sh)
3675 if (sh->index & 3) {
3676 int sz = 4 - (sh->index & 3);
3677 memset (sh->data + sh->index, 0, sz);
3678 sh->index += sz;
3682 struct StreamDesc {
3683 const char *name;
3684 MonoDynamicStream *stream;
3688 * build_compressed_metadata() fills in the blob of data that represents the
3689 * raw metadata as it will be saved in the PE file. The five streams are output
3690 * and the metadata tables are comnpressed from the guint32 array representation,
3691 * to the compressed on-disk format.
3693 static void
3694 build_compressed_metadata (MonoDynamicImage *assembly)
3696 MonoDynamicTable *table;
3697 int i;
3698 guint64 valid_mask = 0;
3699 guint64 sorted_mask;
3700 guint32 heapt_size = 0;
3701 guint32 meta_size = 256; /* allow for header and other stuff */
3702 guint32 table_offset;
3703 guint32 ntables = 0;
3704 guint64 *int64val;
3705 guint32 *int32val;
3706 guint16 *int16val;
3707 MonoImage *meta;
3708 unsigned char *p;
3709 struct StreamDesc stream_desc [5];
3711 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3712 for (i = 0; i < assembly->gen_params->len; i++){
3713 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3714 write_generic_param_entry (assembly, entry);
3717 stream_desc [0].name = "#~";
3718 stream_desc [0].stream = &assembly->tstream;
3719 stream_desc [1].name = "#Strings";
3720 stream_desc [1].stream = &assembly->sheap;
3721 stream_desc [2].name = "#US";
3722 stream_desc [2].stream = &assembly->us;
3723 stream_desc [3].name = "#Blob";
3724 stream_desc [3].stream = &assembly->blob;
3725 stream_desc [4].name = "#GUID";
3726 stream_desc [4].stream = &assembly->guid;
3728 /* tables that are sorted */
3729 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3730 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3731 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3732 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3733 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3734 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
3735 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
3737 /* Compute table sizes */
3738 /* the MonoImage has already been created in mono_image_basic_init() */
3739 meta = &assembly->image;
3741 /* sizes should be multiple of 4 */
3742 pad_heap (&assembly->blob);
3743 pad_heap (&assembly->guid);
3744 pad_heap (&assembly->sheap);
3745 pad_heap (&assembly->us);
3747 /* Setup the info used by compute_sizes () */
3748 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3749 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3750 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3752 meta_size += assembly->blob.index;
3753 meta_size += assembly->guid.index;
3754 meta_size += assembly->sheap.index;
3755 meta_size += assembly->us.index;
3757 for (i=0; i < MONO_TABLE_NUM; ++i)
3758 meta->tables [i].rows = assembly->tables [i].rows;
3760 for (i = 0; i < MONO_TABLE_NUM; i++){
3761 if (meta->tables [i].rows == 0)
3762 continue;
3763 valid_mask |= (guint64)1 << i;
3764 ntables ++;
3765 meta->tables [i].row_size = mono_metadata_compute_size (
3766 meta, i, &meta->tables [i].size_bitfield);
3767 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3769 heapt_size += 24; /* #~ header size */
3770 heapt_size += ntables * 4;
3771 /* make multiple of 4 */
3772 heapt_size += 3;
3773 heapt_size &= ~3;
3774 meta_size += heapt_size;
3775 meta->raw_metadata = g_malloc0 (meta_size);
3776 p = (unsigned char*)meta->raw_metadata;
3777 /* the metadata signature */
3778 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3779 /* version numbers and 4 bytes reserved */
3780 int16val = (guint16*)p;
3781 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
3782 *int16val = GUINT16_TO_LE (meta->md_version_minor);
3783 p += 8;
3784 /* version string */
3785 int32val = (guint32*)p;
3786 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3787 p += 4;
3788 memcpy (p, meta->version, strlen (meta->version));
3789 p += GUINT32_FROM_LE (*int32val);
3790 align_pointer (meta->raw_metadata, p);
3791 int16val = (guint16*)p;
3792 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3793 *int16val = GUINT16_TO_LE (5); /* number of streams */
3794 p += 4;
3797 * write the stream info.
3799 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3800 table_offset += 3; table_offset &= ~3;
3802 assembly->tstream.index = heapt_size;
3803 for (i = 0; i < 5; ++i) {
3804 int32val = (guint32*)p;
3805 stream_desc [i].stream->offset = table_offset;
3806 *int32val++ = GUINT32_TO_LE (table_offset);
3807 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3808 table_offset += GUINT32_FROM_LE (*int32val);
3809 table_offset += 3; table_offset &= ~3;
3810 p += 8;
3811 strcpy ((char*)p, stream_desc [i].name);
3812 p += strlen (stream_desc [i].name) + 1;
3813 align_pointer (meta->raw_metadata, p);
3816 * now copy the data, the table stream header and contents goes first.
3818 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3819 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
3820 int32val = (guint32*)p;
3821 *int32val = GUINT32_TO_LE (0); /* reserved */
3822 p += 4;
3824 if (mono_framework_version () > 1) {
3825 *p++ = 2; /* version */
3826 *p++ = 0;
3827 } else {
3828 *p++ = 1; /* version */
3829 *p++ = 0;
3832 if (meta->idx_string_wide)
3833 *p |= 0x01;
3834 if (meta->idx_guid_wide)
3835 *p |= 0x02;
3836 if (meta->idx_blob_wide)
3837 *p |= 0x04;
3838 ++p;
3839 *p++ = 1; /* reserved */
3840 int64val = (guint64*)p;
3841 *int64val++ = GUINT64_TO_LE (valid_mask);
3842 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3843 p += 16;
3844 int32val = (guint32*)p;
3845 for (i = 0; i < MONO_TABLE_NUM; i++){
3846 if (meta->tables [i].rows == 0)
3847 continue;
3848 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3850 p = (unsigned char*)int32val;
3852 /* sort the tables that still need sorting */
3853 table = &assembly->tables [MONO_TABLE_CONSTANT];
3854 if (table->rows)
3855 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
3856 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3857 if (table->rows)
3858 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3859 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3860 if (table->rows)
3861 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3862 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3863 if (table->rows)
3864 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3865 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3866 if (table->rows)
3867 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3868 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3869 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
3870 if (table->rows)
3871 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
3872 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3873 if (table->rows)
3874 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
3876 /* compress the tables */
3877 for (i = 0; i < MONO_TABLE_NUM; i++){
3878 int row, col;
3879 guint32 *values;
3880 guint32 bitfield = meta->tables [i].size_bitfield;
3881 if (!meta->tables [i].rows)
3882 continue;
3883 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3884 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3885 meta->tables [i].base = (char*)p;
3886 for (row = 1; row <= meta->tables [i].rows; ++row) {
3887 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3888 for (col = 0; col < assembly->tables [i].columns; ++col) {
3889 switch (mono_metadata_table_size (bitfield, col)) {
3890 case 1:
3891 *p++ = values [col];
3892 break;
3893 case 2:
3894 *p++ = values [col] & 0xff;
3895 *p++ = (values [col] >> 8) & 0xff;
3896 break;
3897 case 4:
3898 *p++ = values [col] & 0xff;
3899 *p++ = (values [col] >> 8) & 0xff;
3900 *p++ = (values [col] >> 16) & 0xff;
3901 *p++ = (values [col] >> 24) & 0xff;
3902 break;
3903 default:
3904 g_assert_not_reached ();
3908 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3911 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3912 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3913 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3914 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3915 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3917 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3921 * Some tables in metadata need to be sorted according to some criteria, but
3922 * when methods and fields are first created with reflection, they may be assigned a token
3923 * that doesn't correspond to the final token they will get assigned after the sorting.
3924 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3925 * with the reflection objects that represent them. Once all the tables are set up, the
3926 * reflection objects will contains the correct table index. fixup_method() will fixup the
3927 * tokens for the method with ILGenerator @ilgen.
3929 static void
3930 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
3932 guint32 code_idx = GPOINTER_TO_UINT (value);
3933 MonoReflectionILTokenInfo *iltoken;
3934 MonoReflectionFieldBuilder *field;
3935 MonoReflectionCtorBuilder *ctor;
3936 MonoReflectionMethodBuilder *method;
3937 MonoReflectionTypeBuilder *tb;
3938 MonoReflectionArrayMethod *am;
3939 guint32 i, idx = 0;
3940 unsigned char *target;
3942 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3943 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3944 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
3945 switch (target [3]) {
3946 case MONO_TABLE_FIELD:
3947 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3948 field = (MonoReflectionFieldBuilder *)iltoken->member;
3949 idx = field->table_idx;
3950 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3951 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3952 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
3953 } else {
3954 g_assert_not_reached ();
3956 break;
3957 case MONO_TABLE_METHOD:
3958 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3959 method = (MonoReflectionMethodBuilder *)iltoken->member;
3960 idx = method->table_idx;
3961 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3962 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3963 idx = ctor->table_idx;
3964 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3965 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3966 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3967 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3968 } else {
3969 g_assert_not_reached ();
3971 break;
3972 case MONO_TABLE_TYPEDEF:
3973 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3974 g_assert_not_reached ();
3975 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3976 idx = tb->table_idx;
3977 break;
3978 case MONO_TABLE_MEMBERREF:
3979 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3980 am = (MonoReflectionArrayMethod*)iltoken->member;
3981 idx = am->table_idx;
3982 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3983 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
3984 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
3985 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
3986 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3987 g_assert (m->klass->generic_class || m->klass->generic_container);
3988 continue;
3989 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3990 continue;
3991 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3992 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3993 g_assert (is_field_on_inst (f));
3994 continue;
3995 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
3996 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3997 continue;
3998 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
3999 continue;
4000 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4001 continue;
4002 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4003 continue;
4004 } else {
4005 g_assert_not_reached ();
4007 break;
4008 case MONO_TABLE_METHODSPEC:
4009 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4010 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4011 g_assert (mono_method_signature (m)->generic_param_count);
4012 continue;
4013 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4014 continue;
4015 } else {
4016 g_assert_not_reached ();
4018 break;
4019 default:
4020 g_error ("got unexpected table 0x%02x in fixup", target [3]);
4022 target [0] = idx & 0xff;
4023 target [1] = (idx >> 8) & 0xff;
4024 target [2] = (idx >> 16) & 0xff;
4029 * fixup_cattrs:
4031 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4032 * value is not known when the table is emitted.
4034 static void
4035 fixup_cattrs (MonoDynamicImage *assembly)
4037 MonoDynamicTable *table;
4038 guint32 *values;
4039 guint32 type, i, idx, token;
4040 MonoObject *ctor;
4042 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4044 for (i = 0; i < table->rows; ++i) {
4045 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4047 type = values [MONO_CUSTOM_ATTR_TYPE];
4048 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4049 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4050 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4051 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4052 g_assert (ctor);
4054 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4055 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4056 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4057 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4063 static void
4064 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4066 MonoDynamicTable *table;
4067 guint32 *values;
4069 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4070 table->rows++;
4071 alloc_table (table, table->rows);
4072 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4073 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4074 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4075 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4076 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4077 table->next_idx++;
4080 static void
4081 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4083 MonoDynamicTable *table;
4084 guint32 *values;
4085 char blob_size [6];
4086 guchar hash [20];
4087 char *b = blob_size;
4088 char *name, *sname;
4089 guint32 idx, offset;
4091 if (rsrc->filename) {
4092 name = mono_string_to_utf8 (rsrc->filename);
4093 sname = g_path_get_basename (name);
4095 table = &assembly->tables [MONO_TABLE_FILE];
4096 table->rows++;
4097 alloc_table (table, table->rows);
4098 values = table->values + table->next_idx * MONO_FILE_SIZE;
4099 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4100 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4101 g_free (sname);
4103 mono_sha1_get_digest_from_file (name, hash);
4104 mono_metadata_encode_value (20, b, &b);
4105 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4106 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4107 g_free (name);
4108 idx = table->next_idx++;
4109 rsrc->offset = 0;
4110 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4111 } else {
4112 char sizebuf [4];
4113 char *data;
4114 guint len;
4115 if (rsrc->data) {
4116 data = mono_array_addr (rsrc->data, char, 0);
4117 len = mono_array_length (rsrc->data);
4118 } else {
4119 data = NULL;
4120 len = 0;
4122 offset = len;
4123 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4124 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4125 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4126 mono_image_add_stream_data (&assembly->resources, data, len);
4128 if (!mb->is_main)
4130 * The entry should be emitted into the MANIFESTRESOURCE table of
4131 * the main module, but that needs to reference the FILE table
4132 * which isn't emitted yet.
4134 return;
4135 else
4136 idx = 0;
4139 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4142 static void
4143 set_version_from_string (MonoString *version, guint32 *values)
4145 gchar *ver, *p, *str;
4146 guint32 i;
4148 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4149 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4150 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4151 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4152 if (!version)
4153 return;
4154 ver = str = mono_string_to_utf8 (version);
4155 for (i = 0; i < 4; ++i) {
4156 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4157 switch (*p) {
4158 case '.':
4159 p++;
4160 break;
4161 case '*':
4162 /* handle Revision and Build */
4163 p++;
4164 break;
4166 ver = p;
4168 g_free (str);
4171 static guint32
4172 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4173 gsize len;
4174 guint32 token = 0;
4175 char blob_size [6];
4176 char *b = blob_size;
4178 if (!pkey)
4179 return token;
4181 len = mono_array_length (pkey);
4182 mono_metadata_encode_value (len, b, &b);
4183 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4184 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4186 assembly->public_key = g_malloc (len);
4187 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4188 assembly->public_key_len = len;
4190 /* Special case: check for ECMA key (16 bytes) */
4191 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4192 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4193 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4194 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4195 /* minimum key size (in 2.0) is 384 bits */
4196 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4197 } else {
4198 /* FIXME - verifier */
4199 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4200 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4202 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
4204 return token;
4207 static void
4208 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4210 MonoDynamicTable *table;
4211 MonoDynamicImage *assembly;
4212 MonoReflectionAssemblyBuilder *assemblyb;
4213 MonoDomain *domain;
4214 guint32 *values;
4215 int i;
4216 guint32 module_index;
4218 assemblyb = moduleb->assemblyb;
4219 assembly = moduleb->dynamic_image;
4220 domain = mono_object_domain (assemblyb);
4222 /* Emit ASSEMBLY table */
4223 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4224 alloc_table (table, 1);
4225 values = table->values + MONO_ASSEMBLY_SIZE;
4226 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4227 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4228 if (assemblyb->culture) {
4229 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4230 } else {
4231 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4233 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4234 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4235 set_version_from_string (assemblyb->version, values);
4237 /* Emit FILE + EXPORTED_TYPE table */
4238 module_index = 0;
4239 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4240 int j;
4241 MonoReflectionModuleBuilder *file_module =
4242 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4243 if (file_module != moduleb) {
4244 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4245 module_index ++;
4246 if (file_module->types) {
4247 for (j = 0; j < file_module->num_types; ++j) {
4248 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4249 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4254 if (assemblyb->loaded_modules) {
4255 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4256 MonoReflectionModule *file_module =
4257 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4258 mono_image_fill_file_table (domain, file_module, assembly);
4259 module_index ++;
4260 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4263 if (assemblyb->type_forwarders)
4264 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4266 /* Emit MANIFESTRESOURCE table */
4267 module_index = 0;
4268 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4269 int j;
4270 MonoReflectionModuleBuilder *file_module =
4271 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4272 /* The table for the main module is emitted later */
4273 if (file_module != moduleb) {
4274 module_index ++;
4275 if (file_module->resources) {
4276 int len = mono_array_length (file_module->resources);
4277 for (j = 0; j < len; ++j) {
4278 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4279 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4286 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4289 * mono_image_build_metadata() will fill the info in all the needed metadata tables
4290 * for the modulebuilder @moduleb.
4291 * At the end of the process, method and field tokens are fixed up and the
4292 * on-disk compressed metadata representation is created.
4294 void
4295 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4297 MonoDynamicTable *table;
4298 MonoDynamicImage *assembly;
4299 MonoReflectionAssemblyBuilder *assemblyb;
4300 MonoDomain *domain;
4301 GPtrArray *types;
4302 guint32 *values;
4303 int i, j;
4305 assemblyb = moduleb->assemblyb;
4306 assembly = moduleb->dynamic_image;
4307 domain = mono_object_domain (assemblyb);
4309 if (assembly->text_rva)
4310 return;
4312 assembly->text_rva = START_TEXT_RVA;
4314 if (moduleb->is_main) {
4315 mono_image_emit_manifest (moduleb);
4318 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4319 table->rows = 1; /* .<Module> */
4320 table->next_idx++;
4321 alloc_table (table, table->rows);
4323 * Set the first entry.
4325 values = table->values + table->columns;
4326 values [MONO_TYPEDEF_FLAGS] = 0;
4327 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4328 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4329 values [MONO_TYPEDEF_EXTENDS] = 0;
4330 values [MONO_TYPEDEF_FIELD_LIST] = 1;
4331 values [MONO_TYPEDEF_METHOD_LIST] = 1;
4334 * handle global methods
4335 * FIXME: test what to do when global methods are defined in multiple modules.
4337 if (moduleb->global_methods) {
4338 table = &assembly->tables [MONO_TABLE_METHOD];
4339 table->rows += mono_array_length (moduleb->global_methods);
4340 alloc_table (table, table->rows);
4341 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4342 mono_image_get_method_info (
4343 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4345 if (moduleb->global_fields) {
4346 table = &assembly->tables [MONO_TABLE_FIELD];
4347 table->rows += mono_array_length (moduleb->global_fields);
4348 alloc_table (table, table->rows);
4349 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4350 mono_image_get_field_info (
4351 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4354 table = &assembly->tables [MONO_TABLE_MODULE];
4355 alloc_table (table, 1);
4356 mono_image_fill_module_table (domain, moduleb, assembly);
4358 /* Collect all types into a list sorted by their table_idx */
4359 types = g_ptr_array_new ();
4361 if (moduleb->types)
4362 for (i = 0; i < moduleb->num_types; ++i) {
4363 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4364 collect_types (types, type);
4367 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
4368 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4369 table->rows += types->len;
4370 alloc_table (table, table->rows);
4373 * Emit type names + namespaces at one place inside the string heap,
4374 * so load_class_names () needs to touch fewer pages.
4376 for (i = 0; i < types->len; ++i) {
4377 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4378 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4380 for (i = 0; i < types->len; ++i) {
4381 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4382 string_heap_insert_mstring (&assembly->sheap, tb->name);
4385 for (i = 0; i < types->len; ++i) {
4386 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4387 mono_image_get_type_info (domain, type, assembly);
4391 * table->rows is already set above and in mono_image_fill_module_table.
4393 /* add all the custom attributes at the end, once all the indexes are stable */
4394 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4396 /* CAS assembly permissions */
4397 if (assemblyb->permissions_minimum)
4398 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4399 if (assemblyb->permissions_optional)
4400 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4401 if (assemblyb->permissions_refused)
4402 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4404 module_add_cattrs (assembly, moduleb);
4406 /* fixup tokens */
4407 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4409 /* Create the MethodImpl table. We do this after emitting all methods so we already know
4410 * the final tokens and don't need another fixup pass. */
4412 if (moduleb->global_methods) {
4413 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4414 MonoReflectionMethodBuilder *mb = mono_array_get (
4415 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4416 mono_image_add_methodimpl (assembly, mb);
4420 for (i = 0; i < types->len; ++i) {
4421 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4422 if (type->methods) {
4423 for (j = 0; j < type->num_methods; ++j) {
4424 MonoReflectionMethodBuilder *mb = mono_array_get (
4425 type->methods, MonoReflectionMethodBuilder*, j);
4427 mono_image_add_methodimpl (assembly, mb);
4432 g_ptr_array_free (types, TRUE);
4434 fixup_cattrs (assembly);
4437 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4439 void
4440 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4442 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4445 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4447 #ifndef DISABLE_REFLECTION_EMIT
4450 * mono_image_insert_string:
4451 * @module: module builder object
4452 * @str: a string
4454 * Insert @str into the user string stream of @module.
4456 guint32
4457 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4459 MonoDynamicImage *assembly;
4460 guint32 idx;
4461 char buf [16];
4462 char *b = buf;
4464 MONO_ARCH_SAVE_REGS;
4466 if (!module->dynamic_image)
4467 mono_image_module_basic_init (module);
4469 assembly = module->dynamic_image;
4471 if (assembly->save) {
4472 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4473 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4474 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4476 char *swapped = g_malloc (2 * mono_string_length (str));
4477 const char *p = (const char*)mono_string_chars (str);
4479 swap_with_size (swapped, p, 2, mono_string_length (str));
4480 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4481 g_free (swapped);
4483 #else
4484 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4485 #endif
4486 mono_image_add_stream_data (&assembly->us, "", 1);
4487 } else {
4488 idx = assembly->us.index ++;
4491 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4493 return MONO_TOKEN_STRING | idx;
4496 guint32
4497 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4499 MonoClass *klass;
4500 guint32 token = 0;
4502 klass = obj->vtable->klass;
4503 if (strcmp (klass->name, "MonoMethod") == 0) {
4504 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4505 MonoMethodSignature *sig, *old;
4506 guint32 sig_token, parent;
4507 int nargs, i;
4509 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4511 nargs = mono_array_length (opt_param_types);
4512 old = mono_method_signature (method);
4513 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4515 sig->hasthis = old->hasthis;
4516 sig->explicit_this = old->explicit_this;
4517 sig->call_convention = old->call_convention;
4518 sig->generic_param_count = old->generic_param_count;
4519 sig->param_count = old->param_count + nargs;
4520 sig->sentinelpos = old->param_count;
4521 sig->ret = old->ret;
4523 for (i = 0; i < old->param_count; i++)
4524 sig->params [i] = old->params [i];
4526 for (i = 0; i < nargs; i++) {
4527 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4528 sig->params [old->param_count + i] = rt->type;
4531 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4532 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4533 parent >>= MONO_TYPEDEFORREF_BITS;
4535 parent <<= MONO_MEMBERREF_PARENT_BITS;
4536 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4538 sig_token = method_encode_signature (assembly, sig);
4539 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4540 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4541 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4542 ReflectionMethodBuilder rmb;
4543 guint32 parent, sig;
4544 char *name;
4546 reflection_methodbuilder_from_method_builder (&rmb, mb);
4547 rmb.opt_types = opt_param_types;
4549 sig = method_builder_encode_signature (assembly, &rmb);
4551 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
4552 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4554 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4555 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4557 name = mono_string_to_utf8 (rmb.name);
4558 token = mono_image_get_varargs_method_token (
4559 assembly, parent, name, sig);
4560 g_free (name);
4561 } else {
4562 g_error ("requested method token for %s\n", klass->name);
4565 return token;
4569 * mono_image_create_token:
4570 * @assembly: a dynamic assembly
4571 * @obj:
4572 * @register_token: Whenever to register the token in the assembly->tokens hash.
4574 * Get a token to insert in the IL code stream for the given MemberInfo.
4575 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
4576 * the table_idx-es were recomputed, so registering the token would overwrite an existing
4577 * entry.
4579 guint32
4580 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
4581 gboolean create_methodspec, gboolean register_token)
4583 MonoClass *klass;
4584 guint32 token = 0;
4586 klass = obj->vtable->klass;
4588 /* Check for user defined reflection objects */
4589 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
4590 if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0))
4591 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported")); \
4593 if (strcmp (klass->name, "MethodBuilder") == 0) {
4594 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4595 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4597 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
4598 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4599 else
4600 token = mono_image_get_methodbuilder_token (assembly, mb, create_methodspec);
4601 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4602 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4603 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4604 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4606 if (tb->module->dynamic_image == assembly && !tb->generic_params)
4607 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4608 else
4609 token = mono_image_get_ctorbuilder_token (assembly, mb);
4610 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4611 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4612 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4613 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4614 if (tb->generic_params) {
4615 token = mono_image_get_generic_field_token (assembly, fb);
4616 } else {
4617 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4619 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4620 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4621 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4622 } else if (strcmp (klass->name, "MonoType") == 0) {
4623 MonoReflectionType *tb = (MonoReflectionType *)obj;
4624 MonoClass *mc = mono_class_from_mono_type (tb->type);
4625 token = mono_metadata_token_from_dor (
4626 mono_image_typedef_or_ref_full (assembly, tb->type, mc->generic_container == NULL));
4627 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 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, "MonoGenericClass") == 0) {
4632 MonoReflectionType *tb = (MonoReflectionType *)obj;
4633 token = mono_metadata_token_from_dor (
4634 mono_image_typedef_or_ref (assembly, tb->type));
4635 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4636 strcmp (klass->name, "MonoMethod") == 0 ||
4637 strcmp (klass->name, "MonoGenericMethod") == 0 ||
4638 strcmp (klass->name, "MonoGenericCMethod") == 0) {
4639 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4640 if (m->method->is_inflated) {
4641 if (create_methodspec)
4642 token = mono_image_get_methodspec_token (assembly, m->method);
4643 else
4644 token = mono_image_get_inflated_method_token (assembly, m->method);
4645 } else if ((m->method->klass->image == &assembly->image) &&
4646 !m->method->klass->generic_class) {
4647 static guint32 method_table_idx = 0xffffff;
4648 if (m->method->klass->wastypebuilder) {
4649 /* we use the same token as the one that was assigned
4650 * to the Methodbuilder.
4651 * FIXME: do the equivalent for Fields.
4653 token = m->method->token;
4654 } else {
4656 * Each token should have a unique index, but the indexes are
4657 * assigned by managed code, so we don't know about them. An
4658 * easy solution is to count backwards...
4660 method_table_idx --;
4661 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4663 } else {
4664 token = mono_image_get_methodref_token (assembly, m->method, create_methodspec);
4666 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4667 } else if (strcmp (klass->name, "MonoField") == 0) {
4668 MonoReflectionField *f = (MonoReflectionField *)obj;
4669 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
4670 static guint32 field_table_idx = 0xffffff;
4671 field_table_idx --;
4672 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4673 } else {
4674 token = mono_image_get_fieldref_token (assembly, f);
4676 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4677 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4678 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4679 token = mono_image_get_array_token (assembly, m);
4680 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4681 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4682 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4683 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
4684 MonoReflectionType *tb = (MonoReflectionType *)obj;
4685 token = mono_metadata_token_from_dor (
4686 mono_image_typedef_or_ref (assembly, tb->type));
4687 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
4688 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
4689 token = mono_image_get_field_on_inst_token (assembly, f);
4690 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
4691 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
4692 token = mono_image_get_ctor_on_inst_token (assembly, c, create_methodspec);
4693 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
4694 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
4695 token = mono_image_get_method_on_inst_token (assembly, m, create_methodspec);
4696 } else {
4697 g_error ("requested token for %s\n", klass->name);
4700 if (register_token)
4701 mono_image_register_token (assembly, token, obj);
4703 return token;
4707 * mono_image_register_token:
4709 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
4710 * the Module.ResolveXXXToken () methods to work.
4712 void
4713 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
4715 MonoObject *prev = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4716 if (prev) {
4717 /* There could be multiple MethodInfo objects with the same token */
4718 //g_assert (prev == obj);
4719 } else {
4720 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4724 #endif /* DISABLE_REFLECTION_EMIT */
4726 typedef struct {
4727 guint32 import_lookup_table;
4728 guint32 timestamp;
4729 guint32 forwarder;
4730 guint32 name_rva;
4731 guint32 import_address_table_rva;
4732 } MonoIDT;
4734 typedef struct {
4735 guint32 name_rva;
4736 guint32 flags;
4737 } MonoILT;
4739 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4741 static MonoDynamicImage*
4742 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4744 static const guchar entrycode [16] = {0xff, 0x25, 0};
4745 MonoDynamicImage *image;
4746 int i;
4748 const char *version;
4750 if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
4751 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
4752 else
4753 version = mono_get_runtime_info ()->runtime_version;
4755 #if HAVE_BOEHM_GC
4756 image = GC_MALLOC (sizeof (MonoDynamicImage));
4757 #else
4758 image = g_new0 (MonoDynamicImage, 1);
4759 #endif
4761 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
4763 /*g_print ("created image %p\n", image);*/
4764 /* keep in sync with image.c */
4765 image->image.name = assembly_name;
4766 image->image.assembly_name = image->image.name; /* they may be different */
4767 image->image.module_name = module_name;
4768 image->image.version = g_strdup (version);
4769 image->image.md_version_major = 1;
4770 image->image.md_version_minor = 1;
4771 image->image.dynamic = TRUE;
4773 image->image.references = g_new0 (MonoAssembly*, 1);
4774 image->image.references [0] = NULL;
4776 mono_image_init (&image->image);
4778 image->token_fixups = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_KEY_GC);
4779 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
4780 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
4781 image->method_aux_hash = g_hash_table_new (NULL, NULL);
4782 image->handleref = g_hash_table_new (NULL, NULL);
4783 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4784 image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4785 image->methodspec = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_KEY_GC);
4786 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4787 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4788 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4789 image->gen_params = g_ptr_array_new ();
4791 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
4792 string_heap_init (&image->sheap);
4793 mono_image_add_stream_data (&image->us, "", 1);
4794 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4795 /* import tables... */
4796 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
4797 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4798 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4799 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4800 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4801 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4802 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4803 stream_data_align (&image->code);
4805 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4807 for (i=0; i < MONO_TABLE_NUM; ++i) {
4808 image->tables [i].next_idx = 1;
4809 image->tables [i].columns = table_sizes [i];
4812 image->image.assembly = (MonoAssembly*)assembly;
4813 image->run = assembly->run;
4814 image->save = assembly->save;
4815 image->pe_kind = 0x1; /* ILOnly */
4816 image->machine = 0x14c; /* I386 */
4818 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
4820 return image;
4823 static void
4824 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
4826 g_free (key);
4829 void
4830 mono_dynamic_image_free (MonoDynamicImage *image)
4832 MonoDynamicImage *di = image;
4833 GList *list;
4834 int i;
4836 if (di->methodspec)
4837 mono_g_hash_table_destroy (di->methodspec);
4838 if (di->typespec)
4839 g_hash_table_destroy (di->typespec);
4840 if (di->typeref)
4841 g_hash_table_destroy (di->typeref);
4842 if (di->handleref)
4843 g_hash_table_destroy (di->handleref);
4844 if (di->tokens)
4845 mono_g_hash_table_destroy (di->tokens);
4846 if (di->generic_def_objects)
4847 mono_g_hash_table_destroy (di->generic_def_objects);
4848 if (di->blob_cache) {
4849 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
4850 g_hash_table_destroy (di->blob_cache);
4852 if (di->standalonesig_cache)
4853 g_hash_table_destroy (di->standalonesig_cache);
4854 for (list = di->array_methods; list; list = list->next) {
4855 ArrayMethod *am = (ArrayMethod *)list->data;
4856 g_free (am->sig);
4857 g_free (am->name);
4858 g_free (am);
4860 g_list_free (di->array_methods);
4861 if (di->gen_params) {
4862 for (i = 0; i < di->gen_params->len; i++) {
4863 GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
4864 if (entry->gparam->type.type) {
4865 MonoGenericParam *param = entry->gparam->type.type->data.generic_param;
4866 g_free ((char*)param->name);
4867 g_free (param);
4869 g_free (entry);
4871 g_ptr_array_free (di->gen_params, TRUE);
4873 if (di->token_fixups)
4874 mono_g_hash_table_destroy (di->token_fixups);
4875 if (di->method_to_table_idx)
4876 g_hash_table_destroy (di->method_to_table_idx);
4877 if (di->field_to_table_idx)
4878 g_hash_table_destroy (di->field_to_table_idx);
4879 if (di->method_aux_hash)
4880 g_hash_table_destroy (di->method_aux_hash);
4881 g_free (di->strong_name);
4882 g_free (di->win32_res);
4883 if (di->public_key)
4884 g_free (di->public_key);
4886 /*g_print ("string heap destroy for image %p\n", di);*/
4887 mono_dynamic_stream_reset (&di->sheap);
4888 mono_dynamic_stream_reset (&di->code);
4889 mono_dynamic_stream_reset (&di->resources);
4890 mono_dynamic_stream_reset (&di->us);
4891 mono_dynamic_stream_reset (&di->blob);
4892 mono_dynamic_stream_reset (&di->tstream);
4893 mono_dynamic_stream_reset (&di->guid);
4894 for (i = 0; i < MONO_TABLE_NUM; ++i) {
4895 g_free (di->tables [i].values);
4899 #ifndef DISABLE_REFLECTION_EMIT
4902 * mono_image_basic_init:
4903 * @assembly: an assembly builder object
4905 * Create the MonoImage that represents the assembly builder and setup some
4906 * of the helper hash table and the basic metadata streams.
4908 void
4909 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4911 MonoDynamicAssembly *assembly;
4912 MonoDynamicImage *image;
4913 MonoDomain *domain = mono_object_domain (assemblyb);
4915 MONO_ARCH_SAVE_REGS;
4917 if (assemblyb->dynamic_assembly)
4918 return;
4920 #if HAVE_BOEHM_GC
4921 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4922 #else
4923 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
4924 #endif
4926 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
4928 assembly->assembly.ref_count = 1;
4929 assembly->assembly.dynamic = TRUE;
4930 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
4931 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4932 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4933 if (assemblyb->culture)
4934 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4935 else
4936 assembly->assembly.aname.culture = g_strdup ("");
4938 if (assemblyb->version) {
4939 char *vstr = mono_string_to_utf8 (assemblyb->version);
4940 char **version = g_strsplit (vstr, ".", 4);
4941 char **parts = version;
4942 assembly->assembly.aname.major = atoi (*parts++);
4943 assembly->assembly.aname.minor = atoi (*parts++);
4944 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
4945 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
4947 g_strfreev (version);
4948 g_free (vstr);
4949 } else {
4950 assembly->assembly.aname.major = 0;
4951 assembly->assembly.aname.minor = 0;
4952 assembly->assembly.aname.build = 0;
4953 assembly->assembly.aname.revision = 0;
4956 assembly->run = assemblyb->access != 2;
4957 assembly->save = assemblyb->access != 1;
4959 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4960 image->initial_image = TRUE;
4961 assembly->assembly.aname.name = image->image.name;
4962 assembly->assembly.image = &image->image;
4964 mono_domain_assemblies_lock (domain);
4965 domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
4966 mono_domain_assemblies_unlock (domain);
4968 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4970 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
4972 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4975 #endif /* DISABLE_REFLECTION_EMIT */
4977 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4979 static int
4980 calc_section_size (MonoDynamicImage *assembly)
4982 int nsections = 0;
4984 /* alignment constraints */
4985 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
4986 g_assert ((assembly->code.index % 4) == 0);
4987 assembly->meta_size += 3;
4988 assembly->meta_size &= ~3;
4989 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
4990 g_assert ((assembly->resources.index % 4) == 0);
4992 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4993 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4994 nsections++;
4996 if (assembly->win32_res) {
4997 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4999 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5000 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5001 nsections++;
5004 assembly->sections [MONO_SECTION_RELOC].size = 12;
5005 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5006 nsections++;
5008 return nsections;
5011 typedef struct {
5012 guint32 id;
5013 guint32 offset;
5014 GSList *children;
5015 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5016 } ResTreeNode;
5018 static int
5019 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5021 ResTreeNode *t1 = (ResTreeNode*)a;
5022 ResTreeNode *t2 = (ResTreeNode*)b;
5024 return t1->id - t2->id;
5028 * resource_tree_create:
5030 * Organize the resources into a resource tree.
5032 static ResTreeNode *
5033 resource_tree_create (MonoArray *win32_resources)
5035 ResTreeNode *tree, *res_node, *type_node, *lang_node;
5036 GSList *l;
5037 int i;
5039 tree = g_new0 (ResTreeNode, 1);
5041 for (i = 0; i < mono_array_length (win32_resources); ++i) {
5042 MonoReflectionWin32Resource *win32_res =
5043 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5045 /* Create node */
5047 /* FIXME: BUG: this stores managed references in unmanaged memory */
5048 lang_node = g_new0 (ResTreeNode, 1);
5049 lang_node->id = win32_res->lang_id;
5050 lang_node->win32_res = win32_res;
5052 /* Create type node if neccesary */
5053 type_node = NULL;
5054 for (l = tree->children; l; l = l->next)
5055 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5056 type_node = (ResTreeNode*)l->data;
5057 break;
5060 if (!type_node) {
5061 type_node = g_new0 (ResTreeNode, 1);
5062 type_node->id = win32_res->res_type;
5065 * The resource types have to be sorted otherwise
5066 * Windows Explorer can't display the version information.
5068 tree->children = g_slist_insert_sorted (tree->children,
5069 type_node, resource_tree_compare_by_id);
5072 /* Create res node if neccesary */
5073 res_node = NULL;
5074 for (l = type_node->children; l; l = l->next)
5075 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5076 res_node = (ResTreeNode*)l->data;
5077 break;
5080 if (!res_node) {
5081 res_node = g_new0 (ResTreeNode, 1);
5082 res_node->id = win32_res->res_id;
5083 type_node->children = g_slist_append (type_node->children, res_node);
5086 res_node->children = g_slist_append (res_node->children, lang_node);
5089 return tree;
5093 * resource_tree_encode:
5095 * Encode the resource tree into the format used in the PE file.
5097 static void
5098 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5100 char *entries;
5101 MonoPEResourceDir dir;
5102 MonoPEResourceDirEntry dir_entry;
5103 MonoPEResourceDataEntry data_entry;
5104 GSList *l;
5105 guint32 res_id_entries;
5108 * For the format of the resource directory, see the article
5109 * "An In-Depth Look into the Win32 Portable Executable File Format" by
5110 * Matt Pietrek
5113 memset (&dir, 0, sizeof (dir));
5114 memset (&dir_entry, 0, sizeof (dir_entry));
5115 memset (&data_entry, 0, sizeof (data_entry));
5117 g_assert (sizeof (dir) == 16);
5118 g_assert (sizeof (dir_entry) == 8);
5119 g_assert (sizeof (data_entry) == 16);
5121 node->offset = p - begin;
5123 /* IMAGE_RESOURCE_DIRECTORY */
5124 res_id_entries = g_slist_length (node->children);
5125 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5127 memcpy (p, &dir, sizeof (dir));
5128 p += sizeof (dir);
5130 /* Reserve space for entries */
5131 entries = p;
5132 p += sizeof (dir_entry) * res_id_entries;
5134 /* Write children */
5135 for (l = node->children; l; l = l->next) {
5136 ResTreeNode *child = (ResTreeNode*)l->data;
5138 if (child->win32_res) {
5139 guint32 size;
5141 child->offset = p - begin;
5143 /* IMAGE_RESOURCE_DATA_ENTRY */
5144 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5145 size = mono_array_length (child->win32_res->res_data);
5146 data_entry.rde_size = GUINT32_TO_LE (size);
5148 memcpy (p, &data_entry, sizeof (data_entry));
5149 p += sizeof (data_entry);
5151 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5152 p += size;
5153 } else {
5154 resource_tree_encode (child, begin, p, &p);
5158 /* IMAGE_RESOURCE_ENTRY */
5159 for (l = node->children; l; l = l->next) {
5160 ResTreeNode *child = (ResTreeNode*)l->data;
5162 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5163 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5165 memcpy (entries, &dir_entry, sizeof (dir_entry));
5166 entries += sizeof (dir_entry);
5169 *endbuf = p;
5172 static void
5173 resource_tree_free (ResTreeNode * node)
5175 GSList * list;
5176 for (list = node->children; list; list = list->next)
5177 resource_tree_free ((ResTreeNode*)list->data);
5178 g_slist_free(node->children);
5179 g_free (node);
5182 static void
5183 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5185 char *buf;
5186 char *p;
5187 guint32 size, i;
5188 MonoReflectionWin32Resource *win32_res;
5189 ResTreeNode *tree;
5191 if (!assemblyb->win32_resources)
5192 return;
5195 * Resources are stored in a three level tree inside the PE file.
5196 * - level one contains a node for each type of resource
5197 * - level two contains a node for each resource
5198 * - level three contains a node for each instance of a resource for a
5199 * specific language.
5202 tree = resource_tree_create (assemblyb->win32_resources);
5204 /* Estimate the size of the encoded tree */
5205 size = 0;
5206 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5207 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5208 size += mono_array_length (win32_res->res_data);
5210 /* Directory structure */
5211 size += mono_array_length (assemblyb->win32_resources) * 256;
5212 p = buf = g_malloc (size);
5214 resource_tree_encode (tree, p, p, &p);
5216 g_assert (p - buf <= size);
5218 assembly->win32_res = g_malloc (p - buf);
5219 assembly->win32_res_size = p - buf;
5220 memcpy (assembly->win32_res, buf, p - buf);
5222 g_free (buf);
5223 resource_tree_free (tree);
5226 static void
5227 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5229 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5230 int i;
5232 p += sizeof (MonoPEResourceDir);
5233 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5234 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5235 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5236 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5237 fixup_resource_directory (res_section, child, rva);
5238 } else {
5239 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5240 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5243 p += sizeof (MonoPEResourceDirEntry);
5247 static void
5248 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5250 guint32 dummy;
5251 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5252 g_error ("WriteFile returned %d\n", GetLastError ());
5256 * mono_image_create_pefile:
5257 * @mb: a module builder object
5259 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
5260 * assembly->pefile where it can be easily retrieved later in chunks.
5262 void
5263 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5265 MonoMSDOSHeader *msdos;
5266 MonoDotNetHeader *header;
5267 MonoSectionTable *section;
5268 MonoCLIHeader *cli_header;
5269 guint32 size, image_size, virtual_base, text_offset;
5270 guint32 header_start, section_start, file_offset, virtual_offset;
5271 MonoDynamicImage *assembly;
5272 MonoReflectionAssemblyBuilder *assemblyb;
5273 MonoDynamicStream pefile_stream = {0};
5274 MonoDynamicStream *pefile = &pefile_stream;
5275 int i, nsections;
5276 guint32 *rva, value;
5277 guchar *p;
5278 static const unsigned char msheader[] = {
5279 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5280 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5281 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5282 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5283 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5284 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5285 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5286 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5289 assemblyb = mb->assemblyb;
5291 mono_image_basic_init (assemblyb);
5292 assembly = mb->dynamic_image;
5294 assembly->pe_kind = assemblyb->pe_kind;
5295 assembly->machine = assemblyb->machine;
5296 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5297 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5299 mono_image_build_metadata (mb);
5301 if (mb->is_main && assemblyb->resources) {
5302 int len = mono_array_length (assemblyb->resources);
5303 for (i = 0; i < len; ++i)
5304 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5307 if (mb->resources) {
5308 int len = mono_array_length (mb->resources);
5309 for (i = 0; i < len; ++i)
5310 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5313 build_compressed_metadata (assembly);
5315 if (mb->is_main)
5316 assembly_add_win32_resources (assembly, assemblyb);
5318 nsections = calc_section_size (assembly);
5320 /* The DOS header and stub */
5321 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5322 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5324 /* the dotnet header */
5325 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5327 /* the section tables */
5328 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5330 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5331 virtual_offset = VIRT_ALIGN;
5332 image_size = 0;
5334 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5335 if (!assembly->sections [i].size)
5336 continue;
5337 /* align offsets */
5338 file_offset += FILE_ALIGN - 1;
5339 file_offset &= ~(FILE_ALIGN - 1);
5340 virtual_offset += VIRT_ALIGN - 1;
5341 virtual_offset &= ~(VIRT_ALIGN - 1);
5343 assembly->sections [i].offset = file_offset;
5344 assembly->sections [i].rva = virtual_offset;
5346 file_offset += assembly->sections [i].size;
5347 virtual_offset += assembly->sections [i].size;
5348 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5351 file_offset += FILE_ALIGN - 1;
5352 file_offset &= ~(FILE_ALIGN - 1);
5354 image_size += section_start + sizeof (MonoSectionTable) * nsections;
5356 /* back-patch info */
5357 msdos = (MonoMSDOSHeader*)pefile->data;
5358 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5360 header = (MonoDotNetHeader*)(pefile->data + header_start);
5361 header->pesig [0] = 'P';
5362 header->pesig [1] = 'E';
5364 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5365 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5366 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5367 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5368 if (assemblyb->pekind == 1) {
5369 /* it's a dll */
5370 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5371 } else {
5372 /* it's an exe */
5373 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5376 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5378 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5379 header->pe.pe_major = 6;
5380 header->pe.pe_minor = 0;
5381 size = assembly->sections [MONO_SECTION_TEXT].size;
5382 size += FILE_ALIGN - 1;
5383 size &= ~(FILE_ALIGN - 1);
5384 header->pe.pe_code_size = GUINT32_FROM_LE(size);
5385 size = assembly->sections [MONO_SECTION_RSRC].size;
5386 size += FILE_ALIGN - 1;
5387 size &= ~(FILE_ALIGN - 1);
5388 header->pe.pe_data_size = GUINT32_FROM_LE(size);
5389 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5390 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5391 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5392 /* pe_rva_entry_point always at the beginning of the text section */
5393 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5395 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5396 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5397 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5398 header->nt.pe_os_major = GUINT16_FROM_LE (4);
5399 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5400 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5401 size = section_start;
5402 size += FILE_ALIGN - 1;
5403 size &= ~(FILE_ALIGN - 1);
5404 header->nt.pe_header_size = GUINT32_FROM_LE (size);
5405 size = image_size;
5406 size += VIRT_ALIGN - 1;
5407 size &= ~(VIRT_ALIGN - 1);
5408 header->nt.pe_image_size = GUINT32_FROM_LE (size);
5411 // Translate the PEFileKind value to the value expected by the Windows loader
5414 short kind;
5417 // PEFileKinds.Dll == 1
5418 // PEFileKinds.ConsoleApplication == 2
5419 // PEFileKinds.WindowApplication == 3
5421 // need to get:
5422 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5423 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5425 if (assemblyb->pekind == 3)
5426 kind = 2;
5427 else
5428 kind = 3;
5430 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5432 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5433 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5434 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5435 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5436 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5437 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
5439 /* fill data directory entries */
5441 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
5442 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5444 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
5445 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
5447 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
5448 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
5449 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
5450 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5451 /* patch entrypoint name */
5452 if (assemblyb->pekind == 1)
5453 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
5454 else
5455 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
5456 /* patch imported function RVA name */
5457 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
5458 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
5460 /* the import table */
5461 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
5462 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
5463 /* patch imported dll RVA name and other entries in the dir */
5464 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
5465 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
5466 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
5467 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5468 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
5469 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
5471 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
5472 value = (assembly->text_rva + assembly->imp_names_offset);
5473 *p++ = (value) & 0xff;
5474 *p++ = (value >> 8) & (0xff);
5475 *p++ = (value >> 16) & (0xff);
5476 *p++ = (value >> 24) & (0xff);
5478 /* the CLI header info */
5479 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
5480 cli_header->ch_size = GUINT32_FROM_LE (72);
5481 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
5482 if (mono_framework_version () > 1)
5483 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
5484 else
5485 cli_header->ch_runtime_minor = GUINT16_FROM_LE (0);
5486 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
5487 if (assemblyb->entry_point) {
5488 guint32 table_idx = 0;
5489 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
5490 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
5491 table_idx = methodb->table_idx;
5492 } else {
5493 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
5495 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
5496 } else {
5497 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
5499 /* The embedded managed resources */
5500 text_offset = assembly->text_rva + assembly->code.index;
5501 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
5502 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
5503 text_offset += assembly->resources.index;
5504 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
5505 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
5506 text_offset += assembly->meta_size;
5507 if (assembly->strong_name_size) {
5508 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
5509 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
5510 text_offset += assembly->strong_name_size;
5513 /* write the section tables and section content */
5514 section = (MonoSectionTable*)(pefile->data + section_start);
5515 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5516 static const char section_names [][7] = {
5517 ".text", ".rsrc", ".reloc"
5519 if (!assembly->sections [i].size)
5520 continue;
5521 strcpy (section->st_name, section_names [i]);
5522 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5523 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5524 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5525 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5526 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5527 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5528 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5529 section ++;
5532 checked_write_file (file, pefile->data, pefile->index);
5534 mono_dynamic_stream_reset (pefile);
5536 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5537 if (!assembly->sections [i].size)
5538 continue;
5540 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5541 g_error ("SetFilePointer returned %d\n", GetLastError ());
5543 switch (i) {
5544 case MONO_SECTION_TEXT:
5545 /* patch entry point */
5546 p = (guchar*)(assembly->code.data + 2);
5547 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5548 *p++ = (value) & 0xff;
5549 *p++ = (value >> 8) & 0xff;
5550 *p++ = (value >> 16) & 0xff;
5551 *p++ = (value >> 24) & 0xff;
5553 checked_write_file (file, assembly->code.data, assembly->code.index);
5554 checked_write_file (file, assembly->resources.data, assembly->resources.index);
5555 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5556 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5559 g_free (assembly->image.raw_metadata);
5560 break;
5561 case MONO_SECTION_RELOC: {
5562 struct {
5563 guint32 page_rva;
5564 guint32 block_size;
5565 guint16 type_and_offset;
5566 guint16 term;
5567 } reloc;
5569 g_assert (sizeof (reloc) == 12);
5571 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5572 reloc.block_size = GUINT32_FROM_LE (12);
5575 * the entrypoint is always at the start of the text section
5576 * 3 is IMAGE_REL_BASED_HIGHLOW
5577 * 2 is patch_size_rva - text_rva
5579 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5580 reloc.term = 0;
5582 checked_write_file (file, &reloc, sizeof (reloc));
5584 break;
5586 case MONO_SECTION_RSRC:
5587 if (assembly->win32_res) {
5589 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5590 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5591 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5593 break;
5594 default:
5595 g_assert_not_reached ();
5599 /* check that the file is properly padded */
5600 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5601 g_error ("SetFilePointer returned %d\n", GetLastError ());
5602 if (! SetEndOfFile (file))
5603 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5605 mono_dynamic_stream_reset (&assembly->code);
5606 mono_dynamic_stream_reset (&assembly->us);
5607 mono_dynamic_stream_reset (&assembly->blob);
5608 mono_dynamic_stream_reset (&assembly->guid);
5609 mono_dynamic_stream_reset (&assembly->sheap);
5611 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5612 g_hash_table_destroy (assembly->blob_cache);
5613 assembly->blob_cache = NULL;
5616 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5618 void
5619 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5621 g_assert_not_reached ();
5624 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5626 #ifndef DISABLE_REFLECTION_EMIT
5628 MonoReflectionModule *
5629 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5631 char *name;
5632 MonoImage *image;
5633 MonoImageOpenStatus status;
5634 MonoDynamicAssembly *assembly;
5635 guint32 module_count;
5636 MonoImage **new_modules;
5637 gboolean *new_modules_loaded;
5639 name = mono_string_to_utf8 (fileName);
5641 image = mono_image_open (name, &status);
5642 if (!image) {
5643 MonoException *exc;
5644 if (status == MONO_IMAGE_ERROR_ERRNO)
5645 exc = mono_get_exception_file_not_found (fileName);
5646 else
5647 exc = mono_get_exception_bad_image_format (name);
5648 g_free (name);
5649 mono_raise_exception (exc);
5652 g_free (name);
5654 assembly = ab->dynamic_assembly;
5655 image->assembly = (MonoAssembly*)assembly;
5657 module_count = image->assembly->image->module_count;
5658 new_modules = g_new0 (MonoImage *, module_count + 1);
5659 new_modules_loaded = g_new0 (gboolean, module_count + 1);
5661 if (image->assembly->image->modules)
5662 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5663 if (image->assembly->image->modules_loaded)
5664 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
5665 new_modules [module_count] = image;
5666 new_modules_loaded [module_count] = TRUE;
5667 mono_image_addref (image);
5669 g_free (image->assembly->image->modules);
5670 image->assembly->image->modules = new_modules;
5671 image->assembly->image->modules_loaded = new_modules_loaded;
5672 image->assembly->image->module_count ++;
5674 mono_assembly_load_references (image, &status);
5675 if (status) {
5676 mono_image_close (image);
5677 mono_raise_exception (mono_get_exception_file_not_found (fileName));
5680 return mono_module_get_object (mono_domain_get (), image);
5683 #endif /* DISABLE_REFLECTION_EMIT */
5686 * We need to return always the same object for MethodInfo, FieldInfo etc..
5687 * but we need to consider the reflected type.
5688 * type uses a different hash, since it uses custom hash/equal functions.
5691 typedef struct {
5692 gpointer item;
5693 MonoClass *refclass;
5694 } ReflectedEntry;
5696 static gboolean
5697 reflected_equal (gconstpointer a, gconstpointer b) {
5698 const ReflectedEntry *ea = a;
5699 const ReflectedEntry *eb = b;
5701 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
5704 static guint
5705 reflected_hash (gconstpointer a) {
5706 const ReflectedEntry *ea = a;
5707 return mono_aligned_addr_hash (ea->item);
5710 #define CHECK_OBJECT(t,p,k) \
5711 do { \
5712 t _obj; \
5713 ReflectedEntry e; \
5714 e.item = (p); \
5715 e.refclass = (k); \
5716 mono_domain_lock (domain); \
5717 if (!domain->refobject_hash) \
5718 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5719 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
5720 mono_domain_unlock (domain); \
5721 return _obj; \
5723 mono_domain_unlock (domain); \
5724 } while (0)
5726 #ifdef HAVE_BOEHM_GC
5727 /* ReflectedEntry doesn't need to be GC tracked */
5728 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
5729 #define FREE_REFENTRY(entry) g_free ((entry))
5730 #else
5731 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5732 /* FIXME: */
5733 #define FREE_REFENTRY(entry)
5734 #endif
5736 #define CACHE_OBJECT(t,p,o,k) \
5737 do { \
5738 t _obj; \
5739 ReflectedEntry pe; \
5740 pe.item = (p); \
5741 pe.refclass = (k); \
5742 mono_domain_lock (domain); \
5743 if (!domain->refobject_hash) \
5744 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5745 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
5746 if (!_obj) { \
5747 ReflectedEntry *e = ALLOC_REFENTRY; \
5748 e->item = (p); \
5749 e->refclass = (k); \
5750 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
5751 _obj = o; \
5753 mono_domain_unlock (domain); \
5754 return _obj; \
5755 } while (0)
5757 static void
5758 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
5760 mono_domain_lock (domain);
5761 if (domain->refobject_hash) {
5762 ReflectedEntry pe;
5763 gpointer orig_pe, orig_value;
5765 pe.item = o;
5766 pe.refclass = klass;
5767 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
5768 mono_g_hash_table_remove (domain->refobject_hash, &pe);
5769 FREE_REFENTRY (orig_pe);
5772 mono_domain_unlock (domain);
5775 static gpointer
5776 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
5778 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5781 static gpointer
5782 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5784 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
5787 #ifndef DISABLE_REFLECTION_EMIT
5789 void
5790 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5792 MonoDynamicImage *image = moduleb->dynamic_image;
5793 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5794 if (!image) {
5795 int module_count;
5796 MonoImage **new_modules;
5797 MonoImage *ass;
5799 * FIXME: we already created an image in mono_image_basic_init (), but
5800 * we don't know which module it belongs to, since that is only
5801 * determined at assembly save time.
5803 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5804 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5806 moduleb->module.image = &image->image;
5807 moduleb->dynamic_image = image;
5808 register_module (mono_object_domain (moduleb), moduleb, image);
5810 /* register the module with the assembly */
5811 ass = ab->dynamic_assembly->assembly.image;
5812 module_count = ass->module_count;
5813 new_modules = g_new0 (MonoImage *, module_count + 1);
5815 if (ass->modules)
5816 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
5817 new_modules [module_count] = &image->image;
5818 mono_image_addref (&image->image);
5820 g_free (ass->modules);
5821 ass->modules = new_modules;
5822 ass->module_count ++;
5826 #endif
5829 * mono_assembly_get_object:
5830 * @domain: an app domain
5831 * @assembly: an assembly
5833 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5835 MonoReflectionAssembly*
5836 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5838 static MonoClass *System_Reflection_Assembly;
5839 MonoReflectionAssembly *res;
5841 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5842 if (!System_Reflection_Assembly)
5843 System_Reflection_Assembly = mono_class_from_name (
5844 mono_defaults.corlib, "System.Reflection", "Assembly");
5845 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5846 res->assembly = assembly;
5848 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5853 MonoReflectionModule*
5854 mono_module_get_object (MonoDomain *domain, MonoImage *image)
5856 static MonoClass *System_Reflection_Module;
5857 MonoReflectionModule *res;
5858 char* basename;
5860 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5861 if (!System_Reflection_Module)
5862 System_Reflection_Module = mono_class_from_name (
5863 mono_defaults.corlib, "System.Reflection", "Module");
5864 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5866 res->image = image;
5867 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5869 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
5870 basename = g_path_get_basename (image->name);
5871 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
5872 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
5874 g_free (basename);
5876 if (image->assembly->image == image) {
5877 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5878 } else {
5879 int i;
5880 res->token = 0;
5881 if (image->assembly->image->modules) {
5882 for (i = 0; i < image->assembly->image->module_count; i++) {
5883 if (image->assembly->image->modules [i] == image)
5884 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5886 g_assert (res->token);
5890 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
5893 MonoReflectionModule*
5894 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5896 static MonoClass *System_Reflection_Module;
5897 MonoReflectionModule *res;
5898 MonoTableInfo *table;
5899 guint32 cols [MONO_FILE_SIZE];
5900 const char *name;
5901 guint32 i, name_idx;
5902 const char *val;
5904 if (!System_Reflection_Module)
5905 System_Reflection_Module = mono_class_from_name (
5906 mono_defaults.corlib, "System.Reflection", "Module");
5907 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5909 table = &image->tables [MONO_TABLE_FILE];
5910 g_assert (table_index < table->rows);
5911 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5913 res->image = NULL;
5914 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5915 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5917 /* Check whenever the row has a corresponding row in the moduleref table */
5918 table = &image->tables [MONO_TABLE_MODULEREF];
5919 for (i = 0; i < table->rows; ++i) {
5920 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5921 val = mono_metadata_string_heap (image, name_idx);
5922 if (strcmp (val, name) == 0)
5923 res->image = image->modules [i];
5926 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
5927 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
5928 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
5929 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5930 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5932 return res;
5935 static gboolean
5936 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5938 if ((t1->type != t2->type) ||
5939 (t1->byref != t2->byref))
5940 return FALSE;
5942 switch (t1->type) {
5943 case MONO_TYPE_VOID:
5944 case MONO_TYPE_BOOLEAN:
5945 case MONO_TYPE_CHAR:
5946 case MONO_TYPE_I1:
5947 case MONO_TYPE_U1:
5948 case MONO_TYPE_I2:
5949 case MONO_TYPE_U2:
5950 case MONO_TYPE_I4:
5951 case MONO_TYPE_U4:
5952 case MONO_TYPE_I8:
5953 case MONO_TYPE_U8:
5954 case MONO_TYPE_R4:
5955 case MONO_TYPE_R8:
5956 case MONO_TYPE_STRING:
5957 case MONO_TYPE_I:
5958 case MONO_TYPE_U:
5959 case MONO_TYPE_OBJECT:
5960 case MONO_TYPE_TYPEDBYREF:
5961 return TRUE;
5962 case MONO_TYPE_VALUETYPE:
5963 case MONO_TYPE_CLASS:
5964 case MONO_TYPE_SZARRAY:
5965 return t1->data.klass == t2->data.klass;
5966 case MONO_TYPE_PTR:
5967 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5968 case MONO_TYPE_ARRAY:
5969 if (t1->data.array->rank != t2->data.array->rank)
5970 return FALSE;
5971 return t1->data.array->eklass == t2->data.array->eklass;
5972 case MONO_TYPE_GENERICINST: {
5973 int i;
5974 MonoGenericInst *i1 = t1->data.generic_class->context.class_inst;
5975 MonoGenericInst *i2 = t2->data.generic_class->context.class_inst;
5976 if (i1->type_argc != i2->type_argc)
5977 return FALSE;
5978 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
5979 &t2->data.generic_class->container_class->byval_arg))
5980 return FALSE;
5981 /* FIXME: we should probably just compare the instance pointers directly. */
5982 for (i = 0; i < i1->type_argc; ++i) {
5983 if (!mono_metadata_type_equal (i1->type_argv [i], i2->type_argv [i]))
5984 return FALSE;
5986 return TRUE;
5988 case MONO_TYPE_VAR:
5989 case MONO_TYPE_MVAR:
5990 return t1->data.generic_param == t2->data.generic_param;
5991 default:
5992 g_error ("implement type compare for %0x!", t1->type);
5993 return FALSE;
5996 return FALSE;
5999 static guint
6000 mymono_metadata_type_hash (MonoType *t1)
6002 guint hash;
6004 hash = t1->type;
6006 hash |= t1->byref << 6; /* do not collide with t1->type values */
6007 switch (t1->type) {
6008 case MONO_TYPE_VALUETYPE:
6009 case MONO_TYPE_CLASS:
6010 case MONO_TYPE_SZARRAY:
6011 /* check if the distribution is good enough */
6012 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
6013 case MONO_TYPE_PTR:
6014 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
6015 case MONO_TYPE_GENERICINST: {
6016 int i;
6017 MonoGenericInst *inst = t1->data.generic_class->context.class_inst;
6018 hash += g_str_hash (t1->data.generic_class->container_class->name);
6019 hash *= 13;
6020 for (i = 0; i < inst->type_argc; ++i) {
6021 hash += mymono_metadata_type_hash (inst->type_argv [i]);
6022 hash *= 13;
6024 return hash;
6027 return hash;
6030 static MonoReflectionGenericClass*
6031 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
6033 static MonoClass *System_Reflection_MonoGenericClass;
6034 MonoReflectionGenericClass *res;
6035 MonoClass *klass, *gklass;
6037 if (!System_Reflection_MonoGenericClass) {
6038 System_Reflection_MonoGenericClass = mono_class_from_name (
6039 mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
6040 g_assert (System_Reflection_MonoGenericClass);
6043 klass = mono_class_from_mono_type (geninst);
6044 gklass = klass->generic_class->container_class;
6046 mono_class_init (klass);
6048 #ifdef HAVE_SGEN_GC
6049 res = (MonoReflectionGenericClass *) mono_gc_alloc_pinned_obj (mono_class_vtable (domain, System_Reflection_MonoGenericClass), mono_class_instance_size (System_Reflection_MonoGenericClass));
6050 #else
6051 res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
6052 #endif
6054 res->type.type = geninst;
6055 g_assert (gklass->reflection_info);
6056 g_assert (!strcmp (((MonoObject*)gklass->reflection_info)->vtable->klass->name, "TypeBuilder"));
6057 MONO_OBJECT_SETREF (res, generic_type, gklass->reflection_info);
6059 return res;
6062 static gboolean
6063 verify_safe_for_managed_space (MonoType *type)
6065 switch (type->type) {
6066 #ifdef DEBUG_HARDER
6067 case MONO_TYPE_ARRAY:
6068 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6069 case MONO_TYPE_PTR:
6070 return verify_safe_for_managed_space (type->data.type);
6071 case MONO_TYPE_SZARRAY:
6072 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6073 case MONO_TYPE_GENERICINST: {
6074 MonoGenericInst *inst = type->data.generic_class->inst;
6075 int i;
6076 if (!inst->is_open)
6077 break;
6078 for (i = 0; i < inst->type_argc; ++i)
6079 if (!verify_safe_for_managed_space (inst->type_argv [i]))
6080 return FALSE;
6081 break;
6083 #endif
6084 case MONO_TYPE_VAR:
6085 case MONO_TYPE_MVAR:
6086 return TRUE;
6088 return TRUE;
6092 * mono_type_get_object:
6093 * @domain: an app domain
6094 * @type: a type
6096 * Return an System.MonoType object representing the type @type.
6098 MonoReflectionType*
6099 mono_type_get_object (MonoDomain *domain, MonoType *type)
6101 MonoReflectionType *res;
6102 MonoClass *klass = mono_class_from_mono_type (type);
6104 /*we must avoid using @type as it might have come
6105 * from a mono_metadata_type_dup and the caller
6106 * expects that is can be freed.
6107 * Using the right type from
6109 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6111 /* void is very common */
6112 if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6113 return (MonoReflectionType*)domain->typeof_void;
6116 * If the vtable of the given class was already created, we can use
6117 * the MonoType from there and avoid all locking and hash table lookups.
6119 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6120 * that the resulting object is diferent.
6122 if (type == &klass->byval_arg && !klass->image->dynamic) {
6123 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6124 if (vtable && vtable->type)
6125 return vtable->type;
6128 mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6129 mono_domain_lock (domain);
6130 if (!domain->type_hash)
6131 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash,
6132 (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
6133 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
6134 mono_domain_unlock (domain);
6135 mono_loader_unlock ();
6136 return res;
6138 /* Create a MonoGenericClass object for instantiations of not finished TypeBuilders */
6139 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder) {
6140 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
6141 mono_g_hash_table_insert (domain->type_hash, type, res);
6142 mono_domain_unlock (domain);
6143 mono_loader_unlock ();
6144 return res;
6147 if (!verify_safe_for_managed_space (type)) {
6148 mono_domain_unlock (domain);
6149 mono_loader_unlock ();
6150 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6153 if (klass->reflection_info && !klass->wastypebuilder) {
6154 /* g_assert_not_reached (); */
6155 /* should this be considered an error condition? */
6156 if (!type->byref) {
6157 mono_domain_unlock (domain);
6158 mono_loader_unlock ();
6159 return klass->reflection_info;
6162 // FIXME: Get rid of this, do it in the icalls for Type
6163 mono_class_init (klass);
6164 #ifdef HAVE_SGEN_GC
6165 res = (MonoReflectionType *)mono_gc_alloc_pinned_obj (mono_class_vtable (domain, mono_defaults.monotype_class), mono_class_instance_size (mono_defaults.monotype_class));
6166 #else
6167 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
6168 #endif
6169 res->type = type;
6170 mono_g_hash_table_insert (domain->type_hash, type, res);
6172 if (type->type == MONO_TYPE_VOID)
6173 MONO_OBJECT_SETREF (domain, typeof_void, res);
6175 mono_domain_unlock (domain);
6176 mono_loader_unlock ();
6177 return res;
6181 * mono_method_get_object:
6182 * @domain: an app domain
6183 * @method: a method
6184 * @refclass: the reflected type (can be NULL)
6186 * Return an System.Reflection.MonoMethod object representing the method @method.
6188 MonoReflectionMethod*
6189 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6192 * We use the same C representation for methods and constructors, but the type
6193 * name in C# is different.
6195 static MonoClass *System_Reflection_MonoMethod = NULL;
6196 static MonoClass *System_Reflection_MonoCMethod = NULL;
6197 static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6198 static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6199 MonoClass *klass;
6200 MonoReflectionMethod *ret;
6203 * Don't let static RGCTX invoke wrappers get into
6204 * MonoReflectionMethods.
6206 if (method->wrapper_type == MONO_WRAPPER_STATIC_RGCTX_INVOKE)
6207 method = mono_marshal_method_from_wrapper (method);
6209 if (method->is_inflated) {
6210 MonoReflectionGenericMethod *gret;
6212 refclass = method->klass;
6213 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6214 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6215 if (!System_Reflection_MonoGenericCMethod)
6216 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6217 klass = System_Reflection_MonoGenericCMethod;
6218 } else {
6219 if (!System_Reflection_MonoGenericMethod)
6220 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6221 klass = System_Reflection_MonoGenericMethod;
6223 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6224 gret->method.method = method;
6225 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6226 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6227 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6230 if (!refclass)
6231 refclass = method->klass;
6233 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6234 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6235 if (!System_Reflection_MonoCMethod)
6236 System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6237 klass = System_Reflection_MonoCMethod;
6239 else {
6240 if (!System_Reflection_MonoMethod)
6241 System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6242 klass = System_Reflection_MonoMethod;
6244 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6245 ret->method = method;
6246 MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6247 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6251 * mono_method_clear_object:
6253 * Clear the cached reflection objects for the dynamic method METHOD.
6255 void
6256 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
6258 g_assert (method->dynamic);
6260 clear_cached_object (domain, method, method->klass);
6261 /* Added by mono_param_get_objects () */
6262 clear_cached_object (domain, &(method->signature), NULL);
6266 * mono_field_get_object:
6267 * @domain: an app domain
6268 * @klass: a type
6269 * @field: a field
6271 * Return an System.Reflection.MonoField object representing the field @field
6272 * in class @klass.
6274 MonoReflectionField*
6275 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6277 MonoReflectionField *res;
6278 static MonoClass *monofield_klass;
6280 CHECK_OBJECT (MonoReflectionField *, field, klass);
6281 if (!monofield_klass)
6282 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6283 res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6284 res->klass = klass;
6285 res->field = field;
6286 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6287 if (is_field_on_inst (field))
6288 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6289 else
6290 res->attrs = field->type->attrs;
6291 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6292 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6296 * mono_property_get_object:
6297 * @domain: an app domain
6298 * @klass: a type
6299 * @property: a property
6301 * Return an System.Reflection.MonoProperty object representing the property @property
6302 * in class @klass.
6304 MonoReflectionProperty*
6305 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6307 MonoReflectionProperty *res;
6308 static MonoClass *monoproperty_klass;
6310 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6311 if (!monoproperty_klass)
6312 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6313 res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6314 res->klass = klass;
6315 res->property = property;
6316 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6320 * mono_event_get_object:
6321 * @domain: an app domain
6322 * @klass: a type
6323 * @event: a event
6325 * Return an System.Reflection.MonoEvent object representing the event @event
6326 * in class @klass.
6328 MonoReflectionEvent*
6329 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6331 MonoReflectionEvent *res;
6332 MonoReflectionMonoEvent *mono_event;
6333 static MonoClass *monoevent_klass;
6335 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6336 if (!monoevent_klass)
6337 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6338 mono_event = (MonoReflectionMonoEvent *)mono_object_new (domain, monoevent_klass);
6339 mono_event->klass = klass;
6340 mono_event->event = event;
6341 res = (MonoReflectionEvent*)mono_event;
6342 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6346 * mono_get_reflection_missing_object:
6347 * @domain: Domain where the object lives
6349 * Returns the System.Reflection.Missing.Value singleton object
6350 * (of type System.Reflection.Missing).
6352 * Used as the value for ParameterInfo.DefaultValue when Optional
6353 * is present
6355 static MonoObject *
6356 mono_get_reflection_missing_object (MonoDomain *domain)
6358 MonoObject *obj;
6359 static MonoClassField *missing_value_field = NULL;
6361 if (!missing_value_field) {
6362 MonoClass *missing_klass;
6363 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6364 mono_class_init (missing_klass);
6365 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6366 g_assert (missing_value_field);
6368 obj = mono_field_get_value_object (domain, missing_value_field, NULL);
6369 g_assert (obj);
6370 return obj;
6373 static MonoObject*
6374 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6376 if (!*dbnull)
6377 *dbnull = mono_get_dbnull_object (domain);
6378 return *dbnull;
6381 static MonoObject*
6382 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6384 if (!*reflection_missing)
6385 *reflection_missing = mono_get_reflection_missing_object (domain);
6386 return *reflection_missing;
6390 * mono_param_get_objects:
6391 * @domain: an app domain
6392 * @method: a method
6394 * Return an System.Reflection.ParameterInfo array object representing the parameters
6395 * in the method @method.
6397 MonoArray*
6398 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
6400 static MonoClass *System_Reflection_ParameterInfo;
6401 static MonoClass *System_Reflection_ParameterInfo_array;
6402 MonoArray *res = NULL;
6403 MonoReflectionMethod *member = NULL;
6404 MonoReflectionParameter *param = NULL;
6405 char **names, **blobs = NULL;
6406 guint32 *types = NULL;
6407 MonoType *type = NULL;
6408 MonoObject *dbnull = NULL;
6409 MonoObject *missing = NULL;
6410 MonoMarshalSpec **mspecs;
6411 MonoMethodSignature *sig;
6412 MonoVTable *pinfo_vtable;
6413 int i;
6415 if (!System_Reflection_ParameterInfo_array) {
6416 MonoClass *klass;
6418 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6419 mono_memory_barrier ();
6420 System_Reflection_ParameterInfo = klass;
6422 klass = mono_array_class_get (klass, 1);
6423 mono_memory_barrier ();
6424 System_Reflection_ParameterInfo_array = klass;
6427 if (!mono_method_signature (method)->param_count)
6428 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6430 /* Note: the cache is based on the address of the signature into the method
6431 * since we already cache MethodInfos with the method as keys.
6433 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
6435 sig = mono_method_signature (method);
6436 member = mono_method_get_object (domain, method, NULL);
6437 names = g_new (char *, sig->param_count);
6438 mono_method_get_param_names (method, (const char **) names);
6440 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
6441 mono_method_get_marshal_info (method, mspecs);
6443 res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
6444 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
6445 for (i = 0; i < sig->param_count; ++i) {
6446 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
6447 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
6448 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
6449 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
6450 param->PositionImpl = i;
6451 param->AttrsImpl = sig->params [i]->attrs;
6453 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
6454 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6455 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6456 else
6457 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6458 } else {
6460 if (!blobs) {
6461 blobs = g_new0 (char *, sig->param_count);
6462 types = g_new0 (guint32, sig->param_count);
6463 get_default_param_value_blobs (method, blobs, types);
6466 /* Build MonoType for the type from the Constant Table */
6467 if (!type)
6468 type = g_new0 (MonoType, 1);
6469 type->type = types [i];
6470 type->data.klass = NULL;
6471 if (types [i] == MONO_TYPE_CLASS)
6472 type->data.klass = mono_defaults.object_class;
6473 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
6474 /* For enums, types [i] contains the base type */
6476 type->type = MONO_TYPE_VALUETYPE;
6477 type->data.klass = mono_class_from_mono_type (sig->params [i]);
6478 } else
6479 type->data.klass = mono_class_from_mono_type (type);
6481 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
6483 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6484 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
6485 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6486 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6487 else
6488 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6493 if (mspecs [i + 1])
6494 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
6496 mono_array_setref (res, i, param);
6498 g_free (names);
6499 g_free (blobs);
6500 g_free (types);
6501 g_free (type);
6503 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
6504 if (mspecs [i])
6505 mono_metadata_free_marshal_spec (mspecs [i]);
6506 g_free (mspecs);
6508 CACHE_OBJECT (MonoArray *, &(method->signature), res, NULL);
6512 * mono_method_body_get_object:
6513 * @domain: an app domain
6514 * @method: a method
6516 * Return an System.Reflection.MethodBody object representing the method @method.
6518 MonoReflectionMethodBody*
6519 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
6521 static MonoClass *System_Reflection_MethodBody = NULL;
6522 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
6523 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
6524 MonoReflectionMethodBody *ret;
6525 MonoMethodNormal *mn;
6526 MonoMethodHeader *header;
6527 guint32 method_rva, local_var_sig_token;
6528 char *ptr;
6529 unsigned char format, flags;
6530 int i;
6532 if (!System_Reflection_MethodBody)
6533 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
6534 if (!System_Reflection_LocalVariableInfo)
6535 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
6536 if (!System_Reflection_ExceptionHandlingClause)
6537 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
6539 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
6541 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6542 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
6543 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
6544 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
6545 return NULL;
6546 mn = (MonoMethodNormal *)method;
6547 header = mono_method_get_header (method);
6549 /* Obtain local vars signature token */
6550 method_rva = mono_metadata_decode_row_col (&method->klass->image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
6551 ptr = mono_image_rva_map (method->klass->image, method_rva);
6552 flags = *(const unsigned char *) ptr;
6553 format = flags & METHOD_HEADER_FORMAT_MASK;
6554 switch (format){
6555 case METHOD_HEADER_TINY_FORMAT:
6556 case METHOD_HEADER_TINY_FORMAT1:
6557 local_var_sig_token = 0;
6558 break;
6559 case METHOD_HEADER_FAT_FORMAT:
6560 ptr += 2;
6561 ptr += 2;
6562 ptr += 4;
6563 local_var_sig_token = read32 (ptr);
6564 break;
6565 default:
6566 g_assert_not_reached ();
6569 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
6571 ret->init_locals = header->init_locals;
6572 ret->max_stack = header->max_stack;
6573 ret->local_var_sig_token = local_var_sig_token;
6574 MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
6575 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
6577 /* Locals */
6578 MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
6579 for (i = 0; i < header->num_locals; ++i) {
6580 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
6581 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
6582 info->is_pinned = header->locals [i]->pinned;
6583 info->local_index = i;
6584 mono_array_setref (ret->locals, i, info);
6587 /* Exceptions */
6588 MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
6589 for (i = 0; i < header->num_clauses; ++i) {
6590 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
6591 MonoExceptionClause *clause = &header->clauses [i];
6593 info->flags = clause->flags;
6594 info->try_offset = clause->try_offset;
6595 info->try_length = clause->try_len;
6596 info->handler_offset = clause->handler_offset;
6597 info->handler_length = clause->handler_len;
6598 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
6599 info->filter_offset = clause->data.filter_offset;
6600 else if (clause->data.catch_class)
6601 MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
6603 mono_array_setref (ret->clauses, i, info);
6606 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
6607 return ret;
6611 * mono_get_dbnull_object:
6612 * @domain: Domain where the object lives
6614 * Returns the System.DBNull.Value singleton object
6616 * Used as the value for ParameterInfo.DefaultValue
6618 MonoObject *
6619 mono_get_dbnull_object (MonoDomain *domain)
6621 MonoObject *obj;
6622 static MonoClassField *dbnull_value_field = NULL;
6624 if (!dbnull_value_field) {
6625 MonoClass *dbnull_klass;
6626 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
6627 mono_class_init (dbnull_klass);
6628 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
6629 g_assert (dbnull_value_field);
6631 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
6632 g_assert (obj);
6633 return obj;
6636 static void
6637 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
6639 guint32 param_index, i, lastp, crow = 0;
6640 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
6641 gint32 idx;
6643 MonoClass *klass = method->klass;
6644 MonoImage *image = klass->image;
6645 MonoMethodSignature *methodsig = mono_method_signature (method);
6647 MonoTableInfo *constt;
6648 MonoTableInfo *methodt;
6649 MonoTableInfo *paramt;
6651 if (!methodsig->param_count)
6652 return;
6654 mono_class_init (klass);
6656 if (klass->image->dynamic) {
6657 MonoReflectionMethodAux *aux;
6658 if (method->is_inflated)
6659 method = ((MonoMethodInflated*)method)->declaring;
6660 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6661 if (aux && aux->param_defaults) {
6662 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
6663 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
6665 return;
6668 methodt = &klass->image->tables [MONO_TABLE_METHOD];
6669 paramt = &klass->image->tables [MONO_TABLE_PARAM];
6670 constt = &image->tables [MONO_TABLE_CONSTANT];
6672 idx = mono_method_get_index (method) - 1;
6673 g_assert (idx != -1);
6675 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
6676 if (idx + 1 < methodt->rows)
6677 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
6678 else
6679 lastp = paramt->rows + 1;
6681 for (i = param_index; i < lastp; ++i) {
6682 guint32 paramseq;
6684 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
6685 paramseq = param_cols [MONO_PARAM_SEQUENCE];
6687 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT)
6688 continue;
6690 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
6691 if (!crow) {
6692 continue;
6695 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
6696 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
6697 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
6700 return;
6703 static MonoObject *
6704 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
6706 void *retval;
6707 MonoClass *klass;
6708 MonoObject *object;
6709 MonoType *basetype = type;
6711 if (!blob)
6712 return NULL;
6714 klass = mono_class_from_mono_type (type);
6715 if (klass->valuetype) {
6716 object = mono_object_new (domain, klass);
6717 retval = ((gchar *) object + sizeof (MonoObject));
6718 if (klass->enumtype)
6719 basetype = mono_class_enum_basetype (klass);
6720 } else {
6721 retval = &object;
6724 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
6725 return object;
6726 else
6727 return NULL;
6730 static int
6731 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
6732 int found_sep;
6733 char *s;
6735 memset (assembly, 0, sizeof (MonoAssemblyName));
6736 assembly->name = p;
6737 assembly->culture = "";
6738 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
6740 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
6741 p++;
6742 found_sep = 0;
6743 while (g_ascii_isspace (*p) || *p == ',') {
6744 *p++ = 0;
6745 found_sep = 1;
6746 continue;
6748 /* failed */
6749 if (!found_sep)
6750 return 1;
6751 while (*p) {
6752 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
6753 p += 8;
6754 assembly->major = strtoul (p, &s, 10);
6755 if (s == p || *s != '.')
6756 return 1;
6757 p = ++s;
6758 assembly->minor = strtoul (p, &s, 10);
6759 if (s == p || *s != '.')
6760 return 1;
6761 p = ++s;
6762 assembly->build = strtoul (p, &s, 10);
6763 if (s == p || *s != '.')
6764 return 1;
6765 p = ++s;
6766 assembly->revision = strtoul (p, &s, 10);
6767 if (s == p)
6768 return 1;
6769 p = s;
6770 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
6771 p += 8;
6772 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
6773 assembly->culture = "";
6774 p += 7;
6775 } else {
6776 assembly->culture = p;
6777 while (*p && *p != ',') {
6778 p++;
6781 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
6782 p += 15;
6783 if (strncmp (p, "null", 4) == 0) {
6784 p += 4;
6785 } else {
6786 int len;
6787 gchar *start = p;
6788 while (*p && *p != ',') {
6789 p++;
6791 len = (p - start + 1);
6792 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
6793 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
6794 g_strlcpy ((char*)assembly->public_key_token, start, len);
6796 } else {
6797 while (*p && *p != ',')
6798 p++;
6800 found_sep = 0;
6801 while (g_ascii_isspace (*p) || *p == ',') {
6802 *p++ = 0;
6803 found_sep = 1;
6804 continue;
6806 /* failed */
6807 if (!found_sep)
6808 return 1;
6811 return 0;
6815 * mono_reflection_parse_type:
6816 * @name: type name
6818 * Parse a type name as accepted by the GetType () method and output the info
6819 * extracted in the info structure.
6820 * the name param will be mangled, so, make a copy before passing it to this function.
6821 * The fields in info will be valid until the memory pointed to by name is valid.
6823 * See also mono_type_get_name () below.
6825 * Returns: 0 on parse error.
6827 static int
6828 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
6829 MonoTypeNameParse *info)
6831 char *start, *p, *w, *temp, *last_point, *startn;
6832 int in_modifiers = 0;
6833 int isbyref = 0, rank, arity = 0, i;
6835 start = p = w = name;
6837 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
6838 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
6839 info->name = info->name_space = NULL;
6840 info->nested = NULL;
6841 info->modifiers = NULL;
6842 info->type_arguments = NULL;
6844 /* last_point separates the namespace from the name */
6845 last_point = NULL;
6846 /* Skips spaces */
6847 while (*p == ' ') p++, start++, w++, name++;
6849 while (*p) {
6850 switch (*p) {
6851 case '+':
6852 *p = 0; /* NULL terminate the name */
6853 startn = p + 1;
6854 info->nested = g_list_append (info->nested, startn);
6855 /* we have parsed the nesting namespace + name */
6856 if (info->name)
6857 break;
6858 if (last_point) {
6859 info->name_space = start;
6860 *last_point = 0;
6861 info->name = last_point + 1;
6862 } else {
6863 info->name_space = (char *)"";
6864 info->name = start;
6866 break;
6867 case '.':
6868 last_point = p;
6869 break;
6870 case '\\':
6871 ++p;
6872 break;
6873 case '&':
6874 case '*':
6875 case '[':
6876 case ',':
6877 case ']':
6878 in_modifiers = 1;
6879 break;
6880 case '`':
6881 ++p;
6882 i = strtol (p, &temp, 10);
6883 arity += i;
6884 if (p == temp)
6885 return 0;
6886 p = temp-1;
6887 break;
6888 default:
6889 break;
6891 if (in_modifiers)
6892 break;
6893 // *w++ = *p++;
6894 p++;
6897 if (!info->name) {
6898 if (last_point) {
6899 info->name_space = start;
6900 *last_point = 0;
6901 info->name = last_point + 1;
6902 } else {
6903 info->name_space = (char *)"";
6904 info->name = start;
6907 while (*p) {
6908 switch (*p) {
6909 case '&':
6910 if (isbyref) /* only one level allowed by the spec */
6911 return 0;
6912 isbyref = 1;
6913 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
6914 *p++ = 0;
6915 break;
6916 case '*':
6917 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
6918 *p++ = 0;
6919 break;
6920 case '[':
6921 if (arity != 0) {
6922 *p++ = 0;
6923 info->type_arguments = g_ptr_array_new ();
6924 for (i = 0; i < arity; i++) {
6925 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
6926 gboolean fqname = FALSE;
6928 g_ptr_array_add (info->type_arguments, subinfo);
6930 if (*p == '[') {
6931 p++;
6932 fqname = TRUE;
6935 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
6936 return 0;
6938 if (fqname) {
6939 char *aname;
6941 if (*p != ',')
6942 return 0;
6943 *p++ = 0;
6945 aname = p;
6946 while (*p && (*p != ']'))
6947 p++;
6949 if (*p != ']')
6950 return 0;
6952 *p++ = 0;
6953 while (*aname) {
6954 if (g_ascii_isspace (*aname)) {
6955 ++aname;
6956 continue;
6958 break;
6960 if (!*aname ||
6961 !assembly_name_to_aname (&subinfo->assembly, aname))
6962 return 0;
6965 if (i + 1 < arity) {
6966 if (*p != ',')
6967 return 0;
6968 } else {
6969 if (*p != ']')
6970 return 0;
6972 *p++ = 0;
6975 arity = 0;
6976 break;
6978 rank = 1;
6979 *p++ = 0;
6980 while (*p) {
6981 if (*p == ']')
6982 break;
6983 if (*p == ',')
6984 rank++;
6985 else if (*p == '*') /* '*' means unknown lower bound */
6986 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
6987 else
6988 return 0;
6989 ++p;
6991 if (*p++ != ']')
6992 return 0;
6993 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
6994 break;
6995 case ']':
6996 if (is_recursed)
6997 goto end;
6998 return 0;
6999 case ',':
7000 if (is_recursed)
7001 goto end;
7002 *p++ = 0;
7003 while (*p) {
7004 if (g_ascii_isspace (*p)) {
7005 ++p;
7006 continue;
7008 break;
7010 if (!*p)
7011 return 0; /* missing assembly name */
7012 if (!assembly_name_to_aname (&info->assembly, p))
7013 return 0;
7014 break;
7015 default:
7016 return 0;
7018 if (info->assembly.name)
7019 break;
7021 // *w = 0; /* terminate class name */
7022 end:
7023 if (!info->name || !*info->name)
7024 return 0;
7025 if (endptr)
7026 *endptr = p;
7027 /* add other consistency checks */
7028 return 1;
7032 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7034 return _mono_reflection_parse_type (name, NULL, FALSE, info);
7037 static MonoType*
7038 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7040 gboolean type_resolve = FALSE;
7041 MonoType *type;
7042 MonoImage *rootimage = image;
7044 if (info->assembly.name) {
7045 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7046 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7048 * This could happen in the AOT compiler case when the search hook is not
7049 * installed.
7051 assembly = image->assembly;
7052 if (!assembly) {
7053 /* then we must load the assembly ourselve - see #60439 */
7054 assembly = mono_assembly_load (&info->assembly, NULL, NULL);
7055 if (!assembly)
7056 return NULL;
7058 image = assembly->image;
7059 } else if (!image) {
7060 image = mono_defaults.corlib;
7063 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7064 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7065 image = mono_defaults.corlib;
7066 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7069 return type;
7072 static MonoType*
7073 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7075 MonoClass *klass;
7076 GList *mod;
7077 int modval;
7078 gboolean bounded = FALSE;
7080 if (!image)
7081 image = mono_defaults.corlib;
7083 if (ignorecase)
7084 klass = mono_class_from_name_case (image, info->name_space, info->name);
7085 else
7086 klass = mono_class_from_name (image, info->name_space, info->name);
7087 if (!klass)
7088 return NULL;
7089 for (mod = info->nested; mod; mod = mod->next) {
7090 gpointer iter = NULL;
7091 MonoClass *parent;
7093 parent = klass;
7094 mono_class_init (parent);
7096 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7097 if (ignorecase) {
7098 if (g_strcasecmp (klass->name, mod->data) == 0)
7099 break;
7100 } else {
7101 if (strcmp (klass->name, mod->data) == 0)
7102 break;
7105 if (!klass)
7106 break;
7108 if (!klass)
7109 return NULL;
7110 mono_class_init (klass);
7112 if (info->type_arguments) {
7113 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7114 MonoReflectionType *the_type;
7115 MonoType *instance;
7116 int i;
7118 for (i = 0; i < info->type_arguments->len; i++) {
7119 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7121 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7122 if (!type_args [i]) {
7123 g_free (type_args);
7124 return NULL;
7128 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7130 instance = mono_reflection_bind_generic_parameters (
7131 the_type, info->type_arguments->len, type_args);
7133 g_free (type_args);
7134 if (!instance)
7135 return NULL;
7137 klass = mono_class_from_mono_type (instance);
7140 for (mod = info->modifiers; mod; mod = mod->next) {
7141 modval = GPOINTER_TO_UINT (mod->data);
7142 if (!modval) { /* byref: must be last modifier */
7143 return &klass->this_arg;
7144 } else if (modval == -1) {
7145 klass = mono_ptr_class_get (&klass->byval_arg);
7146 } else if (modval == -2) {
7147 bounded = TRUE;
7148 } else { /* array rank */
7149 klass = mono_bounded_array_class_get (klass, modval, bounded);
7151 mono_class_init (klass);
7154 return &klass->byval_arg;
7158 * mono_reflection_get_type:
7159 * @image: a metadata context
7160 * @info: type description structure
7161 * @ignorecase: flag for case-insensitive string compares
7162 * @type_resolve: whenever type resolve was already tried
7164 * Build a MonoType from the type description in @info.
7168 MonoType*
7169 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7170 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7173 static MonoType*
7174 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7176 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (mono_domain_get (), assembly);
7177 MonoType *type;
7178 int i;
7180 g_assert (assembly->dynamic);
7182 /* Enumerate all modules */
7184 type = NULL;
7185 if (abuilder->modules) {
7186 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7187 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7188 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7189 if (type)
7190 break;
7194 if (!type && abuilder->loaded_modules) {
7195 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7196 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7197 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7198 if (type)
7199 break;
7203 return type;
7206 MonoType*
7207 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7209 MonoType *type;
7210 MonoReflectionAssembly *assembly;
7211 GString *fullName;
7212 GList *mod;
7214 if (image && image->dynamic)
7215 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7216 else
7217 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7218 if (type)
7219 return type;
7220 if (!mono_domain_has_type_resolve (mono_domain_get ()))
7221 return NULL;
7223 if (type_resolve) {
7224 if (*type_resolve)
7225 return NULL;
7226 else
7227 *type_resolve = TRUE;
7230 /* Reconstruct the type name */
7231 fullName = g_string_new ("");
7232 if (info->name_space && (info->name_space [0] != '\0'))
7233 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7234 else
7235 g_string_printf (fullName, info->name);
7236 for (mod = info->nested; mod; mod = mod->next)
7237 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7239 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7240 if (assembly) {
7241 if (assembly->assembly->dynamic)
7242 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7243 else
7244 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
7245 info, ignorecase);
7247 g_string_free (fullName, TRUE);
7248 return type;
7251 void
7252 mono_reflection_free_type_info (MonoTypeNameParse *info)
7254 g_list_free (info->modifiers);
7255 g_list_free (info->nested);
7257 if (info->type_arguments) {
7258 int i;
7260 for (i = 0; i < info->type_arguments->len; i++) {
7261 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7263 mono_reflection_free_type_info (subinfo);
7264 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7265 g_free (subinfo);
7268 g_ptr_array_free (info->type_arguments, TRUE);
7273 * mono_reflection_type_from_name:
7274 * @name: type name.
7275 * @image: a metadata context (can be NULL).
7277 * Retrieves a MonoType from its @name. If the name is not fully qualified,
7278 * it defaults to get the type from @image or, if @image is NULL or loading
7279 * from it fails, uses corlib.
7282 MonoType*
7283 mono_reflection_type_from_name (char *name, MonoImage *image)
7285 MonoType *type = NULL;
7286 MonoTypeNameParse info;
7287 char *tmp;
7289 /* Make a copy since parse_type modifies its argument */
7290 tmp = g_strdup (name);
7292 /*g_print ("requested type %s\n", str);*/
7293 if (mono_reflection_parse_type (tmp, &info)) {
7294 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7297 g_free (tmp);
7298 mono_reflection_free_type_info (&info);
7299 return type;
7303 * mono_reflection_get_token:
7305 * Return the metadata token of OBJ which should be an object
7306 * representing a metadata element.
7308 guint32
7309 mono_reflection_get_token (MonoObject *obj)
7311 MonoClass *klass;
7312 guint32 token = 0;
7314 klass = obj->vtable->klass;
7316 if (strcmp (klass->name, "MethodBuilder") == 0) {
7317 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7319 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7320 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7321 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7323 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7324 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7325 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7327 /* Call mono_image_create_token so the object gets added to the tokens hash table */
7328 token = mono_image_create_token (((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image, obj, FALSE, TRUE);
7329 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7330 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7331 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7332 } else if (strcmp (klass->name, "MonoType") == 0) {
7333 MonoReflectionType *tb = (MonoReflectionType *)obj;
7334 token = mono_class_from_mono_type (tb->type)->type_token;
7335 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7336 strcmp (klass->name, "MonoMethod") == 0 ||
7337 strcmp (klass->name, "MonoGenericMethod") == 0 ||
7338 strcmp (klass->name, "MonoGenericCMethod") == 0) {
7339 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7340 if (m->method->is_inflated) {
7341 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7342 return inflated->declaring->token;
7343 } else {
7344 token = m->method->token;
7346 } else if (strcmp (klass->name, "MonoField") == 0) {
7347 MonoReflectionField *f = (MonoReflectionField*)obj;
7349 if (is_field_on_inst (f->field)) {
7350 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
7351 int field_index = f->field - dgclass->fields;
7352 MonoObject *obj;
7354 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
7355 obj = dgclass->field_objects [field_index];
7356 return mono_reflection_get_token (obj);
7358 token = mono_class_get_field_token (f->field);
7359 } else if (strcmp (klass->name, "MonoProperty") == 0) {
7360 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7362 token = mono_class_get_property_token (p->property);
7363 } else if (strcmp (klass->name, "MonoEvent") == 0) {
7364 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
7366 token = mono_class_get_event_token (p->event);
7367 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
7368 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7370 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7371 } else if (strcmp (klass->name, "Module") == 0) {
7372 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7374 token = m->token;
7375 } else if (strcmp (klass->name, "Assembly") == 0) {
7376 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7377 } else {
7378 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7379 MonoException *ex = mono_get_exception_not_implemented (msg);
7380 g_free (msg);
7381 mono_raise_exception (ex);
7384 return token;
7387 static void*
7388 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
7390 int slen, type = t->type;
7391 MonoClass *tklass = t->data.klass;
7393 handle_enum:
7394 switch (type) {
7395 case MONO_TYPE_U1:
7396 case MONO_TYPE_I1:
7397 case MONO_TYPE_BOOLEAN: {
7398 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7399 *bval = *p;
7400 *end = p + 1;
7401 return bval;
7403 case MONO_TYPE_CHAR:
7404 case MONO_TYPE_U2:
7405 case MONO_TYPE_I2: {
7406 guint16 *val = g_malloc (sizeof (guint16));
7407 *val = read16 (p);
7408 *end = p + 2;
7409 return val;
7411 #if SIZEOF_VOID_P == 4
7412 case MONO_TYPE_U:
7413 case MONO_TYPE_I:
7414 #endif
7415 case MONO_TYPE_R4:
7416 case MONO_TYPE_U4:
7417 case MONO_TYPE_I4: {
7418 guint32 *val = g_malloc (sizeof (guint32));
7419 *val = read32 (p);
7420 *end = p + 4;
7421 return val;
7423 #if SIZEOF_VOID_P == 8
7424 case MONO_TYPE_U: /* error out instead? this should probably not happen */
7425 case MONO_TYPE_I:
7426 #endif
7427 case MONO_TYPE_U8:
7428 case MONO_TYPE_I8: {
7429 guint64 *val = g_malloc (sizeof (guint64));
7430 *val = read64 (p);
7431 *end = p + 8;
7432 return val;
7434 case MONO_TYPE_R8: {
7435 double *val = g_malloc (sizeof (double));
7436 readr8 (p, val);
7437 *end = p + 8;
7438 return val;
7440 case MONO_TYPE_VALUETYPE:
7441 if (t->data.klass->enumtype) {
7442 type = mono_class_enum_basetype (t->data.klass)->type;
7443 goto handle_enum;
7444 } else {
7445 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7447 break;
7448 case MONO_TYPE_STRING:
7449 if (*p == (char)0xFF) {
7450 *end = p + 1;
7451 return NULL;
7453 slen = mono_metadata_decode_value (p, &p);
7454 *end = p + slen;
7455 return mono_string_new_len (mono_domain_get (), p, slen);
7456 case MONO_TYPE_CLASS: {
7457 char *n;
7458 MonoType *t;
7459 if (*p == (char)0xFF) {
7460 *end = p + 1;
7461 return NULL;
7463 handle_type:
7464 slen = mono_metadata_decode_value (p, &p);
7465 n = g_memdup (p, slen + 1);
7466 n [slen] = 0;
7467 t = mono_reflection_type_from_name (n, image);
7468 if (!t)
7469 g_warning ("Cannot load type '%s'", n);
7470 g_free (n);
7471 *end = p + slen;
7472 if (t)
7473 return mono_type_get_object (mono_domain_get (), t);
7474 else
7475 return NULL;
7477 case MONO_TYPE_OBJECT: {
7478 char subt = *p++;
7479 MonoObject *obj;
7480 MonoClass *subc = NULL;
7481 void *val;
7483 if (subt == 0x50) {
7484 goto handle_type;
7485 } else if (subt == 0x0E) {
7486 type = MONO_TYPE_STRING;
7487 goto handle_enum;
7488 } else if (subt == 0x1D) {
7489 MonoType simple_type = {{0}};
7490 int etype = *p;
7491 p ++;
7493 if (etype == 0x51)
7494 /* See Partition II, Appendix B3 */
7495 etype = MONO_TYPE_OBJECT;
7496 type = MONO_TYPE_SZARRAY;
7497 simple_type.type = etype;
7498 tklass = mono_class_from_mono_type (&simple_type);
7499 goto handle_enum;
7500 } else if (subt == 0x55) {
7501 char *n;
7502 MonoType *t;
7503 slen = mono_metadata_decode_value (p, &p);
7504 n = g_memdup (p, slen + 1);
7505 n [slen] = 0;
7506 t = mono_reflection_type_from_name (n, image);
7507 if (!t)
7508 g_error ("Cannot load type '%s'", n);
7509 g_free (n);
7510 p += slen;
7511 subc = mono_class_from_mono_type (t);
7512 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
7513 MonoType simple_type = {{0}};
7514 simple_type.type = subt;
7515 subc = mono_class_from_mono_type (&simple_type);
7516 } else {
7517 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
7519 val = load_cattr_value (image, &subc->byval_arg, p, end);
7520 obj = mono_object_new (mono_domain_get (), subc);
7521 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
7522 g_free (val);
7523 return obj;
7525 case MONO_TYPE_SZARRAY: {
7526 MonoArray *arr;
7527 guint32 i, alen, basetype;
7528 alen = read32 (p);
7529 p += 4;
7530 if (alen == 0xffffffff) {
7531 *end = p;
7532 return NULL;
7534 arr = mono_array_new (mono_domain_get(), tklass, alen);
7535 basetype = tklass->byval_arg.type;
7536 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
7537 basetype = mono_class_enum_basetype (tklass)->type;
7538 switch (basetype)
7540 case MONO_TYPE_U1:
7541 case MONO_TYPE_I1:
7542 case MONO_TYPE_BOOLEAN:
7543 for (i = 0; i < alen; i++) {
7544 MonoBoolean val = *p++;
7545 mono_array_set (arr, MonoBoolean, i, val);
7547 break;
7548 case MONO_TYPE_CHAR:
7549 case MONO_TYPE_U2:
7550 case MONO_TYPE_I2:
7551 for (i = 0; i < alen; i++) {
7552 guint16 val = read16 (p);
7553 mono_array_set (arr, guint16, i, val);
7554 p += 2;
7556 break;
7557 case MONO_TYPE_R4:
7558 case MONO_TYPE_U4:
7559 case MONO_TYPE_I4:
7560 for (i = 0; i < alen; i++) {
7561 guint32 val = read32 (p);
7562 mono_array_set (arr, guint32, i, val);
7563 p += 4;
7565 break;
7566 case MONO_TYPE_R8:
7567 for (i = 0; i < alen; i++) {
7568 double val;
7569 readr8 (p, &val);
7570 mono_array_set (arr, double, i, val);
7571 p += 8;
7573 break;
7574 case MONO_TYPE_U8:
7575 case MONO_TYPE_I8:
7576 for (i = 0; i < alen; i++) {
7577 guint64 val = read64 (p);
7578 mono_array_set (arr, guint64, i, val);
7579 p += 8;
7581 break;
7582 case MONO_TYPE_CLASS:
7583 case MONO_TYPE_OBJECT:
7584 case MONO_TYPE_STRING:
7585 for (i = 0; i < alen; i++) {
7586 MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
7587 mono_array_setref (arr, i, item);
7589 break;
7590 default:
7591 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
7593 *end=p;
7594 return arr;
7596 default:
7597 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
7599 return NULL;
7602 static MonoObject*
7603 create_cattr_typed_arg (MonoType *t, MonoObject *val)
7605 static MonoClass *klass;
7606 static MonoMethod *ctor;
7607 MonoObject *retval;
7608 void *params [2], *unboxed;
7610 if (!klass)
7611 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
7612 if (!ctor)
7613 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7615 params [0] = mono_type_get_object (mono_domain_get (), t);
7616 params [1] = val;
7617 retval = mono_object_new (mono_domain_get (), klass);
7618 unboxed = mono_object_unbox (retval);
7619 mono_runtime_invoke (ctor, unboxed, params, NULL);
7621 return retval;
7624 static MonoObject*
7625 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
7627 static MonoClass *klass;
7628 static MonoMethod *ctor;
7629 MonoObject *retval;
7630 void *unboxed, *params [2];
7632 if (!klass)
7633 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
7634 if (!ctor)
7635 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7637 params [0] = minfo;
7638 params [1] = typedarg;
7639 retval = mono_object_new (mono_domain_get (), klass);
7640 unboxed = mono_object_unbox (retval);
7641 mono_runtime_invoke (ctor, unboxed, params, NULL);
7643 return retval;
7646 static gboolean
7647 type_is_reference (MonoType *type)
7649 switch (type->type) {
7650 case MONO_TYPE_BOOLEAN:
7651 case MONO_TYPE_CHAR:
7652 case MONO_TYPE_U:
7653 case MONO_TYPE_I:
7654 case MONO_TYPE_U1:
7655 case MONO_TYPE_I1:
7656 case MONO_TYPE_U2:
7657 case MONO_TYPE_I2:
7658 case MONO_TYPE_U4:
7659 case MONO_TYPE_I4:
7660 case MONO_TYPE_U8:
7661 case MONO_TYPE_I8:
7662 case MONO_TYPE_R8:
7663 case MONO_TYPE_R4:
7664 case MONO_TYPE_VALUETYPE:
7665 return FALSE;
7666 default:
7667 return TRUE;
7671 static void
7672 free_param_data (MonoMethodSignature *sig, void **params) {
7673 int i;
7674 for (i = 0; i < sig->param_count; ++i) {
7675 if (!type_is_reference (sig->params [i]))
7676 g_free (params [i]);
7681 * Find the field index in the metadata FieldDef table.
7683 static guint32
7684 find_field_index (MonoClass *klass, MonoClassField *field) {
7685 int i;
7687 for (i = 0; i < klass->field.count; ++i) {
7688 if (field == &klass->fields [i])
7689 return klass->field.first + 1 + i;
7691 return 0;
7695 * Find the property index in the metadata Property table.
7697 static guint32
7698 find_property_index (MonoClass *klass, MonoProperty *property) {
7699 int i;
7701 for (i = 0; i < klass->ext->property.count; ++i) {
7702 if (property == &klass->ext->properties [i])
7703 return klass->ext->property.first + 1 + i;
7705 return 0;
7709 * Find the event index in the metadata Event table.
7711 static guint32
7712 find_event_index (MonoClass *klass, MonoEvent *event) {
7713 int i;
7715 for (i = 0; i < klass->ext->event.count; ++i) {
7716 if (event == &klass->ext->events [i])
7717 return klass->ext->event.first + 1 + i;
7719 return 0;
7722 static MonoObject*
7723 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7725 const char *p = (const char*)data;
7726 const char *named;
7727 guint32 i, j, num_named;
7728 MonoObject *attr;
7729 void *params_buf [32];
7730 void **params;
7731 MonoMethodSignature *sig;
7733 mono_class_init (method->klass);
7735 if (len == 0) {
7736 attr = mono_object_new (mono_domain_get (), method->klass);
7737 mono_runtime_invoke (method, attr, NULL, NULL);
7738 return attr;
7741 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7742 return NULL;
7744 /*g_print ("got attr %s\n", method->klass->name);*/
7746 sig = mono_method_signature (method);
7747 if (sig->param_count < 32)
7748 params = params_buf;
7749 else
7750 /* Allocate using GC so it gets GC tracking */
7751 params = mono_gc_alloc_fixed (sig->param_count * sizeof (void*), NULL);
7753 /* skip prolog */
7754 p += 2;
7755 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7756 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7759 named = p;
7760 attr = mono_object_new (mono_domain_get (), method->klass);
7761 mono_runtime_invoke (method, attr, params, NULL);
7762 free_param_data (method->signature, params);
7763 num_named = read16 (named);
7764 named += 2;
7765 for (j = 0; j < num_named; j++) {
7766 gint name_len;
7767 char *name, named_type, data_type;
7768 named_type = *named++;
7769 data_type = *named++; /* type of data */
7770 if (data_type == MONO_TYPE_SZARRAY)
7771 data_type = *named++;
7772 if (data_type == MONO_TYPE_ENUM) {
7773 gint type_len;
7774 char *type_name;
7775 type_len = mono_metadata_decode_blob_size (named, &named);
7776 type_name = g_malloc (type_len + 1);
7777 memcpy (type_name, named, type_len);
7778 type_name [type_len] = 0;
7779 named += type_len;
7780 /* FIXME: lookup the type and check type consistency */
7781 g_free (type_name);
7783 name_len = mono_metadata_decode_blob_size (named, &named);
7784 name = g_malloc (name_len + 1);
7785 memcpy (name, named, name_len);
7786 name [name_len] = 0;
7787 named += name_len;
7788 if (named_type == 0x53) {
7789 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
7790 void *val = load_cattr_value (image, field->type, named, &named);
7791 mono_field_set_value (attr, field, val);
7792 if (!type_is_reference (field->type))
7793 g_free (val);
7794 } else if (named_type == 0x54) {
7795 MonoProperty *prop;
7796 void *pparams [1];
7797 MonoType *prop_type;
7799 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
7800 /* can we have more that 1 arg in a custom attr named property? */
7801 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7802 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7803 pparams [0] = load_cattr_value (image, prop_type, named, &named);
7804 mono_property_set_value (prop, attr, pparams, NULL);
7805 if (!type_is_reference (prop_type))
7806 g_free (pparams [0]);
7808 g_free (name);
7811 if (params != params_buf)
7812 mono_gc_free_fixed (params);
7814 return attr;
7817 static MonoObject*
7818 create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7820 MonoArray *typedargs, *namedargs;
7821 MonoClass *attrklass;
7822 static MonoMethod *ctor;
7823 MonoDomain *domain;
7824 MonoObject *attr;
7825 const char *p = (const char*)data;
7826 const char *named;
7827 guint32 i, j, num_named;
7828 void *params [3];
7830 mono_class_init (method->klass);
7832 if (!ctor)
7833 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 3);
7835 domain = mono_domain_get ();
7836 if (len == 0) {
7837 /* This is for Attributes with no parameters */
7838 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
7839 params [0] = mono_method_get_object (domain, method, NULL);
7840 params [1] = params [2] = NULL;
7841 mono_runtime_invoke (method, attr, params, NULL);
7842 return attr;
7845 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7846 return NULL;
7848 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
7850 /* skip prolog */
7851 p += 2;
7852 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7853 MonoObject *obj, *typedarg;
7854 void *val;
7856 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7857 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
7858 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
7859 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
7860 mono_array_setref (typedargs, i, typedarg);
7862 if (!type_is_reference (mono_method_signature (method)->params [i]))
7863 g_free (val);
7866 named = p;
7867 num_named = read16 (named);
7868 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
7869 named += 2;
7870 attrklass = method->klass;
7871 for (j = 0; j < num_named; j++) {
7872 gint name_len;
7873 char *name, named_type, data_type;
7874 named_type = *named++;
7875 data_type = *named++; /* type of data */
7876 if (data_type == MONO_TYPE_SZARRAY)
7877 data_type = *named++;
7878 if (data_type == MONO_TYPE_ENUM) {
7879 gint type_len;
7880 char *type_name;
7881 type_len = mono_metadata_decode_blob_size (named, &named);
7882 type_name = g_malloc (type_len + 1);
7883 memcpy (type_name, named, type_len);
7884 type_name [type_len] = 0;
7885 named += type_len;
7886 /* FIXME: lookup the type and check type consistency */
7887 g_free (type_name);
7889 name_len = mono_metadata_decode_blob_size (named, &named);
7890 name = g_malloc (name_len + 1);
7891 memcpy (name, named, name_len);
7892 name [name_len] = 0;
7893 named += name_len;
7894 if (named_type == 0x53) {
7895 MonoObject *obj, *typedarg, *namedarg;
7896 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
7897 void *minfo, *val = load_cattr_value (image, field->type, named, &named);
7899 minfo = mono_field_get_object (domain, NULL, field);
7900 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
7901 typedarg = create_cattr_typed_arg (field->type, obj);
7902 namedarg = create_cattr_named_arg (minfo, typedarg);
7903 mono_array_setref (namedargs, j, namedarg);
7904 if (!type_is_reference (field->type))
7905 g_free (val);
7906 } else if (named_type == 0x54) {
7907 MonoObject *obj, *typedarg, *namedarg;
7908 MonoType *prop_type;
7909 void *val, *minfo;
7910 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
7912 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7913 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7914 minfo = mono_property_get_object (domain, NULL, prop);
7915 val = load_cattr_value (image, prop_type, named, &named);
7916 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
7917 typedarg = create_cattr_typed_arg (prop_type, obj);
7918 namedarg = create_cattr_named_arg (minfo, typedarg);
7919 mono_array_setref (namedargs, j, namedarg);
7920 if (!type_is_reference (prop_type))
7921 g_free (val);
7923 g_free (name);
7925 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
7926 params [0] = mono_method_get_object (domain, method, NULL);
7927 params [1] = typedargs;
7928 params [2] = namedargs;
7929 mono_runtime_invoke (ctor, attr, params, NULL);
7930 return attr;
7933 MonoArray*
7934 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
7936 MonoArray *result;
7937 MonoObject *attr;
7938 int i;
7940 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, cinfo->num_attrs);
7941 for (i = 0; i < cinfo->num_attrs; ++i) {
7942 if (!cinfo->attrs [i].ctor)
7943 /* The cattr type is not finished yet */
7944 /* We should include the type name but cinfo doesn't contain it */
7945 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
7946 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7947 mono_array_setref (result, i, attr);
7949 return result;
7952 static MonoArray*
7953 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass)
7955 MonoArray *result;
7956 MonoObject *attr;
7957 int i, n;
7959 n = 0;
7960 for (i = 0; i < cinfo->num_attrs; ++i) {
7961 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
7962 n ++;
7965 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
7966 n = 0;
7967 for (i = 0; i < cinfo->num_attrs; ++i) {
7968 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
7969 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7970 mono_array_setref (result, n, attr);
7971 n ++;
7974 return result;
7977 static MonoArray*
7978 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
7980 MonoArray *result;
7981 MonoObject *attr;
7982 int i;
7984 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
7985 for (i = 0; i < cinfo->num_attrs; ++i) {
7986 attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7987 mono_array_setref (result, i, attr);
7989 return result;
7993 * mono_custom_attrs_from_index:
7995 * Returns: NULL if no attributes are found or if a loading error occurs.
7997 MonoCustomAttrInfo*
7998 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
8000 guint32 mtoken, i, len;
8001 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
8002 MonoTableInfo *ca;
8003 MonoCustomAttrInfo *ainfo;
8004 GList *tmp, *list = NULL;
8005 const char *data;
8007 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
8009 i = mono_metadata_custom_attrs_from_index (image, idx);
8010 if (!i)
8011 return NULL;
8012 i --;
8013 while (i < ca->rows) {
8014 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
8015 break;
8016 list = g_list_prepend (list, GUINT_TO_POINTER (i));
8017 ++i;
8019 len = g_list_length (list);
8020 if (!len)
8021 return NULL;
8022 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
8023 ainfo->num_attrs = len;
8024 ainfo->image = image;
8025 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
8026 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
8027 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
8028 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
8029 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
8030 mtoken |= MONO_TOKEN_METHOD_DEF;
8031 break;
8032 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
8033 mtoken |= MONO_TOKEN_MEMBER_REF;
8034 break;
8035 default:
8036 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
8037 break;
8039 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
8040 if (!ainfo->attrs [i].ctor) {
8041 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
8042 g_list_free (list);
8043 g_free (ainfo);
8044 return NULL;
8046 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
8047 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
8048 ainfo->attrs [i].data = (guchar*)data;
8050 g_list_free (list);
8052 return ainfo;
8055 MonoCustomAttrInfo*
8056 mono_custom_attrs_from_method (MonoMethod *method)
8058 guint32 idx;
8061 * An instantiated method has the same cattrs as the generic method definition.
8063 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8064 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8066 if (method->is_inflated)
8067 method = ((MonoMethodInflated *) method)->declaring;
8069 if (method->dynamic || method->klass->image->dynamic)
8070 return lookup_custom_attr (method->klass->image, method);
8072 idx = mono_method_get_index (method);
8073 idx <<= MONO_CUSTOM_ATTR_BITS;
8074 idx |= MONO_CUSTOM_ATTR_METHODDEF;
8075 return mono_custom_attrs_from_index (method->klass->image, idx);
8078 MonoCustomAttrInfo*
8079 mono_custom_attrs_from_class (MonoClass *klass)
8081 guint32 idx;
8083 if (klass->generic_class)
8084 klass = klass->generic_class->container_class;
8086 if (klass->image->dynamic)
8087 return lookup_custom_attr (klass->image, klass);
8089 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
8090 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
8091 idx <<= MONO_CUSTOM_ATTR_BITS;
8092 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
8093 } else {
8094 idx = mono_metadata_token_index (klass->type_token);
8095 idx <<= MONO_CUSTOM_ATTR_BITS;
8096 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
8098 return mono_custom_attrs_from_index (klass->image, idx);
8101 MonoCustomAttrInfo*
8102 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
8104 guint32 idx;
8106 if (assembly->image->dynamic)
8107 return lookup_custom_attr (assembly->image, assembly);
8108 idx = 1; /* there is only one assembly */
8109 idx <<= MONO_CUSTOM_ATTR_BITS;
8110 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
8111 return mono_custom_attrs_from_index (assembly->image, idx);
8114 static MonoCustomAttrInfo*
8115 mono_custom_attrs_from_module (MonoImage *image)
8117 guint32 idx;
8119 if (image->dynamic)
8120 return lookup_custom_attr (image, image);
8121 idx = 1; /* there is only one module */
8122 idx <<= MONO_CUSTOM_ATTR_BITS;
8123 idx |= MONO_CUSTOM_ATTR_MODULE;
8124 return mono_custom_attrs_from_index (image, idx);
8127 MonoCustomAttrInfo*
8128 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
8130 guint32 idx;
8132 if (klass->image->dynamic) {
8133 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
8134 return lookup_custom_attr (klass->image, property);
8136 idx = find_property_index (klass, property);
8137 idx <<= MONO_CUSTOM_ATTR_BITS;
8138 idx |= MONO_CUSTOM_ATTR_PROPERTY;
8139 return mono_custom_attrs_from_index (klass->image, idx);
8142 MonoCustomAttrInfo*
8143 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
8145 guint32 idx;
8147 if (klass->image->dynamic) {
8148 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
8149 return lookup_custom_attr (klass->image, event);
8151 idx = find_event_index (klass, event);
8152 idx <<= MONO_CUSTOM_ATTR_BITS;
8153 idx |= MONO_CUSTOM_ATTR_EVENT;
8154 return mono_custom_attrs_from_index (klass->image, idx);
8157 MonoCustomAttrInfo*
8158 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
8160 guint32 idx;
8161 if (klass->image->dynamic) {
8162 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
8163 return lookup_custom_attr (klass->image, field);
8165 idx = find_field_index (klass, field);
8166 idx <<= MONO_CUSTOM_ATTR_BITS;
8167 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
8168 return mono_custom_attrs_from_index (klass->image, idx);
8171 MonoCustomAttrInfo*
8172 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
8174 MonoTableInfo *ca;
8175 guint32 i, idx, method_index;
8176 guint32 param_list, param_last, param_pos, found;
8177 MonoImage *image;
8178 MonoReflectionMethodAux *aux;
8181 * An instantiated method has the same cattrs as the generic method definition.
8183 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8184 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8186 if (method->is_inflated)
8187 method = ((MonoMethodInflated *) method)->declaring;
8189 if (method->klass->image->dynamic) {
8190 MonoCustomAttrInfo *res, *ainfo;
8191 int size;
8193 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8194 if (!aux || !aux->param_cattr)
8195 return NULL;
8197 /* Need to copy since it will be freed later */
8198 ainfo = aux->param_cattr [param];
8199 size = sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (ainfo->num_attrs - MONO_ZERO_LEN_ARRAY);
8200 res = g_malloc0 (size);
8201 memcpy (res, ainfo, size);
8202 return res;
8205 image = method->klass->image;
8206 method_index = mono_method_get_index (method);
8207 ca = &image->tables [MONO_TABLE_METHOD];
8209 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
8210 if (method_index == ca->rows) {
8211 ca = &image->tables [MONO_TABLE_PARAM];
8212 param_last = ca->rows + 1;
8213 } else {
8214 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
8215 ca = &image->tables [MONO_TABLE_PARAM];
8217 found = FALSE;
8218 for (i = param_list; i < param_last; ++i) {
8219 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
8220 if (param_pos == param) {
8221 found = TRUE;
8222 break;
8225 if (!found)
8226 return NULL;
8227 idx = i;
8228 idx <<= MONO_CUSTOM_ATTR_BITS;
8229 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
8230 return mono_custom_attrs_from_index (image, idx);
8233 gboolean
8234 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8236 int i;
8237 MonoClass *klass;
8238 for (i = 0; i < ainfo->num_attrs; ++i) {
8239 klass = ainfo->attrs [i].ctor->klass;
8240 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
8241 return TRUE;
8243 return FALSE;
8246 MonoObject*
8247 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8249 int i, attr_index;
8250 MonoClass *klass;
8251 MonoArray *attrs;
8253 attr_index = -1;
8254 for (i = 0; i < ainfo->num_attrs; ++i) {
8255 klass = ainfo->attrs [i].ctor->klass;
8256 if (mono_class_has_parent (klass, attr_klass)) {
8257 attr_index = i;
8258 break;
8261 if (attr_index == -1)
8262 return NULL;
8264 attrs = mono_custom_attrs_construct (ainfo);
8265 if (attrs)
8266 return mono_array_get (attrs, MonoObject*, attr_index);
8267 else
8268 return NULL;
8272 * mono_reflection_get_custom_attrs_info:
8273 * @obj: a reflection object handle
8275 * Return the custom attribute info for attributes defined for the
8276 * reflection handle @obj. The objects.
8278 * FIXME this function leaks like a sieve for SRE objects.
8280 MonoCustomAttrInfo*
8281 mono_reflection_get_custom_attrs_info (MonoObject *obj)
8283 MonoClass *klass;
8284 MonoCustomAttrInfo *cinfo = NULL;
8286 klass = obj->vtable->klass;
8287 if (klass == mono_defaults.monotype_class) {
8288 MonoReflectionType *rtype = (MonoReflectionType*)obj;
8289 klass = mono_class_from_mono_type (rtype->type);
8290 cinfo = mono_custom_attrs_from_class (klass);
8291 } else if (strcmp ("Assembly", klass->name) == 0) {
8292 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
8293 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
8294 } else if (strcmp ("Module", klass->name) == 0) {
8295 MonoReflectionModule *module = (MonoReflectionModule*)obj;
8296 cinfo = mono_custom_attrs_from_module (module->image);
8297 } else if (strcmp ("MonoProperty", klass->name) == 0) {
8298 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
8299 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
8300 } else if (strcmp ("MonoEvent", klass->name) == 0) {
8301 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
8302 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
8303 } else if (strcmp ("MonoField", klass->name) == 0) {
8304 MonoReflectionField *rfield = (MonoReflectionField*)obj;
8305 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
8306 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
8307 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8308 cinfo = mono_custom_attrs_from_method (rmethod->method);
8309 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
8310 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8311 cinfo = mono_custom_attrs_from_method (rmethod->method);
8312 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
8313 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
8314 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8315 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
8316 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
8317 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
8318 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
8319 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
8320 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8321 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
8322 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
8323 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
8324 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
8325 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
8326 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8327 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
8328 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
8329 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8330 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
8331 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
8332 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8333 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
8334 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
8335 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
8336 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
8337 } else { /* handle other types here... */
8338 g_error ("get custom attrs not yet supported for %s", klass->name);
8341 return cinfo;
8345 * mono_reflection_get_custom_attrs_by_type:
8346 * @obj: a reflection object handle
8348 * Return an array with all the custom attributes defined of the
8349 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
8350 * of that type are returned. The objects are fully build. Return NULL if a loading error
8351 * occurs.
8353 MonoArray*
8354 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass)
8356 MonoArray *result;
8357 MonoCustomAttrInfo *cinfo;
8359 cinfo = mono_reflection_get_custom_attrs_info (obj);
8360 if (cinfo) {
8361 if (attr_klass)
8362 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass);
8363 else
8364 result = mono_custom_attrs_construct (cinfo);
8365 if (!cinfo->cached)
8366 mono_custom_attrs_free (cinfo);
8367 } else {
8368 if (mono_loader_get_last_error ())
8369 return NULL;
8370 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
8373 return result;
8377 * mono_reflection_get_custom_attrs:
8378 * @obj: a reflection object handle
8380 * Return an array with all the custom attributes defined of the
8381 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
8382 * occurs.
8384 MonoArray*
8385 mono_reflection_get_custom_attrs (MonoObject *obj)
8387 return mono_reflection_get_custom_attrs_by_type (obj, NULL);
8391 * mono_reflection_get_custom_attrs_data:
8392 * @obj: a reflection obj handle
8394 * Returns an array of System.Reflection.CustomAttributeData,
8395 * which include information about attributes reflected on
8396 * types loaded using the Reflection Only methods
8398 MonoArray*
8399 mono_reflection_get_custom_attrs_data (MonoObject *obj)
8401 MonoArray *result;
8402 MonoCustomAttrInfo *cinfo;
8404 cinfo = mono_reflection_get_custom_attrs_info (obj);
8405 if (cinfo) {
8406 result = mono_custom_attrs_data_construct (cinfo);
8407 if (!cinfo->cached)
8408 mono_custom_attrs_free (cinfo);
8409 } else
8410 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
8412 return result;
8415 static MonoReflectionType*
8416 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
8418 MonoMethod *method_get_underlying_system_type;
8420 method_get_underlying_system_type = mono_object_get_virtual_method ((MonoObject *) t,
8421 mono_class_get_method_from_name (mono_object_class (t),
8422 "get_UnderlyingSystemType",
8423 0));
8424 return (MonoReflectionType *) mono_runtime_invoke (method_get_underlying_system_type, t, NULL, NULL);
8427 static MonoType*
8428 mono_reflection_type_get_handle (MonoReflectionType* t)
8430 if (t->type)
8431 return t->type;
8433 t = mono_reflection_type_get_underlying_system_type (t);
8434 if (t)
8435 return t->type;
8437 return NULL;
8441 * LOCKING: Assumes the loader lock is held.
8443 static MonoMethodSignature*
8444 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
8445 MonoMethodSignature *sig;
8446 int count, i;
8448 count = parameters? mono_array_length (parameters): 0;
8450 sig = image_g_malloc0 (image, sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
8451 sig->param_count = count;
8452 sig->sentinelpos = -1; /* FIXME */
8453 for (i = 0; i < count; ++i) {
8454 MonoReflectionType *pt = mono_type_array_get (parameters, i);
8455 sig->params [i] = mono_reflection_type_get_handle (pt);
8457 return sig;
8461 * LOCKING: Assumes the loader lock is held.
8463 static MonoMethodSignature*
8464 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
8465 MonoMethodSignature *sig;
8467 sig = parameters_to_signature (image, ctor->parameters);
8468 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8469 sig->ret = &mono_defaults.void_class->byval_arg;
8470 return sig;
8474 * LOCKING: Assumes the loader lock is held.
8476 static MonoMethodSignature*
8477 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
8478 MonoMethodSignature *sig;
8480 sig = parameters_to_signature (image, method->parameters);
8481 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8482 sig->ret = method->rtype? monotype_cast (method->rtype)->type: &mono_defaults.void_class->byval_arg;
8483 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
8484 return sig;
8487 static MonoMethodSignature*
8488 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
8489 MonoMethodSignature *sig;
8491 sig = parameters_to_signature (NULL, method->parameters);
8492 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8493 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
8494 sig->generic_param_count = 0;
8495 return sig;
8498 static void
8499 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
8501 MonoClass *klass = mono_object_class (prop);
8502 if (strcmp (klass->name, "PropertyBuilder") == 0) {
8503 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
8504 *name = mono_string_to_utf8 (pb->name);
8505 *type = monotype_cast (pb->type)->type;
8506 } else {
8507 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
8508 *name = g_strdup (p->property->name);
8509 if (p->property->get)
8510 *type = mono_method_signature (p->property->get)->ret;
8511 else
8512 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
8516 static void
8517 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
8519 MonoClass *klass = mono_object_class (field);
8520 if (strcmp (klass->name, "FieldBuilder") == 0) {
8521 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
8522 *name = mono_string_to_utf8 (fb->name);
8523 *type = monotype_cast (fb->type)->type;
8524 } else {
8525 MonoReflectionField *f = (MonoReflectionField *)field;
8526 *name = g_strdup (mono_field_get_name (f->field));
8527 *type = f->field->type;
8532 * Encode a value in a custom attribute stream of bytes.
8533 * The value to encode is either supplied as an object in argument val
8534 * (valuetypes are boxed), or as a pointer to the data in the
8535 * argument argval.
8536 * @type represents the type of the value
8537 * @buffer is the start of the buffer
8538 * @p the current position in the buffer
8539 * @buflen contains the size of the buffer and is used to return the new buffer size
8540 * if this needs to be realloced.
8541 * @retbuffer and @retp return the start and the position of the buffer
8543 static void
8544 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
8546 MonoTypeEnum simple_type;
8548 if ((p-buffer) + 10 >= *buflen) {
8549 char *newbuf;
8550 *buflen *= 2;
8551 newbuf = g_realloc (buffer, *buflen);
8552 p = newbuf + (p-buffer);
8553 buffer = newbuf;
8555 if (!argval)
8556 argval = ((char*)arg + sizeof (MonoObject));
8557 simple_type = type->type;
8558 handle_enum:
8559 switch (simple_type) {
8560 case MONO_TYPE_BOOLEAN:
8561 case MONO_TYPE_U1:
8562 case MONO_TYPE_I1:
8563 *p++ = *argval;
8564 break;
8565 case MONO_TYPE_CHAR:
8566 case MONO_TYPE_U2:
8567 case MONO_TYPE_I2:
8568 swap_with_size (p, argval, 2, 1);
8569 p += 2;
8570 break;
8571 case MONO_TYPE_U4:
8572 case MONO_TYPE_I4:
8573 case MONO_TYPE_R4:
8574 swap_with_size (p, argval, 4, 1);
8575 p += 4;
8576 break;
8577 case MONO_TYPE_R8:
8578 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
8579 p [0] = argval [4];
8580 p [1] = argval [5];
8581 p [2] = argval [6];
8582 p [3] = argval [7];
8583 p [4] = argval [0];
8584 p [5] = argval [1];
8585 p [6] = argval [2];
8586 p [7] = argval [3];
8587 #else
8588 swap_with_size (p, argval, 8, 1);
8589 #endif
8590 p += 8;
8591 break;
8592 case MONO_TYPE_U8:
8593 case MONO_TYPE_I8:
8594 swap_with_size (p, argval, 8, 1);
8595 p += 8;
8596 break;
8597 case MONO_TYPE_VALUETYPE:
8598 if (type->data.klass->enumtype) {
8599 simple_type = mono_class_enum_basetype (type->data.klass)->type;
8600 goto handle_enum;
8601 } else {
8602 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
8604 break;
8605 case MONO_TYPE_STRING: {
8606 char *str;
8607 guint32 slen;
8608 if (!arg) {
8609 *p++ = 0xFF;
8610 break;
8612 str = mono_string_to_utf8 ((MonoString*)arg);
8613 slen = strlen (str);
8614 if ((p-buffer) + 10 + slen >= *buflen) {
8615 char *newbuf;
8616 *buflen *= 2;
8617 *buflen += slen;
8618 newbuf = g_realloc (buffer, *buflen);
8619 p = newbuf + (p-buffer);
8620 buffer = newbuf;
8622 mono_metadata_encode_value (slen, p, &p);
8623 memcpy (p, str, slen);
8624 p += slen;
8625 g_free (str);
8626 break;
8628 case MONO_TYPE_CLASS: {
8629 char *str;
8630 guint32 slen;
8631 MonoClass *k;
8632 if (!arg) {
8633 *p++ = 0xFF;
8634 break;
8636 k = mono_object_class (arg);
8637 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
8638 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit"))) {
8639 MonoReflectionType* rt = mono_reflection_type_get_underlying_system_type ((MonoReflectionType*) arg);
8640 MonoClass *rtc;
8642 if (rt && (rtc = mono_object_class (rt)) &&
8643 (mono_object_isinst ((MonoObject *) rt, mono_defaults.monotype_class) ||
8644 !strcmp (rtc->name, "TypeBuilder") || !strcmp (rtc->name_space, "System.Reflection.Emit"))) {
8645 arg = (MonoObject *) rt;
8646 k = rtc;
8647 } else
8648 g_error ("Only System.Type allowed, not %s.%s", k->name_space, k->name);
8650 handle_type:
8651 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
8652 slen = strlen (str);
8653 if ((p-buffer) + 10 + slen >= *buflen) {
8654 char *newbuf;
8655 *buflen *= 2;
8656 *buflen += slen;
8657 newbuf = g_realloc (buffer, *buflen);
8658 p = newbuf + (p-buffer);
8659 buffer = newbuf;
8661 mono_metadata_encode_value (slen, p, &p);
8662 memcpy (p, str, slen);
8663 p += slen;
8664 g_free (str);
8665 break;
8667 case MONO_TYPE_SZARRAY: {
8668 int len, i;
8669 MonoClass *eclass, *arg_eclass;
8671 if (!arg) {
8672 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
8673 break;
8675 len = mono_array_length ((MonoArray*)arg);
8676 *p++ = len & 0xff;
8677 *p++ = (len >> 8) & 0xff;
8678 *p++ = (len >> 16) & 0xff;
8679 *p++ = (len >> 24) & 0xff;
8680 *retp = p;
8681 *retbuffer = buffer;
8682 eclass = type->data.klass;
8683 arg_eclass = mono_object_class (arg)->element_class;
8685 if (!eclass) {
8686 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
8687 eclass = mono_defaults.object_class;
8689 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
8690 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
8691 int elsize = mono_class_array_element_size (arg_eclass);
8692 for (i = 0; i < len; ++i) {
8693 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
8694 elptr += elsize;
8696 } else if (eclass->valuetype && arg_eclass->valuetype) {
8697 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
8698 int elsize = mono_class_array_element_size (eclass);
8699 for (i = 0; i < len; ++i) {
8700 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
8701 elptr += elsize;
8703 } else {
8704 for (i = 0; i < len; ++i) {
8705 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
8708 break;
8710 case MONO_TYPE_OBJECT: {
8711 MonoClass *klass;
8712 char *str;
8713 guint32 slen;
8716 * The parameter type is 'object' but the type of the actual
8717 * argument is not. So we have to add type information to the blob
8718 * too. This is completely undocumented in the spec.
8721 if (arg == NULL) {
8722 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
8723 *p++ = 0xFF;
8724 break;
8727 klass = mono_object_class (arg);
8729 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
8730 *p++ = 0x50;
8731 goto handle_type;
8732 } else if (klass->enumtype) {
8733 *p++ = 0x55;
8734 } else if (klass == mono_defaults.string_class) {
8735 simple_type = MONO_TYPE_STRING;
8736 *p++ = 0x0E;
8737 goto handle_enum;
8738 } else if (klass->rank == 1) {
8739 *p++ = 0x1D;
8740 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
8741 /* See Partition II, Appendix B3 */
8742 *p++ = 0x51;
8743 else
8744 *p++ = klass->element_class->byval_arg.type;
8745 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
8746 break;
8747 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
8748 *p++ = simple_type = klass->byval_arg.type;
8749 goto handle_enum;
8750 } else {
8751 g_error ("unhandled type in custom attr");
8753 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
8754 slen = strlen (str);
8755 if ((p-buffer) + 10 + slen >= *buflen) {
8756 char *newbuf;
8757 *buflen *= 2;
8758 *buflen += slen;
8759 newbuf = g_realloc (buffer, *buflen);
8760 p = newbuf + (p-buffer);
8761 buffer = newbuf;
8763 mono_metadata_encode_value (slen, p, &p);
8764 memcpy (p, str, slen);
8765 p += slen;
8766 g_free (str);
8767 simple_type = mono_class_enum_basetype (klass)->type;
8768 goto handle_enum;
8770 default:
8771 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
8773 *retp = p;
8774 *retbuffer = buffer;
8777 static void
8778 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
8780 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
8781 char *str = type_get_qualified_name (type, NULL);
8782 int slen = strlen (str);
8784 *p++ = 0x55;
8786 * This seems to be optional...
8787 * *p++ = 0x80;
8789 mono_metadata_encode_value (slen, p, &p);
8790 memcpy (p, str, slen);
8791 p += slen;
8792 g_free (str);
8793 } else if (type->type == MONO_TYPE_OBJECT) {
8794 *p++ = 0x51;
8795 } else if (type->type == MONO_TYPE_CLASS) {
8796 /* it should be a type: encode_cattr_value () has the check */
8797 *p++ = 0x50;
8798 } else {
8799 mono_metadata_encode_value (type->type, p, &p);
8800 if (type->type == MONO_TYPE_SZARRAY)
8801 /* See the examples in Partition VI, Annex B */
8802 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
8805 *retp = p;
8808 static void
8809 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
8811 int len;
8812 /* Preallocate a large enough buffer */
8813 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
8814 char *str = type_get_qualified_name (type, NULL);
8815 len = strlen (str);
8816 g_free (str);
8817 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
8818 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
8819 len = strlen (str);
8820 g_free (str);
8821 } else {
8822 len = 0;
8824 len += strlen (name);
8826 if ((p-buffer) + 20 + len >= *buflen) {
8827 char *newbuf;
8828 *buflen *= 2;
8829 *buflen += len;
8830 newbuf = g_realloc (buffer, *buflen);
8831 p = newbuf + (p-buffer);
8832 buffer = newbuf;
8835 encode_field_or_prop_type (type, p, &p);
8837 len = strlen (name);
8838 mono_metadata_encode_value (len, p, &p);
8839 memcpy (p, name, len);
8840 p += len;
8841 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
8842 *retp = p;
8843 *retbuffer = buffer;
8846 #ifndef DISABLE_REFLECTION_EMIT
8849 * mono_reflection_get_custom_attrs_blob:
8850 * @ctor: custom attribute constructor
8851 * @ctorArgs: arguments o the constructor
8852 * @properties:
8853 * @propValues:
8854 * @fields:
8855 * @fieldValues:
8857 * Creates the blob of data that needs to be saved in the metadata and that represents
8858 * the custom attributed described by @ctor, @ctorArgs etc.
8859 * Returns: a Byte array representing the blob of data.
8861 MonoArray*
8862 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
8864 MonoArray *result;
8865 MonoMethodSignature *sig;
8866 MonoObject *arg;
8867 char *buffer, *p;
8868 guint32 buflen, i;
8870 MONO_ARCH_SAVE_REGS;
8872 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
8873 /* sig is freed later so allocate it in the heap */
8874 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
8875 } else {
8876 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
8879 g_assert (mono_array_length (ctorArgs) == sig->param_count);
8880 buflen = 256;
8881 p = buffer = g_malloc (buflen);
8882 /* write the prolog */
8883 *p++ = 1;
8884 *p++ = 0;
8885 for (i = 0; i < sig->param_count; ++i) {
8886 arg = mono_array_get (ctorArgs, MonoObject*, i);
8887 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
8889 i = 0;
8890 if (properties)
8891 i += mono_array_length (properties);
8892 if (fields)
8893 i += mono_array_length (fields);
8894 *p++ = i & 0xff;
8895 *p++ = (i >> 8) & 0xff;
8896 if (properties) {
8897 MonoObject *prop;
8898 for (i = 0; i < mono_array_length (properties); ++i) {
8899 MonoType *ptype;
8900 char *pname;
8902 prop = mono_array_get (properties, gpointer, i);
8903 get_prop_name_and_type (prop, &pname, &ptype);
8904 *p++ = 0x54; /* PROPERTY signature */
8905 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
8906 g_free (pname);
8910 if (fields) {
8911 MonoObject *field;
8912 for (i = 0; i < mono_array_length (fields); ++i) {
8913 MonoType *ftype;
8914 char *fname;
8916 field = mono_array_get (fields, gpointer, i);
8917 get_field_name_and_type (field, &fname, &ftype);
8918 *p++ = 0x53; /* FIELD signature */
8919 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
8920 g_free (fname);
8924 g_assert (p - buffer <= buflen);
8925 buflen = p - buffer;
8926 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8927 p = mono_array_addr (result, char, 0);
8928 memcpy (p, buffer, buflen);
8929 g_free (buffer);
8930 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
8931 g_free (sig);
8932 return result;
8936 * mono_reflection_setup_internal_class:
8937 * @tb: a TypeBuilder object
8939 * Creates a MonoClass that represents the TypeBuilder.
8940 * This is a trick that lets us simplify a lot of reflection code
8941 * (and will allow us to support Build and Run assemblies easier).
8943 void
8944 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
8946 MonoClass *klass, *parent;
8948 MONO_ARCH_SAVE_REGS;
8950 CHECK_MONOTYPE (tb->parent);
8952 mono_loader_lock ();
8954 if (tb->parent) {
8955 /* check so we can compile corlib correctly */
8956 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
8957 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
8958 parent = monotype_cast (tb->parent)->type->data.klass;
8959 } else {
8960 parent = my_mono_class_from_mono_type (monotype_cast (tb->parent)->type);
8962 } else {
8963 parent = NULL;
8966 /* the type has already being created: it means we just have to change the parent */
8967 if (tb->type.type) {
8968 klass = mono_class_from_mono_type (tb->type.type);
8969 klass->parent = NULL;
8970 /* fool mono_class_setup_parent */
8971 klass->supertypes = NULL;
8972 mono_class_setup_parent (klass, parent);
8973 mono_class_setup_mono_type (klass);
8974 mono_loader_unlock ();
8975 return;
8978 klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
8980 klass->image = &tb->module->dynamic_image->image;
8982 klass->inited = 1; /* we lie to the runtime */
8983 klass->name = mono_string_to_utf8_image (klass->image, tb->name);
8984 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace);
8985 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
8986 klass->flags = tb->attrs;
8988 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
8990 klass->element_class = klass;
8992 MOVING_GC_REGISTER (&klass->reflection_info);
8993 klass->reflection_info = tb;
8995 /* Put into cache so mono_class_get () will find it */
8996 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
8998 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
8999 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
9001 if (parent != NULL) {
9002 mono_class_setup_parent (klass, parent);
9003 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
9004 const char *old_n = klass->name;
9005 /* trick to get relative numbering right when compiling corlib */
9006 klass->name = "BuildingObject";
9007 mono_class_setup_parent (klass, mono_defaults.object_class);
9008 klass->name = old_n;
9011 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
9012 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
9013 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
9014 klass->instance_size = sizeof (MonoObject);
9015 klass->size_inited = 1;
9016 mono_class_setup_vtable_general (klass, NULL, 0);
9019 mono_class_setup_mono_type (klass);
9021 mono_class_setup_supertypes (klass);
9024 * FIXME: handle interfaces.
9027 tb->type.type = &klass->byval_arg;
9029 if (tb->nesting_type) {
9030 g_assert (tb->nesting_type->type);
9031 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
9034 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
9036 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
9038 mono_loader_unlock ();
9042 * mono_reflection_setup_generic_class:
9043 * @tb: a TypeBuilder object
9045 * Setup the generic class before adding the first generic parameter.
9047 void
9048 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
9053 * mono_reflection_create_generic_class:
9054 * @tb: a TypeBuilder object
9056 * Creates the generic class after all generic parameters have been added.
9058 void
9059 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
9061 MonoClass *klass;
9062 int count, i;
9064 MONO_ARCH_SAVE_REGS;
9066 klass = my_mono_class_from_mono_type (tb->type.type);
9068 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
9070 if (klass->generic_container || (count == 0))
9071 return;
9073 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
9075 klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
9077 klass->generic_container->owner.klass = klass;
9078 klass->generic_container->type_argc = count;
9079 klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParam) * count);
9081 klass->is_generic = 1;
9083 for (i = 0; i < count; i++) {
9084 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
9085 klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
9086 /*Make sure we are a diferent type instance */
9087 klass->generic_container->type_params [i].owner = klass->generic_container;
9088 klass->generic_container->type_params [i].pklass = NULL;
9090 g_assert (klass->generic_container->type_params [i].owner);
9093 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
9097 * mono_reflection_create_internal_class:
9098 * @tb: a TypeBuilder object
9100 * Actually create the MonoClass that is associated with the TypeBuilder.
9102 void
9103 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
9105 MonoClass *klass;
9107 MONO_ARCH_SAVE_REGS;
9109 klass = my_mono_class_from_mono_type (tb->type.type);
9111 mono_loader_lock ();
9112 if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
9113 MonoReflectionFieldBuilder *fb;
9114 MonoClass *ec;
9115 MonoType *enum_basetype;
9117 g_assert (tb->fields != NULL);
9118 g_assert (mono_array_length (tb->fields) >= 1);
9120 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
9122 if (!mono_type_is_valid_enum_basetype (monotype_cast (fb->type)->type)) {
9123 mono_loader_unlock ();
9124 return;
9127 enum_basetype = monotype_cast (fb->type)->type;
9128 klass->element_class = my_mono_class_from_mono_type (enum_basetype);
9129 if (!klass->element_class)
9130 klass->element_class = mono_class_from_mono_type (enum_basetype);
9133 * get the element_class from the current corlib.
9135 ec = default_class_from_mono_type (enum_basetype);
9136 klass->instance_size = ec->instance_size;
9137 klass->size_inited = 1;
9139 * this is almost safe to do with enums and it's needed to be able
9140 * to create objects of the enum type (for use in SetConstant).
9142 /* FIXME: Does this mean enums can't have method overrides ? */
9143 mono_class_setup_vtable_general (klass, NULL, 0);
9145 mono_loader_unlock ();
9148 #endif /* DISABLE_REFLECTION_EMIT */
9150 static MonoMarshalSpec*
9151 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
9152 MonoReflectionMarshal *minfo)
9154 MonoMarshalSpec *res;
9156 res = image_g_new0 (image, MonoMarshalSpec, 1);
9157 res->native = minfo->type;
9159 switch (minfo->type) {
9160 case MONO_NATIVE_LPARRAY:
9161 res->data.array_data.elem_type = minfo->eltype;
9162 if (minfo->has_size) {
9163 res->data.array_data.param_num = minfo->param_num;
9164 res->data.array_data.num_elem = minfo->count;
9165 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
9167 else {
9168 res->data.array_data.param_num = -1;
9169 res->data.array_data.num_elem = -1;
9170 res->data.array_data.elem_mult = -1;
9172 break;
9174 case MONO_NATIVE_BYVALTSTR:
9175 case MONO_NATIVE_BYVALARRAY:
9176 res->data.array_data.num_elem = minfo->count;
9177 break;
9179 case MONO_NATIVE_CUSTOM:
9180 if (minfo->marshaltyperef)
9181 res->data.custom_data.custom_name =
9182 type_get_fully_qualified_name (monotype_cast (minfo->marshaltyperef)->type);
9183 if (minfo->mcookie)
9184 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
9185 break;
9187 default:
9188 break;
9191 return res;
9194 MonoReflectionMarshal*
9195 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
9196 MonoMarshalSpec *spec)
9198 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
9199 MonoReflectionMarshal *minfo;
9200 MonoType *mtype;
9202 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
9203 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
9204 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
9205 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
9208 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
9209 minfo->type = spec->native;
9211 switch (minfo->type) {
9212 case MONO_NATIVE_LPARRAY:
9213 minfo->eltype = spec->data.array_data.elem_type;
9214 minfo->count = spec->data.array_data.num_elem;
9215 minfo->param_num = spec->data.array_data.param_num;
9216 break;
9218 case MONO_NATIVE_BYVALTSTR:
9219 case MONO_NATIVE_BYVALARRAY:
9220 minfo->count = spec->data.array_data.num_elem;
9221 break;
9223 case MONO_NATIVE_CUSTOM:
9224 if (spec->data.custom_data.custom_name) {
9225 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
9226 if (mtype)
9227 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
9229 MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
9231 if (spec->data.custom_data.cookie)
9232 MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
9233 break;
9235 default:
9236 break;
9239 return minfo;
9242 static MonoMethod*
9243 reflection_methodbuilder_to_mono_method (MonoClass *klass,
9244 ReflectionMethodBuilder *rmb,
9245 MonoMethodSignature *sig)
9247 MonoMethod *m;
9248 MonoMethodNormal *pm;
9249 MonoMarshalSpec **specs;
9250 MonoReflectionMethodAux *method_aux;
9251 MonoImage *image;
9252 gboolean dynamic;
9253 int i;
9256 * Methods created using a MethodBuilder should have their memory allocated
9257 * inside the image mempool, while dynamic methods should have their memory
9258 * malloc'd.
9260 dynamic = rmb->refs != NULL;
9261 image = dynamic ? NULL : klass->image;
9263 if (!dynamic)
9264 g_assert (!klass->generic_class);
9266 mono_loader_lock ();
9268 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
9269 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
9270 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
9271 else if (rmb->refs)
9272 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
9273 else
9274 m = (MonoMethod *)image_g_new0 (image, MonoMethodNormal, 1);
9276 pm = (MonoMethodNormal*)m;
9278 m->dynamic = dynamic;
9279 m->slot = -1;
9280 m->flags = rmb->attrs;
9281 m->iflags = rmb->iattrs;
9282 m->name = mono_string_to_utf8_image (image, rmb->name);
9283 m->klass = klass;
9284 m->signature = sig;
9285 m->skip_visibility = rmb->skip_visibility;
9286 if (rmb->table_idx)
9287 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
9289 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
9290 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
9291 m->string_ctor = 1;
9293 m->signature->pinvoke = 1;
9294 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
9295 m->signature->pinvoke = 1;
9297 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
9299 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry) : image_strdup (image, m->name);
9300 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll);
9302 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
9304 if (klass->image->dynamic)
9305 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
9307 mono_loader_unlock ();
9309 return m;
9310 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
9311 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
9312 MonoMethodHeader *header;
9313 guint32 code_size;
9314 gint32 max_stack, i;
9315 gint32 num_locals = 0;
9316 gint32 num_clauses = 0;
9317 guint8 *code;
9319 if (rmb->ilgen) {
9320 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
9321 code_size = rmb->ilgen->code_len;
9322 max_stack = rmb->ilgen->max_stack;
9323 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
9324 if (rmb->ilgen->ex_handlers)
9325 num_clauses = method_count_clauses (rmb->ilgen);
9326 } else {
9327 if (rmb->code) {
9328 code = mono_array_addr (rmb->code, guint8, 0);
9329 code_size = mono_array_length (rmb->code);
9330 /* we probably need to run a verifier on the code... */
9331 max_stack = 8;
9333 else {
9334 code = NULL;
9335 code_size = 0;
9336 max_stack = 8;
9340 header = image_g_malloc0 (image, sizeof (MonoMethodHeader) +
9341 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
9342 header->code_size = code_size;
9343 header->code = image_g_malloc (image, code_size);
9344 memcpy ((char*)header->code, code, code_size);
9345 header->max_stack = max_stack;
9346 header->init_locals = rmb->init_locals;
9347 header->num_locals = num_locals;
9349 for (i = 0; i < num_locals; ++i) {
9350 MonoReflectionLocalBuilder *lb =
9351 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
9353 header->locals [i] = image_g_new0 (image, MonoType, 1);
9354 memcpy (header->locals [i], monotype_cast (lb->type)->type, sizeof (MonoType));
9357 header->num_clauses = num_clauses;
9358 if (num_clauses) {
9359 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
9360 rmb->ilgen, num_clauses);
9363 pm->header = header;
9366 if (rmb->generic_params) {
9367 int count = mono_array_length (rmb->generic_params);
9368 MonoGenericContainer *container;
9370 container = rmb->generic_container;
9371 if (container) {
9372 m->is_generic = TRUE;
9373 mono_method_set_generic_container (m, container);
9375 container->type_argc = count;
9376 container->type_params = image_g_new0 (image, MonoGenericParam, count);
9377 container->owner.method = m;
9379 for (i = 0; i < count; i++) {
9380 MonoReflectionGenericParam *gp =
9381 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
9383 container->type_params [i] = *gp->type.type->data.generic_param;
9386 if (klass->generic_container) {
9387 container->parent = klass->generic_container;
9388 container->context.class_inst = klass->generic_container->context.class_inst;
9390 container->context.method_inst = mono_get_shared_generic_inst (container);
9393 if (rmb->refs) {
9394 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
9395 int i;
9396 void **data;
9398 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
9400 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
9401 data [0] = GUINT_TO_POINTER (rmb->nrefs);
9402 for (i = 0; i < rmb->nrefs; ++i)
9403 data [i + 1] = rmb->refs [i];
9406 method_aux = NULL;
9408 /* Parameter info */
9409 if (rmb->pinfo) {
9410 if (!method_aux)
9411 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
9412 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
9413 for (i = 0; i <= m->signature->param_count; ++i) {
9414 MonoReflectionParamBuilder *pb;
9415 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
9416 if ((i > 0) && (pb->attrs)) {
9417 /* Make a copy since it might point to a shared type structure */
9418 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
9419 m->signature->params [i - 1]->attrs = pb->attrs;
9422 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
9423 MonoDynamicImage *assembly;
9424 guint32 idx, def_type, len;
9425 char *p;
9426 const char *p2;
9428 if (!method_aux->param_defaults) {
9429 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
9430 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
9432 assembly = (MonoDynamicImage*)klass->image;
9433 idx = encode_constant (assembly, pb->def_value, &def_type);
9434 /* Copy the data from the blob since it might get realloc-ed */
9435 p = assembly->blob.data + idx;
9436 len = mono_metadata_decode_blob_size (p, &p2);
9437 len += p2 - p;
9438 method_aux->param_defaults [i] = image_g_malloc (image, len);
9439 method_aux->param_default_types [i] = def_type;
9440 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
9443 if (pb->name)
9444 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name);
9445 if (pb->cattrs) {
9446 if (!method_aux->param_cattr)
9447 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
9448 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
9454 /* Parameter marshalling */
9455 specs = NULL;
9456 if (rmb->pinfo)
9457 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
9458 MonoReflectionParamBuilder *pb;
9459 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
9460 if (pb->marshal_info) {
9461 if (specs == NULL)
9462 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
9463 specs [pb->position] =
9464 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
9468 if (specs != NULL) {
9469 if (!method_aux)
9470 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
9471 method_aux->param_marshall = specs;
9474 if (klass->image->dynamic && method_aux)
9475 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
9477 mono_loader_unlock ();
9479 return m;
9482 static MonoMethod*
9483 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
9485 ReflectionMethodBuilder rmb;
9486 MonoMethodSignature *sig;
9488 mono_loader_lock ();
9489 sig = ctor_builder_to_signature (klass->image, mb);
9490 mono_loader_unlock ();
9492 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
9494 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
9495 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
9497 /* If we are in a generic class, we might be called multiple times from inflate_method */
9498 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
9499 /* ilgen is no longer needed */
9500 mb->ilgen = NULL;
9503 return mb->mhandle;
9506 static MonoMethod*
9507 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
9509 ReflectionMethodBuilder rmb;
9510 MonoMethodSignature *sig;
9512 mono_loader_lock ();
9513 sig = method_builder_to_signature (klass->image, mb);
9514 mono_loader_unlock ();
9516 reflection_methodbuilder_from_method_builder (&rmb, mb);
9518 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
9519 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
9521 /* If we are in a generic class, we might be called multiple times from inflate_method */
9522 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
9523 /* ilgen is no longer needed */
9524 mb->ilgen = NULL;
9526 return mb->mhandle;
9529 static MonoClassField*
9530 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
9532 MonoClassField *field;
9533 MonoType *custom;
9535 field = g_new0 (MonoClassField, 1);
9537 field->name = mono_string_to_utf8 (fb->name);
9538 if (fb->attrs || fb->modreq || fb->modopt) {
9539 field->type = mono_metadata_type_dup (NULL, monotype_cast (fb->type)->type);
9540 field->type->attrs = fb->attrs;
9542 g_assert (klass->image->dynamic);
9543 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
9544 g_free (field->type);
9545 field->type = custom;
9546 } else {
9547 field->type = monotype_cast (fb->type)->type;
9549 if (fb->offset != -1)
9550 field->offset = fb->offset;
9551 field->parent = klass;
9552 mono_save_custom_attrs (klass->image, field, fb->cattrs);
9554 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
9556 return field;
9559 MonoType*
9560 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
9562 MonoClass *klass;
9563 MonoReflectionTypeBuilder *tb = NULL;
9564 gboolean is_dynamic = FALSE;
9565 MonoDomain *domain;
9566 MonoClass *geninst;
9568 mono_loader_lock ();
9570 domain = mono_object_domain (type);
9572 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
9573 tb = (MonoReflectionTypeBuilder *) type;
9575 is_dynamic = TRUE;
9576 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
9577 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
9579 tb = rgi->generic_type;
9580 is_dynamic = TRUE;
9583 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
9584 if (tb && tb->generic_container)
9585 mono_reflection_create_generic_class (tb);
9587 klass = mono_class_from_mono_type (type->type);
9588 if (!klass->generic_container) {
9589 mono_loader_unlock ();
9590 return NULL;
9593 if (klass->wastypebuilder) {
9594 tb = (MonoReflectionTypeBuilder *) klass->reflection_info;
9596 is_dynamic = TRUE;
9599 mono_loader_unlock ();
9601 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
9603 return &geninst->byval_arg;
9606 MonoClass*
9607 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
9609 MonoGenericClass *gclass;
9610 MonoGenericInst *inst;
9612 g_assert (klass->generic_container);
9614 inst = mono_metadata_get_generic_inst (type_argc, types);
9615 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
9617 return mono_generic_class_get_class (gclass);
9620 MonoReflectionMethod*
9621 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
9623 MonoClass *klass;
9624 MonoMethod *method, *inflated;
9625 MonoMethodInflated *imethod;
9626 MonoReflectionMethodBuilder *mb = NULL;
9627 MonoGenericContext tmp_context;
9628 MonoGenericInst *ginst;
9629 MonoType **type_argv;
9630 int count, i;
9632 MONO_ARCH_SAVE_REGS;
9634 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
9635 #ifndef DISABLE_REFLECTION_EMIT
9636 MonoReflectionTypeBuilder *tb;
9637 MonoClass *klass;
9639 mb = (MonoReflectionMethodBuilder *) rmethod;
9640 tb = (MonoReflectionTypeBuilder *) mb->type;
9641 klass = mono_class_from_mono_type (tb->type.type);
9643 method = methodbuilder_to_mono_method (klass, mb);
9644 #else
9645 g_assert_not_reached ();
9646 method = NULL;
9647 #endif
9648 } else {
9649 method = rmethod->method;
9652 klass = method->klass;
9654 if (method->is_inflated)
9655 method = ((MonoMethodInflated *) method)->declaring;
9657 count = mono_method_signature (method)->generic_param_count;
9658 if (count != mono_array_length (types))
9659 return NULL;
9661 type_argv = g_new0 (MonoType *, count);
9662 for (i = 0; i < count; i++) {
9663 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
9664 type_argv [i] = garg->type;
9666 ginst = mono_metadata_get_generic_inst (count, type_argv);
9667 g_free (type_argv);
9669 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
9670 tmp_context.method_inst = ginst;
9672 inflated = mono_class_inflate_generic_method (method, &tmp_context);
9673 imethod = (MonoMethodInflated *) inflated;
9675 if (method->klass->image->dynamic) {
9676 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
9678 * This table maps metadata structures representing inflated methods/fields
9679 * to the reflection objects representing their generic definitions.
9681 mono_loader_lock ();
9682 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
9683 mono_loader_unlock ();
9686 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
9689 #ifndef DISABLE_REFLECTION_EMIT
9691 static MonoMethod *
9692 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
9694 MonoMethodInflated *imethod;
9695 MonoGenericContext *context;
9696 int i;
9699 * With generic code sharing the klass might not be inflated.
9700 * This can happen because classes inflated with their own
9701 * type arguments are "normalized" to the uninflated class.
9703 if (!klass->generic_class)
9704 return method;
9706 context = mono_class_get_context (klass);
9708 if (klass->method.count) {
9709 /* Find the already created inflated method */
9710 for (i = 0; i < klass->method.count; ++i) {
9711 g_assert (klass->methods [i]->is_inflated);
9712 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
9713 break;
9715 g_assert (i < klass->method.count);
9716 imethod = (MonoMethodInflated*)klass->methods [i];
9717 } else {
9718 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
9721 if (method->is_generic && method->klass->image->dynamic) {
9722 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
9724 mono_loader_lock ();
9725 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
9726 mono_loader_unlock ();
9728 return (MonoMethod *) imethod;
9731 static MonoMethod *
9732 inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
9734 MonoMethod *method;
9735 MonoClass *gklass;
9737 gklass = mono_class_from_mono_type (type->generic_type->type.type);
9739 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
9740 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
9741 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
9742 else
9743 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
9744 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
9745 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
9746 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
9747 method = ((MonoReflectionMethod *) obj)->method;
9748 else {
9749 method = NULL; /* prevent compiler warning */
9750 g_assert_not_reached ();
9753 return inflate_mono_method (mono_class_from_mono_type (type->type.type), method, obj);
9756 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
9757 void
9758 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
9759 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
9760 MonoArray *events)
9762 MonoGenericClass *gclass;
9763 MonoDynamicGenericClass *dgclass;
9764 MonoClass *klass, *gklass;
9765 int i;
9767 MONO_ARCH_SAVE_REGS;
9769 klass = mono_class_from_mono_type (type->type.type);
9770 g_assert (type->type.type->type == MONO_TYPE_GENERICINST);
9771 gclass = type->type.type->data.generic_class;
9773 g_assert (gclass->is_dynamic);
9774 dgclass = (MonoDynamicGenericClass *) gclass;
9776 if (dgclass->initialized)
9777 return;
9779 gklass = gclass->container_class;
9780 mono_class_init (gklass);
9782 dgclass->count_methods = methods ? mono_array_length (methods) : 0;
9783 dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
9784 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
9785 dgclass->count_properties = properties ? mono_array_length (properties) : 0;
9786 dgclass->count_events = events ? mono_array_length (events) : 0;
9788 dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
9789 dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
9790 dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
9791 dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
9792 dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
9793 dgclass->field_objects = g_new0 (MonoObject*, dgclass->count_fields);
9794 dgclass->field_generic_types = g_new0 (MonoType*, dgclass->count_fields);
9796 for (i = 0; i < dgclass->count_methods; i++) {
9797 MonoObject *obj = mono_array_get (methods, gpointer, i);
9799 dgclass->methods [i] = inflate_method (type, obj);
9802 for (i = 0; i < dgclass->count_ctors; i++) {
9803 MonoObject *obj = mono_array_get (ctors, gpointer, i);
9805 dgclass->ctors [i] = inflate_method (type, obj);
9808 for (i = 0; i < dgclass->count_fields; i++) {
9809 MonoObject *obj = mono_array_get (fields, gpointer, i);
9810 MonoClassField *field, *inflated_field = NULL;
9812 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
9813 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
9814 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
9815 field = ((MonoReflectionField *) obj)->field;
9816 else {
9817 field = NULL; /* prevent compiler warning */
9818 g_assert_not_reached ();
9821 dgclass->fields [i] = *field;
9822 dgclass->fields [i].parent = klass;
9823 dgclass->fields [i].type = mono_class_inflate_generic_type (
9824 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
9825 dgclass->field_generic_types [i] = field->type;
9826 MOVING_GC_REGISTER (&dgclass->field_objects [i]);
9827 dgclass->field_objects [i] = obj;
9829 if (inflated_field) {
9830 g_free (inflated_field);
9831 } else {
9832 dgclass->fields [i].name = g_strdup (dgclass->fields [i].name);
9836 for (i = 0; i < dgclass->count_properties; i++) {
9837 MonoObject *obj = mono_array_get (properties, gpointer, i);
9838 MonoProperty *property = &dgclass->properties [i];
9840 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
9841 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
9843 property->parent = klass;
9844 property->attrs = pb->attrs;
9845 property->name = mono_string_to_utf8 (pb->name);
9846 if (pb->get_method)
9847 property->get = inflate_method (type, (MonoObject *) pb->get_method);
9848 if (pb->set_method)
9849 property->set = inflate_method (type, (MonoObject *) pb->set_method);
9850 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
9851 *property = *((MonoReflectionProperty *) obj)->property;
9852 property->name = g_strdup (property->name);
9854 if (property->get)
9855 property->get = inflate_mono_method (klass, property->get, NULL);
9856 if (property->set)
9857 property->set = inflate_mono_method (klass, property->set, NULL);
9858 } else
9859 g_assert_not_reached ();
9862 for (i = 0; i < dgclass->count_events; i++) {
9863 MonoObject *obj = mono_array_get (events, gpointer, i);
9864 MonoEvent *event = &dgclass->events [i];
9866 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
9867 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
9869 event->parent = klass;
9870 event->attrs = eb->attrs;
9871 event->name = mono_string_to_utf8 (eb->name);
9872 if (eb->add_method)
9873 event->add = inflate_method (type, (MonoObject *) eb->add_method);
9874 if (eb->remove_method)
9875 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
9876 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
9877 *event = *((MonoReflectionMonoEvent *) obj)->event;
9878 event->name = g_strdup (event->name);
9880 if (event->add)
9881 event->add = inflate_mono_method (klass, event->add, NULL);
9882 if (event->remove)
9883 event->remove = inflate_mono_method (klass, event->remove, NULL);
9884 } else
9885 g_assert_not_reached ();
9888 dgclass->initialized = TRUE;
9891 static void
9892 ensure_generic_class_runtime_vtable (MonoClass *klass)
9894 MonoClass *gklass = klass->generic_class->container_class;
9895 int i;
9897 if (klass->wastypebuilder)
9898 return;
9900 ensure_runtime_vtable (gklass);
9902 klass->method.count = gklass->method.count;
9903 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
9905 for (i = 0; i < klass->method.count; i++) {
9906 klass->methods [i] = mono_class_inflate_generic_method_full (
9907 gklass->methods [i], klass, mono_class_get_context (klass));
9910 klass->interface_count = gklass->interface_count;
9911 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
9912 for (i = 0; i < klass->interface_count; ++i) {
9913 MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
9914 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
9915 mono_metadata_free_type (iface_type);
9917 ensure_runtime_vtable (klass->interfaces [i]);
9919 klass->interfaces_inited = 1;
9921 /*We can only finish with this klass once it's parent has as well*/
9922 if (gklass->wastypebuilder)
9923 klass->wastypebuilder = TRUE;
9924 return;
9927 static void
9928 ensure_runtime_vtable (MonoClass *klass)
9930 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9931 int i, num, j;
9933 if (!klass->image->dynamic || (!tb && !klass->generic_class) || klass->wastypebuilder)
9934 return;
9935 if (klass->parent)
9936 ensure_runtime_vtable (klass->parent);
9938 if (tb) {
9939 num = tb->ctors? mono_array_length (tb->ctors): 0;
9940 num += tb->num_methods;
9941 klass->method.count = num;
9942 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
9943 num = tb->ctors? mono_array_length (tb->ctors): 0;
9944 for (i = 0; i < num; ++i)
9945 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
9946 num = tb->num_methods;
9947 j = i;
9948 for (i = 0; i < num; ++i)
9949 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
9951 if (tb->interfaces) {
9952 klass->interface_count = mono_array_length (tb->interfaces);
9953 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
9954 for (i = 0; i < klass->interface_count; ++i) {
9955 MonoReflectionType *iface = mono_type_array_get (tb->interfaces, i);
9956 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
9957 ensure_runtime_vtable (klass->interfaces [i]);
9959 klass->interfaces_inited = 1;
9961 } else if (klass->generic_class){
9962 ensure_generic_class_runtime_vtable (klass);
9965 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
9966 for (i = 0; i < klass->method.count; ++i)
9967 klass->methods [i]->slot = i;
9969 mono_class_setup_interface_offsets (klass);
9970 mono_class_setup_interface_id (klass);
9974 * The generic vtable is needed even if image->run is not set since some
9975 * runtime code like ves_icall_Type_GetMethodsByName depends on
9976 * method->slot being defined.
9980 * tb->methods could not be freed since it is used for determining
9981 * overrides during dynamic vtable construction.
9985 void
9986 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
9988 MonoReflectionTypeBuilder *tb;
9989 int i, onum;
9991 *overrides = NULL;
9992 *num_overrides = 0;
9994 g_assert (klass->image->dynamic);
9996 if (!klass->reflection_info)
9997 return;
9999 g_assert (strcmp (((MonoObject*)klass->reflection_info)->vtable->klass->name, "TypeBuilder") == 0);
10001 tb = (MonoReflectionTypeBuilder*)klass->reflection_info;
10003 onum = 0;
10004 if (tb->methods) {
10005 for (i = 0; i < tb->num_methods; ++i) {
10006 MonoReflectionMethodBuilder *mb =
10007 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10008 if (mb->override_method)
10009 onum ++;
10013 if (onum) {
10014 *overrides = g_new0 (MonoMethod*, onum * 2);
10016 onum = 0;
10017 for (i = 0; i < tb->num_methods; ++i) {
10018 MonoReflectionMethodBuilder *mb =
10019 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10020 if (mb->override_method) {
10021 (*overrides) [onum * 2] =
10022 mb->override_method->method;
10023 (*overrides) [onum * 2 + 1] =
10024 mb->mhandle;
10026 /* FIXME: What if 'override_method' is a MethodBuilder ? */
10027 g_assert (mb->override_method->method);
10028 g_assert (mb->mhandle);
10030 onum ++;
10035 *num_overrides = onum;
10038 static void
10039 typebuilder_setup_fields (MonoClass *klass)
10041 MonoReflectionTypeBuilder *tb = klass->reflection_info;
10042 MonoReflectionFieldBuilder *fb;
10043 MonoClassField *field;
10044 MonoImage *image = klass->image;
10045 const char *p, *p2;
10046 int i;
10047 guint32 len, idx, real_size = 0;
10049 klass->field.count = tb->num_fields;
10050 klass->field.first = 0;
10052 if (tb->class_size) {
10053 g_assert ((tb->packing_size & 0xfffffff0) == 0);
10054 klass->packing_size = tb->packing_size;
10055 real_size = klass->instance_size + tb->class_size;
10058 if (!klass->field.count) {
10059 klass->instance_size = MAX (klass->instance_size, real_size);
10060 return;
10063 klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
10064 mono_class_alloc_ext (klass);
10065 klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
10067 for (i = 0; i < klass->field.count; ++i) {
10068 fb = mono_array_get (tb->fields, gpointer, i);
10069 field = &klass->fields [i];
10070 field->name = mono_string_to_utf8_image (image, fb->name);
10071 if (fb->attrs) {
10072 field->type = mono_metadata_type_dup (klass->image, monotype_cast (fb->type)->type);
10073 field->type->attrs = fb->attrs;
10074 } else {
10075 field->type = monotype_cast (fb->type)->type;
10077 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
10078 klass->ext->field_def_values [i].data = mono_array_addr (fb->rva_data, char, 0);
10079 if (fb->offset != -1)
10080 field->offset = fb->offset;
10081 field->parent = klass;
10082 fb->handle = field;
10083 mono_save_custom_attrs (klass->image, field, fb->cattrs);
10085 if (fb->def_value) {
10086 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
10087 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
10088 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
10089 /* Copy the data from the blob since it might get realloc-ed */
10090 p = assembly->blob.data + idx;
10091 len = mono_metadata_decode_blob_size (p, &p2);
10092 len += p2 - p;
10093 klass->ext->field_def_values [i].data = mono_image_alloc (image, len);
10094 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
10098 klass->instance_size = MAX (klass->instance_size, real_size);
10099 mono_class_layout_fields (klass);
10102 static void
10103 typebuilder_setup_properties (MonoClass *klass)
10105 MonoReflectionTypeBuilder *tb = klass->reflection_info;
10106 MonoReflectionPropertyBuilder *pb;
10107 MonoImage *image = klass->image;
10108 MonoProperty *properties;
10109 int i;
10111 if (!klass->ext)
10112 klass->ext = image_g_new0 (image, MonoClassExt, 1);
10114 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
10115 klass->ext->property.first = 0;
10117 properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
10118 klass->ext->properties = properties;
10119 for (i = 0; i < klass->ext->property.count; ++i) {
10120 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
10121 properties [i].parent = klass;
10122 properties [i].attrs = pb->attrs;
10123 properties [i].name = mono_string_to_utf8_image (image, pb->name);
10124 if (pb->get_method)
10125 properties [i].get = pb->get_method->mhandle;
10126 if (pb->set_method)
10127 properties [i].set = pb->set_method->mhandle;
10129 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
10133 MonoReflectionEvent *
10134 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
10136 MonoEvent *event = g_new0 (MonoEvent, 1);
10137 MonoClass *klass;
10138 int j;
10140 klass = my_mono_class_from_mono_type (tb->type.type);
10142 event->parent = klass;
10143 event->attrs = eb->attrs;
10144 event->name = mono_string_to_utf8 (eb->name);
10145 if (eb->add_method)
10146 event->add = eb->add_method->mhandle;
10147 if (eb->remove_method)
10148 event->remove = eb->remove_method->mhandle;
10149 if (eb->raise_method)
10150 event->raise = eb->raise_method->mhandle;
10152 if (eb->other_methods) {
10153 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
10154 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
10155 MonoReflectionMethodBuilder *mb =
10156 mono_array_get (eb->other_methods,
10157 MonoReflectionMethodBuilder*, j);
10158 event->other [j] = mb->mhandle;
10162 return mono_event_get_object (mono_object_domain (tb), klass, event);
10165 static void
10166 typebuilder_setup_events (MonoClass *klass)
10168 MonoReflectionTypeBuilder *tb = klass->reflection_info;
10169 MonoReflectionEventBuilder *eb;
10170 MonoImage *image = klass->image;
10171 MonoEvent *events;
10172 int i, j;
10174 if (!klass->ext)
10175 klass->ext = image_g_new0 (image, MonoClassExt, 1);
10177 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
10178 klass->ext->event.first = 0;
10180 events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
10181 klass->ext->events = events;
10182 for (i = 0; i < klass->ext->event.count; ++i) {
10183 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
10184 events [i].parent = klass;
10185 events [i].attrs = eb->attrs;
10186 events [i].name = mono_string_to_utf8_image (image, eb->name);
10187 if (eb->add_method)
10188 events [i].add = eb->add_method->mhandle;
10189 if (eb->remove_method)
10190 events [i].remove = eb->remove_method->mhandle;
10191 if (eb->raise_method)
10192 events [i].raise = eb->raise_method->mhandle;
10194 if (eb->other_methods) {
10195 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
10196 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
10197 MonoReflectionMethodBuilder *mb =
10198 mono_array_get (eb->other_methods,
10199 MonoReflectionMethodBuilder*, j);
10200 events [i].other [j] = mb->mhandle;
10203 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
10207 static gboolean
10208 remove_instantiations_of (gpointer key,
10209 gpointer value,
10210 gpointer user_data)
10212 MonoType *type = (MonoType*)key;
10213 MonoClass *klass = (MonoClass*)user_data;
10215 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass))
10216 return TRUE;
10217 else
10218 return FALSE;
10221 MonoReflectionType*
10222 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
10224 MonoClass *klass;
10225 MonoDomain* domain;
10226 MonoReflectionType* res;
10227 int i, j;
10229 MONO_ARCH_SAVE_REGS;
10231 domain = mono_object_domain (tb);
10232 klass = my_mono_class_from_mono_type (tb->type.type);
10235 * Check for user defined Type subclasses.
10237 CHECK_MONOTYPE (tb->parent);
10238 check_array_for_usertypes (tb->interfaces);
10239 if (tb->fields) {
10240 for (i = 0; i < mono_array_length (tb->fields); ++i) {
10241 MonoReflectionFieldBuilder *fb = mono_array_get (tb->fields, gpointer, i);
10242 if (fb) {
10243 CHECK_MONOTYPE (fb->type);
10244 check_array_for_usertypes (fb->modreq);
10245 check_array_for_usertypes (fb->modopt);
10246 if (fb->marshal_info && fb->marshal_info->marshaltyperef)
10247 CHECK_MONOTYPE (fb->marshal_info->marshaltyperef);
10251 if (tb->methods) {
10252 for (i = 0; i < mono_array_length (tb->methods); ++i) {
10253 MonoReflectionMethodBuilder *mb = mono_array_get (tb->methods, gpointer, i);
10254 if (mb) {
10255 CHECK_MONOTYPE (mb->rtype);
10256 check_array_for_usertypes (mb->return_modreq);
10257 check_array_for_usertypes (mb->return_modopt);
10258 check_array_for_usertypes (mb->parameters);
10259 if (mb->param_modreq)
10260 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
10261 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
10262 if (mb->param_modopt)
10263 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
10264 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
10268 if (tb->ctors) {
10269 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
10270 MonoReflectionCtorBuilder *mb = mono_array_get (tb->ctors, gpointer, i);
10271 if (mb) {
10272 check_array_for_usertypes (mb->parameters);
10273 if (mb->param_modreq)
10274 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
10275 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
10276 if (mb->param_modopt)
10277 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
10278 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
10283 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
10286 * we need to lock the domain because the lock will be taken inside
10287 * So, we need to keep the locking order correct.
10289 mono_loader_lock ();
10290 mono_domain_lock (domain);
10291 if (klass->wastypebuilder) {
10292 mono_domain_unlock (domain);
10293 mono_loader_unlock ();
10294 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10297 * Fields to set in klass:
10298 * the various flags: delegate/unicode/contextbound etc.
10300 klass->flags = tb->attrs;
10301 klass->has_cctor = 1;
10302 klass->has_finalize = 1;
10304 #if 0
10305 if (!((MonoDynamicImage*)klass->image)->run) {
10306 if (klass->generic_container) {
10307 /* FIXME: The code below can't handle generic classes */
10308 klass->wastypebuilder = TRUE;
10309 mono_loader_unlock ();
10310 mono_domain_unlock (domain);
10311 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10314 #endif
10316 /* enums are done right away */
10317 if (!klass->enumtype)
10318 ensure_runtime_vtable (klass);
10320 if (tb->subtypes) {
10321 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
10322 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
10323 mono_class_alloc_ext (klass);
10324 klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
10328 klass->nested_classes_inited = TRUE;
10330 /* fields and object layout */
10331 if (klass->parent) {
10332 if (!klass->parent->size_inited)
10333 mono_class_init (klass->parent);
10334 klass->instance_size = klass->parent->instance_size;
10335 klass->sizes.class_size = 0;
10336 klass->min_align = klass->parent->min_align;
10337 /* if the type has no fields we won't call the field_setup
10338 * routine which sets up klass->has_references.
10340 klass->has_references |= klass->parent->has_references;
10341 } else {
10342 klass->instance_size = sizeof (MonoObject);
10343 klass->min_align = 1;
10346 /* FIXME: handle packing_size and instance_size */
10347 typebuilder_setup_fields (klass);
10349 typebuilder_setup_properties (klass);
10351 typebuilder_setup_events (klass);
10353 klass->wastypebuilder = TRUE;
10356 * If we are a generic TypeBuilder, there might be instantiations in the type cache
10357 * which have type System.Reflection.MonoGenericClass, but after the type is created,
10358 * we want to return normal System.MonoType objects, so clear these out from the cache.
10360 if (domain->type_hash && klass->generic_container)
10361 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of, klass);
10363 mono_domain_unlock (domain);
10364 mono_loader_unlock ();
10366 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
10367 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10368 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
10371 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10372 g_assert (res != (MonoReflectionType*)tb);
10374 return res;
10377 void
10378 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
10380 MonoGenericParam *param;
10381 MonoImage *image;
10383 MONO_ARCH_SAVE_REGS;
10385 param = g_new0 (MonoGenericParam, 1);
10387 if (gparam->mbuilder) {
10388 if (!gparam->mbuilder->generic_container) {
10389 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
10390 MonoClass *klass = my_mono_class_from_mono_type (tb->type.type);
10391 gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10392 gparam->mbuilder->generic_container->is_method = TRUE;
10394 param->owner = gparam->mbuilder->generic_container;
10395 } else if (gparam->tbuilder) {
10396 if (!gparam->tbuilder->generic_container) {
10397 MonoClass *klass = my_mono_class_from_mono_type (gparam->tbuilder->type.type);
10398 gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10399 gparam->tbuilder->generic_container->owner.klass = klass;
10401 param->owner = gparam->tbuilder->generic_container;
10404 param->name = mono_string_to_utf8 (gparam->name);
10405 param->num = gparam->index;
10407 image = &gparam->tbuilder->module->dynamic_image->image;
10408 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
10410 gparam->type.type = &param->pklass->byval_arg;
10412 MOVING_GC_REGISTER (&param->pklass->reflection_info);
10413 param->pklass->reflection_info = gparam; /* FIXME: GC pin gparam */
10416 MonoArray *
10417 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
10419 MonoDynamicImage *assembly = sig->module->dynamic_image;
10420 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
10421 guint32 buflen, i;
10422 MonoArray *result;
10423 SigBuffer buf;
10425 check_array_for_usertypes (sig->arguments);
10427 sigbuffer_init (&buf, 32);
10429 sigbuffer_add_value (&buf, 0x07);
10430 sigbuffer_add_value (&buf, na);
10431 for (i = 0; i < na; ++i) {
10432 MonoReflectionType *type = mono_type_array_get (sig->arguments, i);
10433 encode_reflection_type (assembly, type, &buf);
10436 buflen = buf.p - buf.buf;
10437 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10438 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
10439 sigbuffer_free (&buf);
10441 return result;
10444 MonoArray *
10445 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
10447 MonoDynamicImage *assembly = sig->module->dynamic_image;
10448 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
10449 guint32 buflen, i;
10450 MonoArray *result;
10451 SigBuffer buf;
10453 check_array_for_usertypes (sig->arguments);
10455 sigbuffer_init (&buf, 32);
10457 sigbuffer_add_value (&buf, 0x06);
10458 for (i = 0; i < na; ++i) {
10459 MonoReflectionType *type = mono_type_array_get (sig->arguments, i);
10460 encode_reflection_type (assembly, type, &buf);
10463 buflen = buf.p - buf.buf;
10464 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10465 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
10466 sigbuffer_free (&buf);
10468 return result;
10471 void
10472 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
10474 ReflectionMethodBuilder rmb;
10475 MonoMethodSignature *sig;
10476 MonoClass *klass;
10477 GSList *l;
10478 int i;
10480 sig = dynamic_method_to_signature (mb);
10482 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
10485 * Resolve references.
10488 * Every second entry in the refs array is reserved for storing handle_class,
10489 * which is needed by the ldtoken implementation in the JIT.
10491 rmb.nrefs = mb->nrefs;
10492 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
10493 for (i = 0; i < mb->nrefs; i += 2) {
10494 MonoClass *handle_class;
10495 gpointer ref;
10496 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
10498 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
10499 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
10501 * The referenced DynamicMethod should already be created by the managed
10502 * code, except in the case of circular references. In that case, we store
10503 * method in the refs array, and fix it up later when the referenced
10504 * DynamicMethod is created.
10506 if (method->mhandle) {
10507 ref = method->mhandle;
10508 } else {
10509 /* FIXME: GC object stored in unmanaged memory */
10510 ref = method;
10512 /* FIXME: GC object stored in unmanaged memory */
10513 method->referenced_by = g_slist_append (method->referenced_by, mb);
10515 handle_class = mono_defaults.methodhandle_class;
10516 } else {
10517 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
10518 if (!ref) {
10519 g_free (rmb.refs);
10520 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
10521 return;
10525 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
10526 rmb.refs [i + 1] = handle_class;
10529 klass = mb->owner ? mono_class_from_mono_type (mb->owner->type) : mono_defaults.object_class;
10531 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10533 /* Fix up refs entries pointing at us */
10534 for (l = mb->referenced_by; l; l = l->next) {
10535 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
10536 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
10537 gpointer *data;
10539 g_assert (method->mhandle);
10541 data = (gpointer*)wrapper->method_data;
10542 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
10543 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
10544 data [i + 1] = mb->mhandle;
10547 g_slist_free (mb->referenced_by);
10549 g_free (rmb.refs);
10551 /* ilgen is no longer needed */
10552 mb->ilgen = NULL;
10555 #endif /* DISABLE_REFLECTION_EMIT */
10557 void
10558 mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod *mb)
10560 g_assert (mb);
10562 if (mb->mhandle)
10563 mono_runtime_free_method (
10564 mono_object_get_domain ((MonoObject*)mb), mb->mhandle);
10569 * mono_reflection_is_valid_dynamic_token:
10571 * Returns TRUE if token is valid.
10574 gboolean
10575 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
10577 return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
10580 #ifndef DISABLE_REFLECTION_EMIT
10583 * mono_reflection_lookup_dynamic_token:
10585 * Finish the Builder object pointed to by TOKEN and return the corresponding
10586 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
10587 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
10588 * mapping table.
10590 * LOCKING: Take the loader lock
10592 gpointer
10593 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
10595 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
10596 MonoObject *obj;
10597 MonoClass *klass;
10599 mono_loader_lock ();
10600 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
10601 mono_loader_unlock ();
10602 if (!obj) {
10603 if (valid_token)
10604 g_assert_not_reached ();
10605 else
10606 return NULL;
10609 if (!handle_class)
10610 handle_class = &klass;
10611 return resolve_object (image, obj, handle_class, context);
10615 * ensure_complete_type:
10617 * Ensure that KLASS is completed if it is a dynamic type, or references
10618 * dynamic types.
10620 static void
10621 ensure_complete_type (MonoClass *klass)
10623 if (klass->image->dynamic && !klass->wastypebuilder) {
10624 MonoReflectionTypeBuilder *tb = klass->reflection_info;
10626 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10628 // Asserting here could break a lot of code
10629 //g_assert (klass->wastypebuilder);
10632 if (klass->generic_class) {
10633 MonoGenericInst *inst = klass->generic_class->context.class_inst;
10634 int i;
10636 for (i = 0; i < inst->type_argc; ++i) {
10637 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
10642 static gpointer
10643 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
10645 gpointer result = NULL;
10647 if (strcmp (obj->vtable->klass->name, "String") == 0) {
10648 result = mono_string_intern ((MonoString*)obj);
10649 *handle_class = NULL;
10650 g_assert (result);
10651 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
10652 MonoReflectionType *tb = (MonoReflectionType*)obj;
10653 if (context) {
10654 MonoType *inflated = mono_class_inflate_generic_type (tb->type, context);
10655 result = mono_class_from_mono_type (inflated);
10656 mono_metadata_free_type (inflated);
10657 } else {
10658 result = mono_class_from_mono_type (tb->type);
10660 *handle_class = mono_defaults.typehandle_class;
10661 g_assert (result);
10662 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
10663 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
10664 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
10665 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
10666 result = ((MonoReflectionMethod*)obj)->method;
10667 if (context)
10668 result = mono_class_inflate_generic_method (result, context);
10669 *handle_class = mono_defaults.methodhandle_class;
10670 g_assert (result);
10671 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
10672 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
10673 result = mb->mhandle;
10674 if (!result) {
10675 /* Type is not yet created */
10676 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
10678 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10681 * Hopefully this has been filled in by calling CreateType() on the
10682 * TypeBuilder.
10685 * TODO: This won't work if the application finishes another
10686 * TypeBuilder instance instead of this one.
10688 result = mb->mhandle;
10690 if (context)
10691 result = mono_class_inflate_generic_method (result, context);
10692 *handle_class = mono_defaults.methodhandle_class;
10693 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
10694 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
10696 result = cb->mhandle;
10697 if (!result) {
10698 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
10700 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10701 result = cb->mhandle;
10703 if (context)
10704 result = mono_class_inflate_generic_method (result, context);
10705 *handle_class = mono_defaults.methodhandle_class;
10706 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
10707 MonoClassField *field = ((MonoReflectionField*)obj)->field;
10709 ensure_complete_type (field->parent);
10710 if (context) {
10711 MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
10712 MonoClass *class = mono_class_from_mono_type (inflated);
10713 MonoClassField *inflated_field;
10714 gpointer iter = NULL;
10715 mono_metadata_free_type (inflated);
10716 while ((inflated_field = mono_class_get_fields (class, &iter))) {
10717 if (!strcmp (field->name, inflated_field->name))
10718 break;
10720 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
10721 result = inflated_field;
10722 } else {
10723 result = field;
10725 *handle_class = mono_defaults.fieldhandle_class;
10726 g_assert (result);
10727 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
10728 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
10729 result = fb->handle;
10731 if (!result) {
10732 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
10734 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10735 result = fb->handle;
10738 if (fb->handle && fb->handle->parent->generic_container) {
10739 MonoClass *klass = fb->handle->parent;
10740 MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
10741 MonoClass *inflated = mono_class_from_mono_type (type);
10743 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
10744 g_assert (result);
10745 mono_metadata_free_type (type);
10747 *handle_class = mono_defaults.fieldhandle_class;
10748 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
10749 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
10750 MonoClass *klass;
10752 klass = tb->type.type->data.klass;
10753 if (klass->wastypebuilder) {
10754 /* Already created */
10755 result = klass;
10757 else {
10758 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10759 result = tb->type.type->data.klass;
10760 g_assert (result);
10762 *handle_class = mono_defaults.typehandle_class;
10763 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
10764 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
10765 MonoMethodSignature *sig;
10766 int nargs, i;
10768 if (helper->arguments)
10769 nargs = mono_array_length (helper->arguments);
10770 else
10771 nargs = 0;
10773 sig = mono_metadata_signature_alloc (image, nargs);
10774 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
10775 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
10777 if (helper->call_conv == 0) /* unmanaged */
10778 sig->call_convention = helper->unmanaged_call_conv - 1;
10779 else
10780 if (helper->call_conv & 0x02)
10781 sig->call_convention = MONO_CALL_VARARG;
10782 else
10783 sig->call_convention = MONO_CALL_DEFAULT;
10785 sig->param_count = nargs;
10786 /* TODO: Copy type ? */
10787 sig->ret = helper->return_type->type;
10788 for (i = 0; i < nargs; ++i) {
10789 MonoReflectionType *rt = mono_type_array_get (helper->arguments, i);
10790 sig->params [i] = rt->type;
10793 result = sig;
10794 *handle_class = NULL;
10795 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
10796 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
10797 /* Already created by the managed code */
10798 g_assert (method->mhandle);
10799 result = method->mhandle;
10800 *handle_class = mono_defaults.methodhandle_class;
10801 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
10802 MonoReflectionType *tb = (MonoReflectionType*)obj;
10803 MonoType *type = mono_class_inflate_generic_type (tb->type, context);
10804 result = mono_class_from_mono_type (type);
10805 *handle_class = mono_defaults.typehandle_class;
10806 g_assert (result);
10807 mono_metadata_free_type (type);
10808 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
10809 MonoReflectionGenericClass *ref = (MonoReflectionGenericClass*)obj;
10810 MonoType *type = mono_class_inflate_generic_type (ref->type.type, context);
10811 result = mono_class_from_mono_type (type);
10812 *handle_class = mono_defaults.typehandle_class;
10813 g_assert (result);
10814 mono_metadata_free_type (type);
10815 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
10816 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
10817 MonoClass *inflated;
10818 MonoType *type;
10820 type = mono_class_inflate_generic_type (f->inst->type.type, context);
10821 inflated = mono_class_from_mono_type (type);
10823 g_assert (f->fb->handle);
10824 result = mono_class_get_field_from_name (inflated, mono_field_get_name (f->fb->handle));
10825 g_assert (result);
10826 mono_metadata_free_type (type);
10827 *handle_class = mono_defaults.fieldhandle_class;
10828 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
10829 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
10830 MonoType *type = mono_class_inflate_generic_type (c->inst->type.type, context);
10831 MonoClass *inflated_klass = mono_class_from_mono_type (type);
10832 g_assert (c->cb->mhandle);
10833 result = inflate_mono_method (inflated_klass, c->cb->mhandle, (MonoObject*)c->cb);
10834 *handle_class = mono_defaults.methodhandle_class;
10835 mono_metadata_free_type (type);
10836 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
10837 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
10838 MonoType *type = mono_class_inflate_generic_type (m->inst->type.type, context);
10839 MonoClass *inflated_klass = mono_class_from_mono_type (type);
10840 g_assert (m->mb->mhandle);
10841 result = inflate_mono_method (inflated_klass, m->mb->mhandle, (MonoObject*)m->mb);
10842 *handle_class = mono_defaults.methodhandle_class;
10843 mono_metadata_free_type (type);
10844 } else {
10845 g_print (obj->vtable->klass->name);
10846 g_assert_not_reached ();
10848 return result;
10851 #else /* DISABLE_REFLECTION_EMIT */
10853 MonoArray*
10854 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
10856 g_assert_not_reached ();
10857 return NULL;
10860 void
10861 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
10863 g_assert_not_reached ();
10866 void
10867 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
10869 g_assert_not_reached ();
10872 void
10873 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
10875 g_assert_not_reached ();
10878 void
10879 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
10881 g_assert_not_reached ();
10884 void
10885 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
10887 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
10890 void
10891 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
10893 g_assert_not_reached ();
10896 MonoReflectionModule *
10897 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
10899 g_assert_not_reached ();
10900 return NULL;
10903 guint32
10904 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
10906 g_assert_not_reached ();
10907 return 0;
10910 guint32
10911 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
10913 g_assert_not_reached ();
10914 return 0;
10917 guint32
10918 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
10919 gboolean create_methodspec, gboolean register_token)
10921 g_assert_not_reached ();
10922 return 0;
10925 void
10926 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
10930 void
10931 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
10932 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
10933 MonoArray *events)
10935 g_assert_not_reached ();
10938 void
10939 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
10941 *overrides = NULL;
10942 *num_overrides = 0;
10945 MonoReflectionEvent *
10946 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
10948 g_assert_not_reached ();
10949 return NULL;
10952 MonoReflectionType*
10953 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
10955 g_assert_not_reached ();
10956 return NULL;
10959 void
10960 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
10962 g_assert_not_reached ();
10965 MonoArray *
10966 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
10968 g_assert_not_reached ();
10969 return NULL;
10972 MonoArray *
10973 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
10975 g_assert_not_reached ();
10976 return NULL;
10979 void
10980 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
10984 gpointer
10985 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
10987 return NULL;
10990 #endif /* DISABLE_REFLECTION_EMIT */
10992 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
10993 const static guint32 declsec_flags_map[] = {
10994 0x00000000, /* empty */
10995 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
10996 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
10997 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
10998 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
10999 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
11000 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
11001 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
11002 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
11003 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
11004 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
11005 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
11006 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
11007 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
11008 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
11009 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
11010 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
11011 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
11012 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
11016 * Returns flags that includes all available security action associated to the handle.
11017 * @token: metadata token (either for a class or a method)
11018 * @image: image where resides the metadata.
11020 static guint32
11021 mono_declsec_get_flags (MonoImage *image, guint32 token)
11023 int index = mono_metadata_declsec_from_index (image, token);
11024 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
11025 guint32 result = 0;
11026 guint32 action;
11027 int i;
11029 /* HasSecurity can be present for other, not specially encoded, attributes,
11030 e.g. SuppressUnmanagedCodeSecurityAttribute */
11031 if (index < 0)
11032 return 0;
11034 for (i = index; i < t->rows; i++) {
11035 guint32 cols [MONO_DECL_SECURITY_SIZE];
11037 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
11038 if (cols [MONO_DECL_SECURITY_PARENT] != token)
11039 break;
11041 action = cols [MONO_DECL_SECURITY_ACTION];
11042 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
11043 result |= declsec_flags_map [action];
11044 } else {
11045 g_assert_not_reached ();
11048 return result;
11052 * Get the security actions (in the form of flags) associated with the specified method.
11054 * @method: The method for which we want the declarative security flags.
11055 * Return the declarative security flags for the method (only).
11057 * Note: To keep MonoMethod size down we do not cache the declarative security flags
11058 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
11060 guint32
11061 mono_declsec_flags_from_method (MonoMethod *method)
11063 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11064 /* FIXME: No cache (for the moment) */
11065 guint32 idx = mono_method_get_index (method);
11066 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11067 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
11068 return mono_declsec_get_flags (method->klass->image, idx);
11070 return 0;
11074 * Get the security actions (in the form of flags) associated with the specified class.
11076 * @klass: The class for which we want the declarative security flags.
11077 * Return the declarative security flags for the class.
11079 * Note: We cache the flags inside the MonoClass structure as this will get
11080 * called very often (at least for each method).
11082 guint32
11083 mono_declsec_flags_from_class (MonoClass *klass)
11085 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
11086 if (!klass->ext || !klass->ext->declsec_flags) {
11087 guint32 idx;
11089 idx = mono_metadata_token_index (klass->type_token);
11090 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11091 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
11092 mono_loader_lock ();
11093 mono_class_alloc_ext (klass);
11094 mono_loader_unlock ();
11095 /* we cache the flags on classes */
11096 klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
11098 return klass->ext->declsec_flags;
11100 return 0;
11104 * Get the security actions (in the form of flags) associated with the specified assembly.
11106 * @assembly: The assembly for which we want the declarative security flags.
11107 * Return the declarative security flags for the assembly.
11109 guint32
11110 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
11112 guint32 idx = 1; /* there is only one assembly */
11113 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11114 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
11115 return mono_declsec_get_flags (assembly->image, idx);
11120 * Fill actions for the specific index (which may either be an encoded class token or
11121 * an encoded method token) from the metadata image.
11122 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
11124 static MonoBoolean
11125 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
11126 guint32 id_std, guint32 id_noncas, guint32 id_choice)
11128 MonoBoolean result = FALSE;
11129 MonoTableInfo *t;
11130 guint32 cols [MONO_DECL_SECURITY_SIZE];
11131 int index = mono_metadata_declsec_from_index (image, token);
11132 int i;
11134 t = &image->tables [MONO_TABLE_DECLSECURITY];
11135 for (i = index; i < t->rows; i++) {
11136 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
11138 if (cols [MONO_DECL_SECURITY_PARENT] != token)
11139 return result;
11141 /* if present only replace (class) permissions with method permissions */
11142 /* if empty accept either class or method permissions */
11143 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
11144 if (!actions->demand.blob) {
11145 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11146 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
11147 actions->demand.blob = (char*) (blob + 2);
11148 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
11149 result = TRUE;
11151 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
11152 if (!actions->noncasdemand.blob) {
11153 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11154 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
11155 actions->noncasdemand.blob = (char*) (blob + 2);
11156 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
11157 result = TRUE;
11159 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
11160 if (!actions->demandchoice.blob) {
11161 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11162 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
11163 actions->demandchoice.blob = (char*) (blob + 2);
11164 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
11165 result = TRUE;
11170 return result;
11173 static MonoBoolean
11174 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
11175 guint32 id_std, guint32 id_noncas, guint32 id_choice)
11177 guint32 idx = mono_metadata_token_index (klass->type_token);
11178 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11179 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
11180 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
11183 static MonoBoolean
11184 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
11185 guint32 id_std, guint32 id_noncas, guint32 id_choice)
11187 guint32 idx = mono_method_get_index (method);
11188 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11189 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
11190 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
11194 * Collect all actions (that requires to generate code in mini) assigned for
11195 * the specified method.
11196 * Note: Don't use the content of actions if the function return FALSE.
11198 MonoBoolean
11199 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
11201 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
11202 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
11203 MonoBoolean result = FALSE;
11204 guint32 flags;
11206 /* quick exit if no declarative security is present in the metadata */
11207 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11208 return FALSE;
11210 /* we want the original as the wrapper is "free" of the security informations */
11211 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
11212 method = mono_marshal_method_from_wrapper (method);
11213 if (!method)
11214 return FALSE;
11217 /* First we look for method-level attributes */
11218 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11219 mono_class_init (method->klass);
11220 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11222 result = mono_declsec_get_method_demands_params (method, demands,
11223 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
11226 /* Here we use (or create) the class declarative cache to look for demands */
11227 flags = mono_declsec_flags_from_class (method->klass);
11228 if (flags & mask) {
11229 if (!result) {
11230 mono_class_init (method->klass);
11231 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11233 result |= mono_declsec_get_class_demands_params (method->klass, demands,
11234 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
11237 /* The boolean return value is used as a shortcut in case nothing needs to
11238 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
11239 return result;
11244 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
11246 * Note: Don't use the content of actions if the function return FALSE.
11248 MonoBoolean
11249 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
11251 MonoBoolean result = FALSE;
11252 guint32 flags;
11254 /* quick exit if no declarative security is present in the metadata */
11255 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11256 return FALSE;
11258 /* we want the original as the wrapper is "free" of the security informations */
11259 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
11260 method = mono_marshal_method_from_wrapper (method);
11261 if (!method)
11262 return FALSE;
11265 /* results are independant - zeroize both */
11266 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
11267 memset (klass, 0, sizeof (MonoDeclSecurityActions));
11269 /* First we look for method-level attributes */
11270 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11271 mono_class_init (method->klass);
11273 result = mono_declsec_get_method_demands_params (method, cmethod,
11274 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
11277 /* Here we use (or create) the class declarative cache to look for demands */
11278 flags = mono_declsec_flags_from_class (method->klass);
11279 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
11280 mono_class_init (method->klass);
11282 result |= mono_declsec_get_class_demands_params (method->klass, klass,
11283 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
11286 return result;
11290 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
11292 * @klass The inherited class - this is the class that provides the security check (attributes)
11293 * @demans
11294 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
11296 * Note: Don't use the content of actions if the function return FALSE.
11298 MonoBoolean
11299 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
11301 MonoBoolean result = FALSE;
11302 guint32 flags;
11304 /* quick exit if no declarative security is present in the metadata */
11305 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11306 return FALSE;
11308 /* Here we use (or create) the class declarative cache to look for demands */
11309 flags = mono_declsec_flags_from_class (klass);
11310 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
11311 mono_class_init (klass);
11312 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11314 result |= mono_declsec_get_class_demands_params (klass, demands,
11315 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
11318 return result;
11322 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
11324 * Note: Don't use the content of actions if the function return FALSE.
11326 MonoBoolean
11327 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
11329 /* quick exit if no declarative security is present in the metadata */
11330 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11331 return FALSE;
11333 /* we want the original as the wrapper is "free" of the security informations */
11334 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
11335 method = mono_marshal_method_from_wrapper (method);
11336 if (!method)
11337 return FALSE;
11340 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11341 mono_class_init (method->klass);
11342 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11344 return mono_declsec_get_method_demands_params (method, demands,
11345 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
11347 return FALSE;
11351 static MonoBoolean
11352 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
11354 guint32 cols [MONO_DECL_SECURITY_SIZE];
11355 MonoTableInfo *t;
11356 int i;
11358 int index = mono_metadata_declsec_from_index (image, token);
11359 if (index == -1)
11360 return FALSE;
11362 t = &image->tables [MONO_TABLE_DECLSECURITY];
11363 for (i = index; i < t->rows; i++) {
11364 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
11366 /* shortcut - index are ordered */
11367 if (token != cols [MONO_DECL_SECURITY_PARENT])
11368 return FALSE;
11370 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
11371 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11372 entry->blob = (char*) (metadata + 2);
11373 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
11374 return TRUE;
11378 return FALSE;
11381 MonoBoolean
11382 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
11384 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11385 guint32 idx = mono_method_get_index (method);
11386 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11387 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
11388 return get_declsec_action (method->klass->image, idx, action, entry);
11390 return FALSE;
11393 MonoBoolean
11394 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
11396 /* use cache */
11397 guint32 flags = mono_declsec_flags_from_class (klass);
11398 if (declsec_flags_map [action] & flags) {
11399 guint32 idx = mono_metadata_token_index (klass->type_token);
11400 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11401 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
11402 return get_declsec_action (klass->image, idx, action, entry);
11404 return FALSE;
11407 MonoBoolean
11408 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
11410 guint32 idx = 1; /* there is only one assembly */
11411 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11412 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
11414 return get_declsec_action (assembly->image, idx, action, entry);
11417 gboolean
11418 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
11420 MonoObject *res, *exc;
11421 void *params [1];
11422 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
11423 static MonoMethod *method = NULL;
11425 if (!System_Reflection_Emit_TypeBuilder) {
11426 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
11427 g_assert (System_Reflection_Emit_TypeBuilder);
11429 if (method == NULL) {
11430 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
11431 g_assert (method);
11435 * The result of mono_type_get_object () might be a System.MonoType but we
11436 * need a TypeBuilder so use klass->reflection_info.
11438 g_assert (klass->reflection_info);
11439 g_assert (!strcmp (((MonoObject*)(klass->reflection_info))->vtable->klass->name, "TypeBuilder"));
11441 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
11443 res = mono_runtime_invoke (method, (MonoObject*)(klass->reflection_info), params, &exc);
11444 if (exc)
11445 return FALSE;
11446 else
11447 return *(MonoBoolean*)mono_object_unbox (res);