2010-04-07 Rodrigo Kumpera <rkumpera@novell.com>
[mono.git] / mono / metadata / reflection.c
blobfa431524496bec82c5da3fde79f2a383129a44f1
1 /*
2 * reflection.c: Routines for creating an image at runtime.
3 *
4 * Author:
5 * Paolo Molaro (lupus@ximian.com)
7 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
11 #include <config.h>
12 #include "mono/utils/mono-digest.h"
13 #include "mono/utils/mono-membar.h"
14 #include "mono/metadata/reflection.h"
15 #include "mono/metadata/tabledefs.h"
16 #include "mono/metadata/metadata-internals.h"
17 #include <mono/metadata/profiler-private.h>
18 #include "mono/metadata/class-internals.h"
19 #include "mono/metadata/gc-internal.h"
20 #include "mono/metadata/tokentype.h"
21 #include "mono/metadata/domain-internals.h"
22 #include "mono/metadata/opcodes.h"
23 #include "mono/metadata/assembly.h"
24 #include "mono/metadata/object-internals.h"
25 #include <mono/metadata/exception.h>
26 #include <mono/metadata/marshal.h>
27 #include <mono/metadata/security-manager.h>
28 #include <stdio.h>
29 #include <glib.h>
30 #include <errno.h>
31 #include <time.h>
32 #include <string.h>
33 #include <ctype.h>
34 #include "image.h"
35 #include "cil-coff.h"
36 #include "mono-endian.h"
37 #include <mono/metadata/gc-internal.h>
38 #include <mono/metadata/mempool-internals.h>
39 #include <mono/metadata/security-core-clr.h>
40 #include <mono/metadata/debug-helpers.h>
41 #include <mono/utils/mono-string.h>
42 #include <mono/utils/mono-error-internals.h>
45 #if HAVE_SGEN_GC
46 static void* reflection_info_desc = NULL;
47 #define MOVING_GC_REGISTER(addr) do { \
48 if (!reflection_info_desc) { \
49 gsize bmap = 1; \
50 reflection_info_desc = mono_gc_make_descr_from_bitmap (&bmap, 1); \
51 } \
52 mono_gc_register_root ((char*)(addr), sizeof (gpointer), reflection_info_desc); \
53 } while (0)
54 #else
55 #define MOVING_GC_REGISTER(addr)
56 #endif
58 static gboolean is_usertype (MonoReflectionType *ref);
59 static MonoReflectionType *mono_reflection_type_resolve_user_types (MonoReflectionType *type);
61 typedef struct {
62 char *p;
63 char *buf;
64 char *end;
65 } SigBuffer;
67 #define TEXT_OFFSET 512
68 #define CLI_H_SIZE 136
69 #define FILE_ALIGN 512
70 #define VIRT_ALIGN 8192
71 #define START_TEXT_RVA 0x00002000
73 typedef struct {
74 MonoReflectionILGen *ilgen;
75 MonoReflectionType *rtype;
76 MonoArray *parameters;
77 MonoArray *generic_params;
78 MonoGenericContainer *generic_container;
79 MonoArray *pinfo;
80 MonoArray *opt_types;
81 guint32 attrs;
82 guint32 iattrs;
83 guint32 call_conv;
84 guint32 *table_idx; /* note: it's a pointer */
85 MonoArray *code;
86 MonoObject *type;
87 MonoString *name;
88 MonoBoolean init_locals;
89 MonoBoolean skip_visibility;
90 MonoArray *return_modreq;
91 MonoArray *return_modopt;
92 MonoArray *param_modreq;
93 MonoArray *param_modopt;
94 MonoArray *permissions;
95 MonoMethod *mhandle;
96 guint32 nrefs;
97 gpointer *refs;
98 /* for PInvoke */
99 int charset, extra_flags, native_cc;
100 MonoString *dll, *dllentry;
101 } ReflectionMethodBuilder;
103 typedef struct {
104 guint32 owner;
105 MonoReflectionGenericParam *gparam;
106 } GenericParamTableEntry;
108 const unsigned char table_sizes [MONO_TABLE_NUM] = {
109 MONO_MODULE_SIZE,
110 MONO_TYPEREF_SIZE,
111 MONO_TYPEDEF_SIZE,
113 MONO_FIELD_SIZE,
115 MONO_METHOD_SIZE,
117 MONO_PARAM_SIZE,
118 MONO_INTERFACEIMPL_SIZE,
119 MONO_MEMBERREF_SIZE, /* 0x0A */
120 MONO_CONSTANT_SIZE,
121 MONO_CUSTOM_ATTR_SIZE,
122 MONO_FIELD_MARSHAL_SIZE,
123 MONO_DECL_SECURITY_SIZE,
124 MONO_CLASS_LAYOUT_SIZE,
125 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
126 MONO_STAND_ALONE_SIGNATURE_SIZE,
127 MONO_EVENT_MAP_SIZE,
129 MONO_EVENT_SIZE,
130 MONO_PROPERTY_MAP_SIZE,
132 MONO_PROPERTY_SIZE,
133 MONO_METHOD_SEMA_SIZE,
134 MONO_METHODIMPL_SIZE,
135 MONO_MODULEREF_SIZE, /* 0x1A */
136 MONO_TYPESPEC_SIZE,
137 MONO_IMPLMAP_SIZE,
138 MONO_FIELD_RVA_SIZE,
141 MONO_ASSEMBLY_SIZE, /* 0x20 */
142 MONO_ASSEMBLY_PROCESSOR_SIZE,
143 MONO_ASSEMBLYOS_SIZE,
144 MONO_ASSEMBLYREF_SIZE,
145 MONO_ASSEMBLYREFPROC_SIZE,
146 MONO_ASSEMBLYREFOS_SIZE,
147 MONO_FILE_SIZE,
148 MONO_EXP_TYPE_SIZE,
149 MONO_MANIFEST_SIZE,
150 MONO_NESTED_CLASS_SIZE,
152 MONO_GENERICPARAM_SIZE, /* 0x2A */
153 MONO_METHODSPEC_SIZE,
154 MONO_GENPARCONSTRAINT_SIZE
158 #ifndef DISABLE_REFLECTION_EMIT
159 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
160 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec);
161 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
162 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
163 static void ensure_runtime_vtable (MonoClass *klass);
164 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
165 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method);
166 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
167 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
168 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
169 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
170 static guint32 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb);
171 #endif
173 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
174 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
175 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
176 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
177 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
178 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
179 static void encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
180 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
181 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t);
182 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
183 static MonoReflectionType* mono_reflection_type_resolve_user_types (MonoReflectionType *type);
184 static gboolean is_sre_array (MonoClass *class);
185 static gboolean is_sre_byref (MonoClass *class);
186 static gboolean is_sre_pointer (MonoClass *class);
187 static gboolean is_sre_type_builder (MonoClass *class);
188 static gboolean is_sre_method_builder (MonoClass *class);
189 static gboolean is_sre_ctor_builder (MonoClass *class);
190 static gboolean is_sre_field_builder (MonoClass *class);
191 static gboolean is_sr_mono_method (MonoClass *class);
192 static gboolean is_sr_mono_cmethod (MonoClass *class);
193 static gboolean is_sr_mono_generic_method (MonoClass *class);
194 static gboolean is_sr_mono_generic_cmethod (MonoClass *class);
195 static gboolean is_sr_mono_field (MonoClass *class);
196 static gboolean is_sr_mono_property (MonoClass *class);
197 static gboolean is_sre_method_on_tb_inst (MonoClass *class);
198 static gboolean is_sre_ctor_on_tb_inst (MonoClass *class);
200 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
201 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
202 static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj);
204 #define RESOLVE_TYPE(type) do { type = (void*)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type); } while (0)
205 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index) do { \
206 MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index); \
207 __type = mono_reflection_type_resolve_user_types (__type); \
208 mono_array_set (arr, MonoReflectionType*, index, __type); \
209 } while (0)
211 #define mono_type_array_get_and_resolve(array, index) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index))
213 void
214 mono_reflection_init (void)
218 static void
219 sigbuffer_init (SigBuffer *buf, int size)
221 buf->buf = g_malloc (size);
222 buf->p = buf->buf;
223 buf->end = buf->buf + size;
226 static void
227 sigbuffer_make_room (SigBuffer *buf, int size)
229 if (buf->end - buf->p < size) {
230 int new_size = buf->end - buf->buf + size + 32;
231 char *p = g_realloc (buf->buf, new_size);
232 size = buf->p - buf->buf;
233 buf->buf = p;
234 buf->p = p + size;
235 buf->end = buf->buf + new_size;
239 static void
240 sigbuffer_add_value (SigBuffer *buf, guint32 val)
242 sigbuffer_make_room (buf, 6);
243 mono_metadata_encode_value (val, buf->p, &buf->p);
246 static void
247 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
249 sigbuffer_make_room (buf, 1);
250 buf->p [0] = val;
251 buf->p++;
254 static void
255 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
257 sigbuffer_make_room (buf, size);
258 memcpy (buf->p, p, size);
259 buf->p += size;
262 static void
263 sigbuffer_free (SigBuffer *buf)
265 g_free (buf->buf);
268 #ifndef DISABLE_REFLECTION_EMIT
270 * mp_g_alloc:
272 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
273 * from the C heap.
275 static gpointer
276 image_g_malloc (MonoImage *image, guint size)
278 if (image)
279 return mono_image_alloc (image, size);
280 else
281 return g_malloc (size);
283 #endif /* !DISABLE_REFLECTION_EMIT */
286 * image_g_alloc0:
288 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
289 * from the C heap.
291 static gpointer
292 image_g_malloc0 (MonoImage *image, guint size)
294 if (image)
295 return mono_image_alloc0 (image, size);
296 else
297 return g_malloc0 (size);
300 #ifndef DISABLE_REFLECTION_EMIT
301 static char*
302 image_strdup (MonoImage *image, const char *s)
304 if (image)
305 return mono_image_strdup (image, s);
306 else
307 return g_strdup (s);
309 #endif
311 #define image_g_new(image,struct_type, n_structs) \
312 ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
314 #define image_g_new0(image,struct_type, n_structs) \
315 ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
318 static void
319 alloc_table (MonoDynamicTable *table, guint nrows)
321 table->rows = nrows;
322 g_assert (table->columns);
323 if (nrows + 1 >= table->alloc_rows) {
324 while (nrows + 1 >= table->alloc_rows) {
325 if (table->alloc_rows == 0)
326 table->alloc_rows = 16;
327 else
328 table->alloc_rows *= 2;
331 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
335 static void
336 make_room_in_stream (MonoDynamicStream *stream, int size)
338 if (size <= stream->alloc_size)
339 return;
341 while (stream->alloc_size <= size) {
342 if (stream->alloc_size < 4096)
343 stream->alloc_size = 4096;
344 else
345 stream->alloc_size *= 2;
348 stream->data = g_realloc (stream->data, stream->alloc_size);
351 static guint32
352 string_heap_insert (MonoDynamicStream *sh, const char *str)
354 guint32 idx;
355 guint32 len;
356 gpointer oldkey, oldval;
358 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
359 return GPOINTER_TO_UINT (oldval);
361 len = strlen (str) + 1;
362 idx = sh->index;
364 make_room_in_stream (sh, idx + len);
367 * We strdup the string even if we already copy them in sh->data
368 * so that the string pointers in the hash remain valid even if
369 * we need to realloc sh->data. We may want to avoid that later.
371 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
372 memcpy (sh->data + idx, str, len);
373 sh->index += len;
374 return idx;
377 static guint32
378 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
380 char *name = mono_string_to_utf8 (str);
381 guint32 idx;
382 idx = string_heap_insert (sh, name);
383 g_free (name);
384 return idx;
387 #ifndef DISABLE_REFLECTION_EMIT
388 static void
389 string_heap_init (MonoDynamicStream *sh)
391 sh->index = 0;
392 sh->alloc_size = 4096;
393 sh->data = g_malloc (4096);
394 sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
395 string_heap_insert (sh, "");
397 #endif
399 static guint32
400 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
402 guint32 idx;
404 make_room_in_stream (stream, stream->index + len);
405 memcpy (stream->data + stream->index, data, len);
406 idx = stream->index;
407 stream->index += len;
409 * align index? Not without adding an additional param that controls it since
410 * we may store a blob value in pieces.
412 return idx;
415 static guint32
416 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
418 guint32 idx;
420 make_room_in_stream (stream, stream->index + len);
421 memset (stream->data + stream->index, 0, len);
422 idx = stream->index;
423 stream->index += len;
424 return idx;
427 static void
428 stream_data_align (MonoDynamicStream *stream)
430 char buf [4] = {0};
431 guint32 count = stream->index % 4;
433 /* we assume the stream data will be aligned */
434 if (count)
435 mono_image_add_stream_data (stream, buf, 4 - count);
438 #ifndef DISABLE_REFLECTION_EMIT
439 static int
440 mono_blob_entry_hash (const char* str)
442 guint len, h;
443 const char *end;
444 len = mono_metadata_decode_blob_size (str, &str);
445 if (len > 0) {
446 end = str + len;
447 h = *str;
448 for (str += 1; str < end; str++)
449 h = (h << 5) - h + *str;
450 return h;
451 } else {
452 return 0;
456 static gboolean
457 mono_blob_entry_equal (const char *str1, const char *str2) {
458 int len, len2;
459 const char *end1;
460 const char *end2;
461 len = mono_metadata_decode_blob_size (str1, &end1);
462 len2 = mono_metadata_decode_blob_size (str2, &end2);
463 if (len != len2)
464 return 0;
465 return memcmp (end1, end2, len) == 0;
467 #endif
468 static guint32
469 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
471 guint32 idx;
472 char *copy;
473 gpointer oldkey, oldval;
475 copy = g_malloc (s1+s2);
476 memcpy (copy, b1, s1);
477 memcpy (copy + s1, b2, s2);
478 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
479 g_free (copy);
480 idx = GPOINTER_TO_UINT (oldval);
481 } else {
482 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
483 mono_image_add_stream_data (&assembly->blob, b2, s2);
484 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
486 return idx;
489 static guint32
490 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
492 char blob_size [8];
493 char *b = blob_size;
494 guint32 size = buf->p - buf->buf;
495 /* store length */
496 g_assert (size <= (buf->end - buf->buf));
497 mono_metadata_encode_value (size, b, &b);
498 return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
502 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
503 * dest may be misaligned.
505 static void
506 swap_with_size (char *dest, const char* val, int len, int nelem) {
507 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
508 int elem;
510 for (elem = 0; elem < nelem; ++elem) {
511 switch (len) {
512 case 1:
513 *dest = *val;
514 break;
515 case 2:
516 dest [0] = val [1];
517 dest [1] = val [0];
518 break;
519 case 4:
520 dest [0] = val [3];
521 dest [1] = val [2];
522 dest [2] = val [1];
523 dest [3] = val [0];
524 break;
525 case 8:
526 dest [0] = val [7];
527 dest [1] = val [6];
528 dest [2] = val [5];
529 dest [3] = val [4];
530 dest [4] = val [3];
531 dest [5] = val [2];
532 dest [6] = val [1];
533 dest [7] = val [0];
534 break;
535 default:
536 g_assert_not_reached ();
538 dest += len;
539 val += len;
541 #else
542 memcpy (dest, val, len * nelem);
543 #endif
546 static guint32
547 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
549 char blob_size [64];
550 char *b = blob_size;
551 guint32 idx = 0, len;
553 len = str->length * 2;
554 mono_metadata_encode_value (len, b, &b);
555 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
557 char *swapped = g_malloc (2 * mono_string_length (str));
558 const char *p = (const char*)mono_string_chars (str);
560 swap_with_size (swapped, p, 2, mono_string_length (str));
561 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
562 g_free (swapped);
564 #else
565 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
566 #endif
567 return idx;
570 #ifndef DISABLE_REFLECTION_EMIT
571 static MonoClass *
572 default_class_from_mono_type (MonoType *type)
574 switch (type->type) {
575 case MONO_TYPE_OBJECT:
576 return mono_defaults.object_class;
577 case MONO_TYPE_VOID:
578 return mono_defaults.void_class;
579 case MONO_TYPE_BOOLEAN:
580 return mono_defaults.boolean_class;
581 case MONO_TYPE_CHAR:
582 return mono_defaults.char_class;
583 case MONO_TYPE_I1:
584 return mono_defaults.sbyte_class;
585 case MONO_TYPE_U1:
586 return mono_defaults.byte_class;
587 case MONO_TYPE_I2:
588 return mono_defaults.int16_class;
589 case MONO_TYPE_U2:
590 return mono_defaults.uint16_class;
591 case MONO_TYPE_I4:
592 return mono_defaults.int32_class;
593 case MONO_TYPE_U4:
594 return mono_defaults.uint32_class;
595 case MONO_TYPE_I:
596 return mono_defaults.int_class;
597 case MONO_TYPE_U:
598 return mono_defaults.uint_class;
599 case MONO_TYPE_I8:
600 return mono_defaults.int64_class;
601 case MONO_TYPE_U8:
602 return mono_defaults.uint64_class;
603 case MONO_TYPE_R4:
604 return mono_defaults.single_class;
605 case MONO_TYPE_R8:
606 return mono_defaults.double_class;
607 case MONO_TYPE_STRING:
608 return mono_defaults.string_class;
609 default:
610 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
611 g_assert_not_reached ();
614 return NULL;
616 #endif
619 * mono_class_get_ref_info:
621 * Return the type builder/generic param builder corresponding to KLASS, if it exists.
623 gpointer
624 mono_class_get_ref_info (MonoClass *klass)
626 if (klass->ref_info_handle == 0)
627 return NULL;
628 else
629 return mono_gchandle_get_target (klass->ref_info_handle);
632 void
633 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
635 klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
636 g_assert (klass->ref_info_handle != 0);
639 void
640 mono_class_free_ref_info (MonoClass *klass)
642 if (klass->ref_info_handle) {
643 mono_gchandle_free (klass->ref_info_handle);
644 klass->ref_info_handle = 0;
648 static void
649 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
651 int i;
652 MonoGenericInst *class_inst;
653 MonoClass *klass;
655 g_assert (gclass);
657 class_inst = gclass->context.class_inst;
659 sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
660 klass = gclass->container_class;
661 sigbuffer_add_value (buf, klass->byval_arg.type);
662 sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
664 sigbuffer_add_value (buf, class_inst->type_argc);
665 for (i = 0; i < class_inst->type_argc; ++i)
666 encode_type (assembly, class_inst->type_argv [i], buf);
670 static void
671 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
673 if (!type) {
674 g_assert_not_reached ();
675 return;
678 if (type->byref)
679 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
681 switch (type->type){
682 case MONO_TYPE_VOID:
683 case MONO_TYPE_BOOLEAN:
684 case MONO_TYPE_CHAR:
685 case MONO_TYPE_I1:
686 case MONO_TYPE_U1:
687 case MONO_TYPE_I2:
688 case MONO_TYPE_U2:
689 case MONO_TYPE_I4:
690 case MONO_TYPE_U4:
691 case MONO_TYPE_I8:
692 case MONO_TYPE_U8:
693 case MONO_TYPE_R4:
694 case MONO_TYPE_R8:
695 case MONO_TYPE_I:
696 case MONO_TYPE_U:
697 case MONO_TYPE_STRING:
698 case MONO_TYPE_OBJECT:
699 case MONO_TYPE_TYPEDBYREF:
700 sigbuffer_add_value (buf, type->type);
701 break;
702 case MONO_TYPE_PTR:
703 sigbuffer_add_value (buf, type->type);
704 encode_type (assembly, type->data.type, buf);
705 break;
706 case MONO_TYPE_SZARRAY:
707 sigbuffer_add_value (buf, type->type);
708 encode_type (assembly, &type->data.klass->byval_arg, buf);
709 break;
710 case MONO_TYPE_VALUETYPE:
711 case MONO_TYPE_CLASS: {
712 MonoClass *k = mono_class_from_mono_type (type);
714 if (k->generic_container) {
715 MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
716 encode_generic_class (assembly, gclass, buf);
717 } else {
719 * Make sure we use the correct type.
721 sigbuffer_add_value (buf, k->byval_arg.type);
723 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
724 * otherwise two typerefs could point to the same type, leading to
725 * verification errors.
727 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
729 break;
731 case MONO_TYPE_ARRAY:
732 sigbuffer_add_value (buf, type->type);
733 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
734 sigbuffer_add_value (buf, type->data.array->rank);
735 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
736 sigbuffer_add_value (buf, 0);
737 break;
738 case MONO_TYPE_GENERICINST:
739 encode_generic_class (assembly, type->data.generic_class, buf);
740 break;
741 case MONO_TYPE_VAR:
742 case MONO_TYPE_MVAR:
743 sigbuffer_add_value (buf, type->type);
744 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
745 break;
746 default:
747 g_error ("need to encode type %x", type->type);
751 static void
752 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
754 if (!type) {
755 sigbuffer_add_value (buf, MONO_TYPE_VOID);
756 return;
759 encode_type (assembly, mono_reflection_type_get_handle (type), buf);
762 static void
763 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
765 int i;
767 if (modreq) {
768 for (i = 0; i < mono_array_length (modreq); ++i) {
769 MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
770 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
771 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
774 if (modopt) {
775 for (i = 0; i < mono_array_length (modopt); ++i) {
776 MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
777 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
778 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
783 #ifndef DISABLE_REFLECTION_EMIT
784 static guint32
785 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
787 SigBuffer buf;
788 int i;
789 guint32 nparams = sig->param_count;
790 guint32 idx;
792 if (!assembly->save)
793 return 0;
795 sigbuffer_init (&buf, 32);
797 * FIXME: vararg, explicit_this, differenc call_conv values...
799 idx = sig->call_convention;
800 if (sig->hasthis)
801 idx |= 0x20; /* hasthis */
802 if (sig->generic_param_count)
803 idx |= 0x10; /* generic */
804 sigbuffer_add_byte (&buf, idx);
805 if (sig->generic_param_count)
806 sigbuffer_add_value (&buf, sig->generic_param_count);
807 sigbuffer_add_value (&buf, nparams);
808 encode_type (assembly, sig->ret, &buf);
809 for (i = 0; i < nparams; ++i) {
810 if (i == sig->sentinelpos)
811 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
812 encode_type (assembly, sig->params [i], &buf);
814 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
815 sigbuffer_free (&buf);
816 return idx;
818 #endif
820 static guint32
821 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
824 * FIXME: reuse code from method_encode_signature().
826 SigBuffer buf;
827 int i;
828 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
829 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
830 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
831 guint32 idx;
833 sigbuffer_init (&buf, 32);
834 /* LAMESPEC: all the call conv spec is foobared */
835 idx = mb->call_conv & 0x60; /* has-this, explicit-this */
836 if (mb->call_conv & 2)
837 idx |= 0x5; /* vararg */
838 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
839 idx |= 0x20; /* hasthis */
840 if (ngparams)
841 idx |= 0x10; /* generic */
842 sigbuffer_add_byte (&buf, idx);
843 if (ngparams)
844 sigbuffer_add_value (&buf, ngparams);
845 sigbuffer_add_value (&buf, nparams + notypes);
846 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
847 encode_reflection_type (assembly, mb->rtype, &buf);
848 for (i = 0; i < nparams; ++i) {
849 MonoArray *modreq = NULL;
850 MonoArray *modopt = NULL;
851 MonoReflectionType *pt;
853 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
854 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
855 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
856 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
857 encode_custom_modifiers (assembly, modreq, modopt, &buf);
858 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
859 encode_reflection_type (assembly, pt, &buf);
861 if (notypes)
862 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
863 for (i = 0; i < notypes; ++i) {
864 MonoReflectionType *pt;
866 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
867 encode_reflection_type (assembly, pt, &buf);
870 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
871 sigbuffer_free (&buf);
872 return idx;
875 static guint32
876 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
878 MonoDynamicTable *table;
879 guint32 *values;
880 guint32 idx, sig_idx;
881 guint nl = mono_array_length (ilgen->locals);
882 SigBuffer buf;
883 int i;
885 sigbuffer_init (&buf, 32);
886 sigbuffer_add_value (&buf, 0x07);
887 sigbuffer_add_value (&buf, nl);
888 for (i = 0; i < nl; ++i) {
889 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
891 if (lb->is_pinned)
892 sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
894 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf);
896 sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
897 sigbuffer_free (&buf);
899 if (assembly->standalonesig_cache == NULL)
900 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
901 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
902 if (idx)
903 return idx;
905 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
906 idx = table->next_idx ++;
907 table->rows ++;
908 alloc_table (table, table->rows);
909 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
911 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
913 g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
915 return idx;
918 static guint32
919 method_count_clauses (MonoReflectionILGen *ilgen)
921 guint32 num_clauses = 0;
922 int i;
924 MonoILExceptionInfo *ex_info;
925 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
926 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
927 if (ex_info->handlers)
928 num_clauses += mono_array_length (ex_info->handlers);
929 else
930 num_clauses++;
933 return num_clauses;
936 #ifndef DISABLE_REFLECTION_EMIT
937 static MonoExceptionClause*
938 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
940 MonoExceptionClause *clauses;
941 MonoExceptionClause *clause;
942 MonoILExceptionInfo *ex_info;
943 MonoILExceptionBlock *ex_block;
944 guint32 finally_start;
945 int i, j, clause_index;;
947 clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
949 clause_index = 0;
950 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
951 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
952 finally_start = ex_info->start + ex_info->len;
953 if (!ex_info->handlers)
954 continue;
955 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
956 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
957 clause = &(clauses [clause_index]);
959 clause->flags = ex_block->type;
960 clause->try_offset = ex_info->start;
962 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
963 clause->try_len = finally_start - ex_info->start;
964 else
965 clause->try_len = ex_info->len;
966 clause->handler_offset = ex_block->start;
967 clause->handler_len = ex_block->len;
968 if (ex_block->extype) {
969 clause->data.catch_class = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype));
970 } else {
971 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
972 clause->data.filter_offset = ex_block->filter_offset;
973 else
974 clause->data.filter_offset = 0;
976 finally_start = ex_block->start + ex_block->len;
978 clause_index ++;
982 return clauses;
984 #endif /* !DISABLE_REFLECTION_EMIT */
986 static guint32
987 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
989 char flags = 0;
990 guint32 idx;
991 guint32 code_size;
992 gint32 max_stack, i;
993 gint32 num_locals = 0;
994 gint32 num_exception = 0;
995 gint maybe_small;
996 guint32 fat_flags;
997 char fat_header [12];
998 guint32 int_value;
999 guint16 short_value;
1000 guint32 local_sig = 0;
1001 guint32 header_size = 12;
1002 MonoArray *code;
1004 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
1005 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
1006 return 0;
1008 /*if (mb->name)
1009 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1010 if (mb->ilgen) {
1011 code = mb->ilgen->code;
1012 code_size = mb->ilgen->code_len;
1013 max_stack = mb->ilgen->max_stack;
1014 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1015 if (mb->ilgen->ex_handlers)
1016 num_exception = method_count_clauses (mb->ilgen);
1017 } else {
1018 code = mb->code;
1019 if (code == NULL){
1020 char *name = mono_string_to_utf8 (mb->name);
1021 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1022 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
1023 g_free (str);
1024 g_free (name);
1025 mono_raise_exception (exception);
1028 code_size = mono_array_length (code);
1029 max_stack = 8; /* we probably need to run a verifier on the code... */
1032 stream_data_align (&assembly->code);
1034 /* check for exceptions, maxstack, locals */
1035 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1036 if (maybe_small) {
1037 if (code_size < 64 && !(code_size & 1)) {
1038 flags = (code_size << 2) | 0x2;
1039 } else if (code_size < 32 && (code_size & 1)) {
1040 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1041 } else {
1042 goto fat_header;
1044 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1045 /* add to the fixup todo list */
1046 if (mb->ilgen && mb->ilgen->num_token_fixups)
1047 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1048 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1049 return assembly->text_rva + idx;
1051 fat_header:
1052 if (num_locals)
1053 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
1055 * FIXME: need to set also the header size in fat_flags.
1056 * (and more sects and init locals flags)
1058 fat_flags = 0x03;
1059 if (num_exception)
1060 fat_flags |= METHOD_HEADER_MORE_SECTS;
1061 if (mb->init_locals)
1062 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1063 fat_header [0] = fat_flags;
1064 fat_header [1] = (header_size / 4 ) << 4;
1065 short_value = GUINT16_TO_LE (max_stack);
1066 memcpy (fat_header + 2, &short_value, 2);
1067 int_value = GUINT32_TO_LE (code_size);
1068 memcpy (fat_header + 4, &int_value, 4);
1069 int_value = GUINT32_TO_LE (local_sig);
1070 memcpy (fat_header + 8, &int_value, 4);
1071 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1072 /* add to the fixup todo list */
1073 if (mb->ilgen && mb->ilgen->num_token_fixups)
1074 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1076 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1077 if (num_exception) {
1078 unsigned char sheader [4];
1079 MonoILExceptionInfo * ex_info;
1080 MonoILExceptionBlock * ex_block;
1081 int j;
1083 stream_data_align (&assembly->code);
1084 /* always use fat format for now */
1085 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1086 num_exception *= 6 * sizeof (guint32);
1087 num_exception += 4; /* include the size of the header */
1088 sheader [1] = num_exception & 0xff;
1089 sheader [2] = (num_exception >> 8) & 0xff;
1090 sheader [3] = (num_exception >> 16) & 0xff;
1091 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1092 /* fat header, so we are already aligned */
1093 /* reverse order */
1094 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1095 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1096 if (ex_info->handlers) {
1097 int finally_start = ex_info->start + ex_info->len;
1098 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1099 guint32 val;
1100 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1101 /* the flags */
1102 val = GUINT32_TO_LE (ex_block->type);
1103 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1104 /* try offset */
1105 val = GUINT32_TO_LE (ex_info->start);
1106 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1107 /* need fault, too, probably */
1108 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1109 val = GUINT32_TO_LE (finally_start - ex_info->start);
1110 else
1111 val = GUINT32_TO_LE (ex_info->len);
1112 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1113 /* handler offset */
1114 val = GUINT32_TO_LE (ex_block->start);
1115 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1116 /* handler len */
1117 val = GUINT32_TO_LE (ex_block->len);
1118 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1119 finally_start = ex_block->start + ex_block->len;
1120 if (ex_block->extype) {
1121 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype)));
1122 } else {
1123 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1124 val = ex_block->filter_offset;
1125 else
1126 val = 0;
1128 val = GUINT32_TO_LE (val);
1129 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1130 /*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",
1131 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);*/
1133 } else {
1134 g_error ("No clauses for ex info block %d", i);
1138 return assembly->text_rva + idx;
1141 static guint32
1142 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1144 int i;
1145 MonoDynamicTable *table;
1146 guint32 *values;
1148 table = &assembly->tables [table_idx];
1150 g_assert (col < table->columns);
1152 values = table->values + table->columns;
1153 for (i = 1; i <= table->rows; ++i) {
1154 if (values [col] == token)
1155 return i;
1156 values += table->columns;
1158 return 0;
1162 * LOCKING: Acquires the loader lock.
1164 static MonoCustomAttrInfo*
1165 lookup_custom_attr (MonoImage *image, gpointer member)
1167 MonoCustomAttrInfo* res;
1169 res = mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1171 if (!res)
1172 return NULL;
1174 return g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1177 static gboolean
1178 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1180 /* FIXME: Need to do more checks */
1181 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1182 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1184 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1185 return FALSE;
1188 return TRUE;
1191 static MonoCustomAttrInfo*
1192 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1194 int i, index, count, not_visible;
1195 MonoCustomAttrInfo *ainfo;
1196 MonoReflectionCustomAttr *cattr;
1198 if (!cattrs)
1199 return NULL;
1200 /* FIXME: check in assembly the Run flag is set */
1202 count = mono_array_length (cattrs);
1204 /* Skip nonpublic attributes since MS.NET seems to do the same */
1205 /* FIXME: This needs to be done more globally */
1206 not_visible = 0;
1207 for (i = 0; i < count; ++i) {
1208 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1209 if (!custom_attr_visible (image, cattr))
1210 not_visible ++;
1212 count -= not_visible;
1214 ainfo = image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1216 ainfo->image = image;
1217 ainfo->num_attrs = count;
1218 ainfo->cached = alloc_img != NULL;
1219 index = 0;
1220 for (i = 0; i < count; ++i) {
1221 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1222 if (custom_attr_visible (image, cattr)) {
1223 unsigned char *saved = mono_image_alloc (image, mono_array_length (cattr->data));
1224 memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1225 ainfo->attrs [index].ctor = cattr->ctor->method;
1226 ainfo->attrs [index].data = saved;
1227 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1228 index ++;
1232 return ainfo;
1235 #ifndef DISABLE_REFLECTION_EMIT
1237 * LOCKING: Acquires the loader lock.
1239 static void
1240 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1242 MonoCustomAttrInfo *ainfo, *tmp;
1244 if (!cattrs || !mono_array_length (cattrs))
1245 return;
1247 ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1249 mono_loader_lock ();
1250 tmp = mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1251 if (tmp)
1252 mono_custom_attrs_free (tmp);
1253 mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1254 mono_loader_unlock ();
1257 #endif
1259 void
1260 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1262 if (!ainfo->cached)
1263 g_free (ainfo);
1267 * idx is the table index of the object
1268 * type is one of MONO_CUSTOM_ATTR_*
1270 static void
1271 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1273 MonoDynamicTable *table;
1274 MonoReflectionCustomAttr *cattr;
1275 guint32 *values;
1276 guint32 count, i, token;
1277 char blob_size [6];
1278 char *p = blob_size;
1280 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1281 if (!cattrs)
1282 return;
1283 count = mono_array_length (cattrs);
1284 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1285 table->rows += count;
1286 alloc_table (table, table->rows);
1287 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1288 idx <<= MONO_CUSTOM_ATTR_BITS;
1289 idx |= type;
1290 for (i = 0; i < count; ++i) {
1291 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1292 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1293 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE);
1294 type = mono_metadata_token_index (token);
1295 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1296 switch (mono_metadata_token_table (token)) {
1297 case MONO_TABLE_METHOD:
1298 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1299 break;
1300 case MONO_TABLE_MEMBERREF:
1301 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1302 break;
1303 default:
1304 g_warning ("got wrong token in custom attr");
1305 continue;
1307 values [MONO_CUSTOM_ATTR_TYPE] = type;
1308 p = blob_size;
1309 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1310 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1311 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1312 values += MONO_CUSTOM_ATTR_SIZE;
1313 ++table->next_idx;
1317 static void
1318 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1320 MonoDynamicTable *table;
1321 guint32 *values;
1322 guint32 count, i, idx;
1323 MonoReflectionPermissionSet *perm;
1325 if (!permissions)
1326 return;
1328 count = mono_array_length (permissions);
1329 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1330 table->rows += count;
1331 alloc_table (table, table->rows);
1333 for (i = 0; i < mono_array_length (permissions); ++i) {
1334 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1336 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1338 idx = mono_metadata_token_index (parent_token);
1339 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1340 switch (mono_metadata_token_table (parent_token)) {
1341 case MONO_TABLE_TYPEDEF:
1342 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1343 break;
1344 case MONO_TABLE_METHOD:
1345 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1346 break;
1347 case MONO_TABLE_ASSEMBLY:
1348 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1349 break;
1350 default:
1351 g_assert_not_reached ();
1354 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1355 values [MONO_DECL_SECURITY_PARENT] = idx;
1356 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1358 ++table->next_idx;
1363 * Fill in the MethodDef and ParamDef tables for a method.
1364 * This is used for both normal methods and constructors.
1366 static void
1367 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1369 MonoDynamicTable *table;
1370 guint32 *values;
1371 guint i, count;
1373 /* room in this table is already allocated */
1374 table = &assembly->tables [MONO_TABLE_METHOD];
1375 *mb->table_idx = table->next_idx ++;
1376 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1377 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1378 values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1379 values [MONO_METHOD_FLAGS] = mb->attrs;
1380 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1381 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1382 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1384 table = &assembly->tables [MONO_TABLE_PARAM];
1385 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1387 mono_image_add_decl_security (assembly,
1388 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1390 if (mb->pinfo) {
1391 MonoDynamicTable *mtable;
1392 guint32 *mvalues;
1394 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1395 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1397 count = 0;
1398 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1399 if (mono_array_get (mb->pinfo, gpointer, i))
1400 count++;
1402 table->rows += count;
1403 alloc_table (table, table->rows);
1404 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1405 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1406 MonoReflectionParamBuilder *pb;
1407 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1408 values [MONO_PARAM_FLAGS] = pb->attrs;
1409 values [MONO_PARAM_SEQUENCE] = i;
1410 if (pb->name != NULL) {
1411 values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1412 } else {
1413 values [MONO_PARAM_NAME] = 0;
1415 values += MONO_PARAM_SIZE;
1416 if (pb->marshal_info) {
1417 mtable->rows++;
1418 alloc_table (mtable, mtable->rows);
1419 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1420 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1421 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1423 pb->table_idx = table->next_idx++;
1424 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1425 guint32 field_type = 0;
1426 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1427 mtable->rows ++;
1428 alloc_table (mtable, mtable->rows);
1429 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1430 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1431 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1432 mvalues [MONO_CONSTANT_TYPE] = field_type;
1433 mvalues [MONO_CONSTANT_PADDING] = 0;
1440 #ifndef DISABLE_REFLECTION_EMIT
1441 static void
1442 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1444 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1446 rmb->ilgen = mb->ilgen;
1447 rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype);
1448 rmb->parameters = mb->parameters;
1449 rmb->generic_params = mb->generic_params;
1450 rmb->generic_container = mb->generic_container;
1451 rmb->opt_types = NULL;
1452 rmb->pinfo = mb->pinfo;
1453 rmb->attrs = mb->attrs;
1454 rmb->iattrs = mb->iattrs;
1455 rmb->call_conv = mb->call_conv;
1456 rmb->code = mb->code;
1457 rmb->type = mb->type;
1458 rmb->name = mb->name;
1459 rmb->table_idx = &mb->table_idx;
1460 rmb->init_locals = mb->init_locals;
1461 rmb->skip_visibility = FALSE;
1462 rmb->return_modreq = mb->return_modreq;
1463 rmb->return_modopt = mb->return_modopt;
1464 rmb->param_modreq = mb->param_modreq;
1465 rmb->param_modopt = mb->param_modopt;
1466 rmb->permissions = mb->permissions;
1467 rmb->mhandle = mb->mhandle;
1468 rmb->nrefs = 0;
1469 rmb->refs = NULL;
1471 if (mb->dll) {
1472 rmb->charset = mb->charset;
1473 rmb->extra_flags = mb->extra_flags;
1474 rmb->native_cc = mb->native_cc;
1475 rmb->dllentry = mb->dllentry;
1476 rmb->dll = mb->dll;
1480 static void
1481 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1483 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1485 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1487 rmb->ilgen = mb->ilgen;
1488 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1489 rmb->parameters = mb->parameters;
1490 rmb->generic_params = NULL;
1491 rmb->generic_container = NULL;
1492 rmb->opt_types = NULL;
1493 rmb->pinfo = mb->pinfo;
1494 rmb->attrs = mb->attrs;
1495 rmb->iattrs = mb->iattrs;
1496 rmb->call_conv = mb->call_conv;
1497 rmb->code = NULL;
1498 rmb->type = mb->type;
1499 rmb->name = mono_string_new (mono_domain_get (), name);
1500 rmb->table_idx = &mb->table_idx;
1501 rmb->init_locals = mb->init_locals;
1502 rmb->skip_visibility = FALSE;
1503 rmb->return_modreq = NULL;
1504 rmb->return_modopt = NULL;
1505 rmb->param_modreq = mb->param_modreq;
1506 rmb->param_modopt = mb->param_modopt;
1507 rmb->permissions = mb->permissions;
1508 rmb->mhandle = mb->mhandle;
1509 rmb->nrefs = 0;
1510 rmb->refs = NULL;
1513 static void
1514 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1516 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1518 rmb->ilgen = mb->ilgen;
1519 rmb->rtype = mb->rtype;
1520 rmb->parameters = mb->parameters;
1521 rmb->generic_params = NULL;
1522 rmb->generic_container = NULL;
1523 rmb->opt_types = NULL;
1524 rmb->pinfo = NULL;
1525 rmb->attrs = mb->attrs;
1526 rmb->iattrs = 0;
1527 rmb->call_conv = mb->call_conv;
1528 rmb->code = NULL;
1529 rmb->type = (MonoObject *) mb->owner;
1530 rmb->name = mb->name;
1531 rmb->table_idx = NULL;
1532 rmb->init_locals = mb->init_locals;
1533 rmb->skip_visibility = mb->skip_visibility;
1534 rmb->return_modreq = NULL;
1535 rmb->return_modopt = NULL;
1536 rmb->param_modreq = NULL;
1537 rmb->param_modopt = NULL;
1538 rmb->permissions = NULL;
1539 rmb->mhandle = mb->mhandle;
1540 rmb->nrefs = 0;
1541 rmb->refs = NULL;
1543 #endif
1545 static void
1546 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1548 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1549 MonoDynamicTable *table;
1550 guint32 *values;
1551 guint32 tok;
1553 if (!mb->override_method)
1554 return;
1556 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1557 table->rows ++;
1558 alloc_table (table, table->rows);
1559 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1560 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1561 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1563 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE, FALSE);
1564 switch (mono_metadata_token_table (tok)) {
1565 case MONO_TABLE_MEMBERREF:
1566 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1567 break;
1568 case MONO_TABLE_METHOD:
1569 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1570 break;
1571 default:
1572 g_assert_not_reached ();
1574 values [MONO_METHODIMPL_DECLARATION] = tok;
1577 #ifndef DISABLE_REFLECTION_EMIT
1578 static void
1579 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1581 MonoDynamicTable *table;
1582 guint32 *values;
1583 ReflectionMethodBuilder rmb;
1584 int i;
1586 reflection_methodbuilder_from_method_builder (&rmb, mb);
1588 mono_image_basic_method (&rmb, assembly);
1589 mb->table_idx = *rmb.table_idx;
1591 if (mb->dll) { /* It's a P/Invoke method */
1592 guint32 moduleref;
1593 /* map CharSet values to on-disk values */
1594 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1595 int extra_flags = mb->extra_flags;
1596 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1597 table->rows ++;
1598 alloc_table (table, table->rows);
1599 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1601 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1602 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1603 if (mb->dllentry)
1604 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1605 else
1606 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1607 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1608 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1609 table = &assembly->tables [MONO_TABLE_MODULEREF];
1610 table->rows ++;
1611 alloc_table (table, table->rows);
1612 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1613 values [MONO_IMPLMAP_SCOPE] = table->rows;
1617 if (mb->generic_params) {
1618 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1619 table->rows += mono_array_length (mb->generic_params);
1620 alloc_table (table, table->rows);
1621 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1622 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1624 mono_image_get_generic_param_info (
1625 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1631 static void
1632 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1634 ReflectionMethodBuilder rmb;
1636 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1638 mono_image_basic_method (&rmb, assembly);
1639 mb->table_idx = *rmb.table_idx;
1641 #endif
1643 static char*
1644 type_get_fully_qualified_name (MonoType *type)
1646 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1649 static char*
1650 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1651 MonoClass *klass;
1652 MonoAssembly *ta;
1654 klass = mono_class_from_mono_type (type);
1655 if (!klass)
1656 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1657 ta = klass->image->assembly;
1658 if (ta->dynamic || (ta == ass)) {
1659 if (klass->generic_class || klass->generic_container)
1660 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1661 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1662 else
1663 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1666 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1669 #ifndef DISABLE_REFLECTION_EMIT
1670 /*field_image is the image to which the eventual custom mods have been encoded against*/
1671 static guint32
1672 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
1674 SigBuffer buf;
1675 guint32 idx, i, token;
1677 if (!assembly->save)
1678 return 0;
1680 sigbuffer_init (&buf, 32);
1682 sigbuffer_add_value (&buf, 0x06);
1683 /* encode custom attributes before the type */
1684 if (type->num_mods) {
1685 for (i = 0; i < type->num_mods; ++i) {
1686 if (field_image) {
1687 MonoClass *class = mono_class_get (field_image, type->modifiers [i].token);
1688 g_assert (class);
1689 token = mono_image_typedef_or_ref (assembly, &class->byval_arg);
1690 } else {
1691 token = type->modifiers [i].token;
1694 if (type->modifiers [i].required)
1695 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1696 else
1697 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1699 sigbuffer_add_value (&buf, token);
1702 encode_type (assembly, type, &buf);
1703 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1704 sigbuffer_free (&buf);
1705 return idx;
1707 #endif
1709 static guint32
1710 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1712 SigBuffer buf;
1713 guint32 idx;
1715 sigbuffer_init (&buf, 32);
1717 sigbuffer_add_value (&buf, 0x06);
1718 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1719 /* encode custom attributes before the type */
1720 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
1721 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1722 sigbuffer_free (&buf);
1723 return idx;
1726 static guint32
1727 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1728 char blob_size [64];
1729 char *b = blob_size;
1730 char *p, *box_val;
1731 char* buf;
1732 guint32 idx = 0, len = 0, dummy = 0;
1733 #ifdef ARM_FPU_FPA
1734 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1735 guint32 fpa_double [2];
1736 guint32 *fpa_p;
1737 #endif
1738 #endif
1740 p = buf = g_malloc (64);
1741 if (!val) {
1742 *ret_type = MONO_TYPE_CLASS;
1743 len = 4;
1744 box_val = (char*)&dummy;
1745 } else {
1746 box_val = ((char*)val) + sizeof (MonoObject);
1747 *ret_type = val->vtable->klass->byval_arg.type;
1749 handle_enum:
1750 switch (*ret_type) {
1751 case MONO_TYPE_BOOLEAN:
1752 case MONO_TYPE_U1:
1753 case MONO_TYPE_I1:
1754 len = 1;
1755 break;
1756 case MONO_TYPE_CHAR:
1757 case MONO_TYPE_U2:
1758 case MONO_TYPE_I2:
1759 len = 2;
1760 break;
1761 case MONO_TYPE_U4:
1762 case MONO_TYPE_I4:
1763 case MONO_TYPE_R4:
1764 len = 4;
1765 break;
1766 case MONO_TYPE_U8:
1767 case MONO_TYPE_I8:
1768 len = 8;
1769 break;
1770 case MONO_TYPE_R8:
1771 len = 8;
1772 #ifdef ARM_FPU_FPA
1773 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1774 fpa_p = (guint32*)box_val;
1775 fpa_double [0] = fpa_p [1];
1776 fpa_double [1] = fpa_p [0];
1777 box_val = (char*)fpa_double;
1778 #endif
1779 #endif
1780 break;
1781 case MONO_TYPE_VALUETYPE:
1782 if (val->vtable->klass->enumtype) {
1783 *ret_type = mono_class_enum_basetype (val->vtable->klass)->type;
1784 goto handle_enum;
1785 } else
1786 g_error ("we can't encode valuetypes");
1787 case MONO_TYPE_CLASS:
1788 break;
1789 case MONO_TYPE_STRING: {
1790 MonoString *str = (MonoString*)val;
1791 /* there is no signature */
1792 len = str->length * 2;
1793 mono_metadata_encode_value (len, b, &b);
1794 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1796 char *swapped = g_malloc (2 * mono_string_length (str));
1797 const char *p = (const char*)mono_string_chars (str);
1799 swap_with_size (swapped, p, 2, mono_string_length (str));
1800 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1801 g_free (swapped);
1803 #else
1804 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1805 #endif
1807 g_free (buf);
1808 return idx;
1810 case MONO_TYPE_GENERICINST:
1811 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
1812 goto handle_enum;
1813 default:
1814 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1817 /* there is no signature */
1818 mono_metadata_encode_value (len, b, &b);
1819 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1820 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1821 swap_with_size (blob_size, box_val, len, 1);
1822 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1823 #else
1824 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1825 #endif
1827 g_free (buf);
1828 return idx;
1831 static guint32
1832 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1833 char *str;
1834 SigBuffer buf;
1835 guint32 idx, len;
1837 sigbuffer_init (&buf, 32);
1839 sigbuffer_add_value (&buf, minfo->type);
1841 switch (minfo->type) {
1842 case MONO_NATIVE_BYVALTSTR:
1843 case MONO_NATIVE_BYVALARRAY:
1844 sigbuffer_add_value (&buf, minfo->count);
1845 break;
1846 case MONO_NATIVE_LPARRAY:
1847 if (minfo->eltype || minfo->has_size) {
1848 sigbuffer_add_value (&buf, minfo->eltype);
1849 if (minfo->has_size) {
1850 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
1851 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
1853 /* LAMESPEC: ElemMult is undocumented */
1854 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1857 break;
1858 case MONO_NATIVE_SAFEARRAY:
1859 if (minfo->eltype)
1860 sigbuffer_add_value (&buf, minfo->eltype);
1861 break;
1862 case MONO_NATIVE_CUSTOM:
1863 if (minfo->guid) {
1864 str = mono_string_to_utf8 (minfo->guid);
1865 len = strlen (str);
1866 sigbuffer_add_value (&buf, len);
1867 sigbuffer_add_mem (&buf, str, len);
1868 g_free (str);
1869 } else {
1870 sigbuffer_add_value (&buf, 0);
1872 /* native type name */
1873 sigbuffer_add_value (&buf, 0);
1874 /* custom marshaler type name */
1875 if (minfo->marshaltype || minfo->marshaltyperef) {
1876 if (minfo->marshaltyperef)
1877 str = type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
1878 else
1879 str = mono_string_to_utf8 (minfo->marshaltype);
1880 len = strlen (str);
1881 sigbuffer_add_value (&buf, len);
1882 sigbuffer_add_mem (&buf, str, len);
1883 g_free (str);
1884 } else {
1885 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
1886 sigbuffer_add_value (&buf, 0);
1888 if (minfo->mcookie) {
1889 str = mono_string_to_utf8 (minfo->mcookie);
1890 len = strlen (str);
1891 sigbuffer_add_value (&buf, len);
1892 sigbuffer_add_mem (&buf, str, len);
1893 g_free (str);
1894 } else {
1895 sigbuffer_add_value (&buf, 0);
1897 break;
1898 default:
1899 break;
1901 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1902 sigbuffer_free (&buf);
1903 return idx;
1906 static void
1907 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1909 MonoDynamicTable *table;
1910 guint32 *values;
1912 /* maybe this fixup should be done in the C# code */
1913 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1914 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1915 table = &assembly->tables [MONO_TABLE_FIELD];
1916 fb->table_idx = table->next_idx ++;
1917 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1918 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1919 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
1920 values [MONO_FIELD_FLAGS] = fb->attrs;
1921 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1923 if (fb->offset != -1) {
1924 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1925 table->rows ++;
1926 alloc_table (table, table->rows);
1927 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1928 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1929 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1931 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1932 guint32 field_type = 0;
1933 table = &assembly->tables [MONO_TABLE_CONSTANT];
1934 table->rows ++;
1935 alloc_table (table, table->rows);
1936 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1937 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1938 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1939 values [MONO_CONSTANT_TYPE] = field_type;
1940 values [MONO_CONSTANT_PADDING] = 0;
1942 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1943 guint32 rva_idx;
1944 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1945 table->rows ++;
1946 alloc_table (table, table->rows);
1947 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1948 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1950 * We store it in the code section because it's simpler for now.
1952 if (fb->rva_data) {
1953 if (mono_array_length (fb->rva_data) >= 10)
1954 stream_data_align (&assembly->code);
1955 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1956 } else
1957 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1958 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1960 if (fb->marshal_info) {
1961 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1962 table->rows ++;
1963 alloc_table (table, table->rows);
1964 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1965 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1966 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1970 static guint32
1971 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1973 SigBuffer buf;
1974 guint32 nparams = 0;
1975 MonoReflectionMethodBuilder *mb = fb->get_method;
1976 MonoReflectionMethodBuilder *smb = fb->set_method;
1977 guint32 idx, i;
1979 if (mb && mb->parameters)
1980 nparams = mono_array_length (mb->parameters);
1981 if (!mb && smb && smb->parameters)
1982 nparams = mono_array_length (smb->parameters) - 1;
1983 sigbuffer_init (&buf, 32);
1984 sigbuffer_add_byte (&buf, 0x08);
1985 sigbuffer_add_value (&buf, nparams);
1986 if (mb) {
1987 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf);
1988 for (i = 0; i < nparams; ++i) {
1989 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1990 encode_reflection_type (assembly, pt, &buf);
1992 } else if (smb && smb->parameters) {
1993 /* the property type is the last param */
1994 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
1995 for (i = 0; i < nparams; ++i) {
1996 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1997 encode_reflection_type (assembly, pt, &buf);
1999 } else {
2000 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
2003 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2004 sigbuffer_free (&buf);
2005 return idx;
2008 static void
2009 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
2011 MonoDynamicTable *table;
2012 guint32 *values;
2013 guint num_methods = 0;
2014 guint32 semaidx;
2017 * we need to set things in the following tables:
2018 * PROPERTYMAP (info already filled in _get_type_info ())
2019 * PROPERTY (rows already preallocated in _get_type_info ())
2020 * METHOD (method info already done with the generic method code)
2021 * METHODSEMANTICS
2022 * CONSTANT
2024 table = &assembly->tables [MONO_TABLE_PROPERTY];
2025 pb->table_idx = table->next_idx ++;
2026 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2027 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2028 values [MONO_PROPERTY_FLAGS] = pb->attrs;
2029 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
2031 /* FIXME: we still don't handle 'other' methods */
2032 if (pb->get_method) num_methods ++;
2033 if (pb->set_method) num_methods ++;
2035 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2036 table->rows += num_methods;
2037 alloc_table (table, table->rows);
2039 if (pb->get_method) {
2040 semaidx = table->next_idx ++;
2041 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2042 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2043 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2044 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2046 if (pb->set_method) {
2047 semaidx = table->next_idx ++;
2048 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2049 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2050 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2051 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2053 if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2054 guint32 field_type = 0;
2055 table = &assembly->tables [MONO_TABLE_CONSTANT];
2056 table->rows ++;
2057 alloc_table (table, table->rows);
2058 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2059 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2060 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2061 values [MONO_CONSTANT_TYPE] = field_type;
2062 values [MONO_CONSTANT_PADDING] = 0;
2066 static void
2067 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
2069 MonoDynamicTable *table;
2070 guint32 *values;
2071 guint num_methods = 0;
2072 guint32 semaidx;
2075 * we need to set things in the following tables:
2076 * EVENTMAP (info already filled in _get_type_info ())
2077 * EVENT (rows already preallocated in _get_type_info ())
2078 * METHOD (method info already done with the generic method code)
2079 * METHODSEMANTICS
2081 table = &assembly->tables [MONO_TABLE_EVENT];
2082 eb->table_idx = table->next_idx ++;
2083 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2084 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2085 values [MONO_EVENT_FLAGS] = eb->attrs;
2086 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (eb->type));
2089 * FIXME: we still don't handle 'other' methods
2091 if (eb->add_method) num_methods ++;
2092 if (eb->remove_method) num_methods ++;
2093 if (eb->raise_method) num_methods ++;
2095 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2096 table->rows += num_methods;
2097 alloc_table (table, table->rows);
2099 if (eb->add_method) {
2100 semaidx = table->next_idx ++;
2101 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2102 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2103 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2104 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2106 if (eb->remove_method) {
2107 semaidx = table->next_idx ++;
2108 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2109 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2110 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2111 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2113 if (eb->raise_method) {
2114 semaidx = table->next_idx ++;
2115 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2116 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2117 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2118 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2122 static void
2123 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2125 MonoDynamicTable *table;
2126 guint32 num_constraints, i;
2127 guint32 *values;
2128 guint32 table_idx;
2130 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2131 num_constraints = gparam->iface_constraints ?
2132 mono_array_length (gparam->iface_constraints) : 0;
2133 table->rows += num_constraints;
2134 if (gparam->base_type)
2135 table->rows++;
2136 alloc_table (table, table->rows);
2138 if (gparam->base_type) {
2139 table_idx = table->next_idx ++;
2140 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2142 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2143 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2144 assembly, mono_reflection_type_get_handle (gparam->base_type));
2147 for (i = 0; i < num_constraints; i++) {
2148 MonoReflectionType *constraint = mono_array_get (
2149 gparam->iface_constraints, gpointer, i);
2151 table_idx = table->next_idx ++;
2152 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2154 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2155 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2156 assembly, mono_reflection_type_get_handle (constraint));
2160 static void
2161 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2163 GenericParamTableEntry *entry;
2166 * The GenericParam table must be sorted according to the `owner' field.
2167 * We need to do this sorting prior to writing the GenericParamConstraint
2168 * table, since we have to use the final GenericParam table indices there
2169 * and they must also be sorted.
2172 entry = g_new0 (GenericParamTableEntry, 1);
2173 entry->owner = owner;
2174 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2175 MOVING_GC_REGISTER (&entry->gparam);
2176 entry->gparam = gparam;
2178 g_ptr_array_add (assembly->gen_params, entry);
2181 static void
2182 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2184 MonoDynamicTable *table;
2185 MonoGenericParam *param;
2186 guint32 *values;
2187 guint32 table_idx;
2189 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2190 table_idx = table->next_idx ++;
2191 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2193 param = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam)->data.generic_param;
2195 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2196 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2197 values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2198 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2200 mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2202 encode_constraints (entry->gparam, table_idx, assembly);
2205 static guint32
2206 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2208 MonoDynamicTable *table;
2209 guint32 token;
2210 guint32 *values;
2211 guint32 cols [MONO_ASSEMBLY_SIZE];
2212 const char *pubkey;
2213 guint32 publen;
2215 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2216 return token;
2218 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2219 table = &assembly->tables [MONO_TABLE_MODULEREF];
2220 token = table->next_idx ++;
2221 table->rows ++;
2222 alloc_table (table, table->rows);
2223 values = table->values + token * MONO_MODULEREF_SIZE;
2224 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2226 token <<= MONO_RESOLTION_SCOPE_BITS;
2227 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2228 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2230 return token;
2233 if (image->assembly->dynamic)
2234 /* FIXME: */
2235 memset (cols, 0, sizeof (cols));
2236 else {
2237 /* image->assembly->image is the manifest module */
2238 image = image->assembly->image;
2239 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2242 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2243 token = table->next_idx ++;
2244 table->rows ++;
2245 alloc_table (table, table->rows);
2246 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2247 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2248 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2249 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2250 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2251 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2252 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2253 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2254 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2256 if (strcmp ("", image->assembly->aname.culture)) {
2257 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2258 image->assembly->aname.culture);
2261 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2262 guchar pubtoken [9];
2263 pubtoken [0] = 8;
2264 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2265 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2266 } else {
2267 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2269 token <<= MONO_RESOLTION_SCOPE_BITS;
2270 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2271 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2272 return token;
2275 static guint32
2276 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2278 MonoDynamicTable *table;
2279 guint32 *values;
2280 guint32 token;
2281 SigBuffer buf;
2283 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2284 return token;
2286 sigbuffer_init (&buf, 32);
2287 switch (type->type) {
2288 case MONO_TYPE_FNPTR:
2289 case MONO_TYPE_PTR:
2290 case MONO_TYPE_SZARRAY:
2291 case MONO_TYPE_ARRAY:
2292 case MONO_TYPE_VAR:
2293 case MONO_TYPE_MVAR:
2294 case MONO_TYPE_GENERICINST:
2295 encode_type (assembly, type, &buf);
2296 break;
2297 case MONO_TYPE_CLASS:
2298 case MONO_TYPE_VALUETYPE: {
2299 MonoClass *k = mono_class_from_mono_type (type);
2300 if (!k || !k->generic_container) {
2301 sigbuffer_free (&buf);
2302 return 0;
2304 encode_type (assembly, type, &buf);
2305 break;
2307 default:
2308 sigbuffer_free (&buf);
2309 return 0;
2312 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2313 if (assembly->save) {
2314 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2315 alloc_table (table, table->rows + 1);
2316 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2317 values [MONO_TYPESPEC_SIGNATURE] = token;
2319 sigbuffer_free (&buf);
2321 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2322 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2323 table->next_idx ++;
2324 return token;
2327 static guint32
2328 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2330 MonoDynamicTable *table;
2331 guint32 *values;
2332 guint32 token, scope, enclosing;
2333 MonoClass *klass;
2335 /* if the type requires a typespec, we must try that first*/
2336 if (try_typespec && (token = create_typespec (assembly, type)))
2337 return token;
2338 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2339 if (token)
2340 return token;
2341 klass = mono_class_from_mono_type (type);
2342 if (!klass)
2343 klass = mono_class_from_mono_type (type);
2346 * If it's in the same module and not a generic type parameter:
2348 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2349 (type->type != MONO_TYPE_MVAR)) {
2350 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
2351 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2352 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), mono_class_get_ref_info (klass));
2353 return token;
2356 if (klass->nested_in) {
2357 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2358 /* get the typeref idx of the enclosing type */
2359 enclosing >>= MONO_TYPEDEFORREF_BITS;
2360 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2361 } else {
2362 scope = resolution_scope_from_image (assembly, klass->image);
2364 table = &assembly->tables [MONO_TABLE_TYPEREF];
2365 if (assembly->save) {
2366 alloc_table (table, table->rows + 1);
2367 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2368 values [MONO_TYPEREF_SCOPE] = scope;
2369 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2370 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2372 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2373 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2374 table->next_idx ++;
2375 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), mono_class_get_ref_info (klass));
2376 return token;
2380 * Despite the name, we handle also TypeSpec (with the above helper).
2382 static guint32
2383 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2385 return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2388 #ifndef DISABLE_REFLECTION_EMIT
2389 static guint32
2390 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2392 MonoDynamicTable *table;
2393 guint32 *values;
2394 guint32 token, pclass;
2396 switch (parent & MONO_TYPEDEFORREF_MASK) {
2397 case MONO_TYPEDEFORREF_TYPEREF:
2398 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2399 break;
2400 case MONO_TYPEDEFORREF_TYPESPEC:
2401 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2402 break;
2403 case MONO_TYPEDEFORREF_TYPEDEF:
2404 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2405 break;
2406 default:
2407 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2408 return 0;
2410 /* extract the index */
2411 parent >>= MONO_TYPEDEFORREF_BITS;
2413 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2415 if (assembly->save) {
2416 alloc_table (table, table->rows + 1);
2417 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2418 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2419 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2420 values [MONO_MEMBERREF_SIGNATURE] = sig;
2423 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2424 table->next_idx ++;
2426 return token;
2430 * Insert a memberef row into the metadata: the token that point to the memberref
2431 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2432 * mono_image_get_fieldref_token()).
2433 * The sig param is an index to an already built signature.
2435 static guint32
2436 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2438 guint32 parent = mono_image_typedef_or_ref (assembly, type);
2439 return mono_image_add_memberef_row (assembly, parent, name, sig);
2443 static guint32
2444 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2446 guint32 token;
2447 MonoMethodSignature *sig;
2449 create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2451 if (create_typespec) {
2452 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2453 if (token)
2454 return token;
2457 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2458 if (token && !create_typespec)
2459 return token;
2461 g_assert (!method->is_inflated);
2462 if (!token) {
2464 * A methodref signature can't contain an unmanaged calling convention.
2466 sig = mono_metadata_signature_dup (mono_method_signature (method));
2467 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2468 sig->call_convention = MONO_CALL_DEFAULT;
2469 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2470 method->name, method_encode_signature (assembly, sig));
2471 g_free (sig);
2472 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2475 if (create_typespec) {
2476 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2477 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2478 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2480 if (assembly->save) {
2481 guint32 *values;
2483 alloc_table (table, table->rows + 1);
2484 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2485 values [MONO_METHODSPEC_METHOD] = token;
2486 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2489 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2490 table->next_idx ++;
2491 /*methodspec and memberef tokens are diferent, */
2492 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2493 return token;
2495 return token;
2498 static guint32
2499 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2501 guint32 token, parent, sig;
2502 ReflectionMethodBuilder rmb;
2503 char *name;
2504 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2506 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2507 if (token)
2508 return token;
2510 name = mono_string_to_utf8 (method->name);
2511 reflection_methodbuilder_from_method_builder (&rmb, method);
2514 * A methodref signature can't contain an unmanaged calling convention.
2515 * Since some flags are encoded as part of call_conv, we need to check against it.
2517 if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2518 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2520 sig = method_builder_encode_signature (assembly, &rmb);
2522 if (tb->generic_params)
2523 parent = create_generic_typespec (assembly, tb);
2524 else
2525 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type));
2527 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2529 g_free (name);
2530 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2531 return token;
2534 static guint32
2535 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2536 const gchar *name, guint32 sig)
2538 MonoDynamicTable *table;
2539 guint32 token;
2540 guint32 *values;
2542 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2544 if (assembly->save) {
2545 alloc_table (table, table->rows + 1);
2546 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2547 values [MONO_MEMBERREF_CLASS] = original;
2548 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2549 values [MONO_MEMBERREF_SIGNATURE] = sig;
2552 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2553 table->next_idx ++;
2555 return token;
2558 static guint32
2559 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2561 SigBuffer buf;
2562 int i;
2563 guint32 nparams = mono_array_length (mb->generic_params);
2564 guint32 idx;
2566 if (!assembly->save)
2567 return 0;
2569 sigbuffer_init (&buf, 32);
2571 sigbuffer_add_value (&buf, 0xa);
2572 sigbuffer_add_value (&buf, nparams);
2574 for (i = 0; i < nparams; i++) {
2575 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2576 sigbuffer_add_value (&buf, i);
2579 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2580 sigbuffer_free (&buf);
2581 return idx;
2584 static guint32
2585 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2587 MonoDynamicTable *table;
2588 guint32 *values;
2589 guint32 token, mtoken = 0;
2591 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2592 if (token)
2593 return token;
2595 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2597 mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2598 switch (mono_metadata_token_table (mtoken)) {
2599 case MONO_TABLE_MEMBERREF:
2600 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2601 break;
2602 case MONO_TABLE_METHOD:
2603 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2604 break;
2605 default:
2606 g_assert_not_reached ();
2609 if (assembly->save) {
2610 alloc_table (table, table->rows + 1);
2611 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2612 values [MONO_METHODSPEC_METHOD] = mtoken;
2613 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2616 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2617 table->next_idx ++;
2619 mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2620 return token;
2623 static guint32
2624 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2626 guint32 token;
2628 if (mb->generic_params && create_methodspec)
2629 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2631 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2632 if (token)
2633 return token;
2635 token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2636 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2637 return token;
2640 static guint32
2641 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2643 guint32 token, parent, sig;
2644 ReflectionMethodBuilder rmb;
2645 char *name;
2646 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
2648 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2649 if (token)
2650 return token;
2652 g_assert (tb->generic_params);
2654 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2656 parent = create_generic_typespec (assembly, tb);
2657 name = mono_string_to_utf8 (rmb.name);
2658 sig = method_builder_encode_signature (assembly, &rmb);
2660 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2662 g_free (name);
2663 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2664 return token;
2666 #endif
2668 static gboolean
2669 is_field_on_inst (MonoClassField *field)
2671 return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2675 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2677 static MonoType*
2678 get_field_on_inst_generic_type (MonoClassField *field)
2680 MonoClass *class, *gtd;
2681 MonoDynamicGenericClass *dgclass;
2682 int field_index;
2684 g_assert (is_field_on_inst (field));
2686 dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2688 if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
2689 field_index = field - dgclass->fields;
2690 return dgclass->field_generic_types [field_index];
2693 class = field->parent;
2694 gtd = class->generic_class->container_class;
2696 if (field >= class->fields && field - class->fields < class->field.count) {
2697 field_index = field - class->fields;
2698 return gtd->fields [field_index].type;
2701 g_assert_not_reached ();
2702 return 0;
2705 #ifndef DISABLE_REFLECTION_EMIT
2706 static guint32
2707 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2709 MonoType *type;
2710 guint32 token;
2711 MonoClassField *field;
2713 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2714 if (token)
2715 return token;
2716 g_assert (f->field->parent);
2718 field = f->field;
2719 if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2720 int index = field - field->parent->fields;
2721 type = field->parent->generic_class->container_class->fields [index].type;
2722 } else {
2723 if (is_field_on_inst (f->field))
2724 type = get_field_on_inst_generic_type (f->field);
2725 else
2726 type = f->field->type;
2728 token = mono_image_get_memberref_token (assembly, &f->field->parent->byval_arg,
2729 mono_field_get_name (f->field),
2730 fieldref_encode_signature (assembly, field->parent->image, type));
2731 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
2732 return token;
2735 static guint32
2736 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
2738 guint32 token;
2739 MonoClass *klass;
2740 MonoGenericClass *gclass;
2741 MonoDynamicGenericClass *dgclass;
2742 MonoType *type;
2743 char *name;
2745 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2746 if (token)
2747 return token;
2748 if (is_sre_field_builder (mono_object_class (f->fb))) {
2749 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
2750 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2751 klass = mono_class_from_mono_type (type);
2752 gclass = type->data.generic_class;
2753 g_assert (gclass->is_dynamic);
2754 dgclass = (MonoDynamicGenericClass *) gclass;
2756 name = mono_string_to_utf8 (fb->name);
2757 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name,
2758 field_encode_signature (assembly, fb));
2759 g_free (name);
2760 } else if (is_sr_mono_field (mono_object_class (f->fb))) {
2761 guint32 sig;
2762 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
2764 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2765 klass = mono_class_from_mono_type (type);
2767 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
2768 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
2769 } else {
2770 char *name = mono_type_get_full_name (mono_object_class (f->fb));
2771 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
2774 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
2775 return token;
2778 static guint32
2779 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
2781 guint32 sig, token;
2782 MonoClass *klass;
2783 MonoGenericClass *gclass;
2784 MonoType *type;
2786 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
2788 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
2789 if (token)
2790 return token;
2792 if (is_sre_ctor_builder (mono_object_class (c->cb))) {
2793 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
2794 MonoDynamicGenericClass *dgclass;
2795 ReflectionMethodBuilder rmb;
2796 char *name;
2798 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2799 klass = mono_class_from_mono_type (type);
2801 gclass = type->data.generic_class;
2802 g_assert (gclass->is_dynamic);
2803 dgclass = (MonoDynamicGenericClass *) gclass;
2805 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
2807 name = mono_string_to_utf8 (rmb.name);
2809 sig = method_builder_encode_signature (assembly, &rmb);
2811 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2812 g_free (name);
2813 } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
2814 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
2816 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2817 klass = mono_class_from_mono_type (type);
2819 sig = method_encode_signature (assembly, mono_method_signature (mm));
2820 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2821 } else {
2822 char *name = mono_type_get_full_name (mono_object_class (c->cb));
2823 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2827 mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
2828 return token;
2831 static MonoMethod*
2832 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m)
2834 MonoClass *klass;
2835 MonoGenericContext tmp_context;
2836 MonoType **type_argv;
2837 MonoGenericInst *ginst;
2838 MonoMethod *method, *inflated;
2839 int count, i;
2841 method = inflate_method (m->inst, (MonoObject*)m->mb);
2843 klass = method->klass;
2845 if (m->method_args == NULL)
2846 return method;
2848 if (method->is_inflated)
2849 method = ((MonoMethodInflated *) method)->declaring;
2851 count = mono_array_length (m->method_args);
2853 type_argv = g_new0 (MonoType *, count);
2854 for (i = 0; i < count; i++) {
2855 MonoReflectionType *garg = mono_array_get (m->method_args, gpointer, i);
2856 type_argv [i] = mono_reflection_type_get_handle (garg);
2858 ginst = mono_metadata_get_generic_inst (count, type_argv);
2859 g_free (type_argv);
2861 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
2862 tmp_context.method_inst = ginst;
2864 inflated = mono_class_inflate_generic_method (method, &tmp_context);
2865 return inflated;
2868 static guint32
2869 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
2871 guint32 sig, token = 0;
2872 MonoType *type;
2873 MonoClass *klass;
2875 if (m->method_args) {
2876 MonoMethod *inflated;
2878 inflated = mono_reflection_method_on_tb_inst_get_handle (m);
2879 if (create_methodspec)
2880 token = mono_image_get_methodspec_token (assembly, inflated);
2881 else
2882 token = mono_image_get_inflated_method_token (assembly, inflated);
2883 return token;
2886 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
2887 if (token)
2888 return token;
2890 if (is_sre_method_builder (mono_object_class (m->mb))) {
2891 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
2892 MonoGenericClass *gclass;
2893 ReflectionMethodBuilder rmb;
2894 char *name;
2896 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2897 klass = mono_class_from_mono_type (type);
2898 gclass = type->data.generic_class;
2899 g_assert (gclass->is_dynamic);
2901 reflection_methodbuilder_from_method_builder (&rmb, mb);
2903 name = mono_string_to_utf8 (rmb.name);
2905 sig = method_builder_encode_signature (assembly, &rmb);
2907 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2908 g_free (name);
2909 } else if (is_sr_mono_method (mono_object_class (m->mb))) {
2910 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
2912 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2913 klass = mono_class_from_mono_type (type);
2915 sig = method_encode_signature (assembly, mono_method_signature (mm));
2916 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2917 } else {
2918 char *name = mono_type_get_full_name (mono_object_class (m->mb));
2919 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2922 mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
2923 return token;
2926 static guint32
2927 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
2929 SigBuffer buf;
2930 int i;
2931 guint32 nparams = context->method_inst->type_argc;
2932 guint32 idx;
2934 if (!assembly->save)
2935 return 0;
2937 sigbuffer_init (&buf, 32);
2939 * FIXME: vararg, explicit_this, differenc call_conv values...
2941 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
2942 sigbuffer_add_value (&buf, nparams);
2944 for (i = 0; i < nparams; i++)
2945 encode_type (assembly, context->method_inst->type_argv [i], &buf);
2947 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2948 sigbuffer_free (&buf);
2949 return idx;
2952 static guint32
2953 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2955 MonoDynamicTable *table;
2956 guint32 *values;
2957 guint32 token, mtoken = 0, sig;
2958 MonoMethodInflated *imethod;
2959 MonoMethod *declaring;
2961 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2963 g_assert (method->is_inflated);
2964 imethod = (MonoMethodInflated *) method;
2965 declaring = imethod->declaring;
2967 sig = method_encode_signature (assembly, mono_method_signature (declaring));
2968 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2970 if (!mono_method_signature (declaring)->generic_param_count)
2971 return mtoken;
2973 switch (mono_metadata_token_table (mtoken)) {
2974 case MONO_TABLE_MEMBERREF:
2975 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2976 break;
2977 case MONO_TABLE_METHOD:
2978 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2979 break;
2980 default:
2981 g_assert_not_reached ();
2984 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
2986 if (assembly->save) {
2987 alloc_table (table, table->rows + 1);
2988 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2989 values [MONO_METHODSPEC_METHOD] = mtoken;
2990 values [MONO_METHODSPEC_SIGNATURE] = sig;
2993 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2994 table->next_idx ++;
2996 return token;
2999 static guint32
3000 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3002 MonoMethodInflated *imethod;
3003 guint32 token;
3005 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3006 if (token)
3007 return token;
3009 g_assert (method->is_inflated);
3010 imethod = (MonoMethodInflated *) method;
3012 if (mono_method_signature (imethod->declaring)->generic_param_count) {
3013 token = method_encode_methodspec (assembly, method);
3014 } else {
3015 guint32 sig = method_encode_signature (
3016 assembly, mono_method_signature (imethod->declaring));
3017 token = mono_image_get_memberref_token (
3018 assembly, &method->klass->byval_arg, method->name, sig);
3021 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3022 return token;
3025 static guint32
3026 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3028 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3029 guint32 sig, token;
3031 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3032 token = mono_image_get_memberref_token (
3033 assembly, &m->klass->byval_arg, m->name, sig);
3035 return token;
3038 static guint32
3039 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
3041 MonoDynamicTable *table;
3042 MonoClass *klass;
3043 MonoType *type;
3044 guint32 *values;
3045 guint32 token;
3046 SigBuffer buf;
3047 int count, i;
3050 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3051 * ie. what we'd normally use as the generic type in a TypeSpec signature.
3052 * Because of this, we must not insert it into the `typeref' hash table.
3054 type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
3055 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3056 if (token)
3057 return token;
3059 sigbuffer_init (&buf, 32);
3061 g_assert (tb->generic_params);
3062 klass = mono_class_from_mono_type (type);
3064 if (tb->generic_container)
3065 mono_reflection_create_generic_class (tb);
3067 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3068 g_assert (klass->generic_container);
3069 sigbuffer_add_value (&buf, klass->byval_arg.type);
3070 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3072 count = mono_array_length (tb->generic_params);
3073 sigbuffer_add_value (&buf, count);
3074 for (i = 0; i < count; i++) {
3075 MonoReflectionGenericParam *gparam;
3077 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3079 encode_type (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)gparam), &buf);
3082 table = &assembly->tables [MONO_TABLE_TYPESPEC];
3084 if (assembly->save) {
3085 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3086 alloc_table (table, table->rows + 1);
3087 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3088 values [MONO_TYPESPEC_SIGNATURE] = token;
3090 sigbuffer_free (&buf);
3092 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3093 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3094 table->next_idx ++;
3095 return token;
3099 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3101 static MonoType*
3102 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
3104 int i, count, len, pos;
3105 MonoType *t;
3107 count = 0;
3108 if (modreq)
3109 count += mono_array_length (modreq);
3110 if (modopt)
3111 count += mono_array_length (modopt);
3113 if (count == 0)
3114 return mono_metadata_type_dup (NULL, type);
3116 len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3117 t = g_malloc (len);
3118 memcpy (t, type, MONO_SIZEOF_TYPE);
3120 t->num_mods = count;
3121 pos = 0;
3122 if (modreq) {
3123 for (i = 0; i < mono_array_length (modreq); ++i) {
3124 MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
3125 t->modifiers [pos].required = 1;
3126 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3127 pos ++;
3130 if (modopt) {
3131 for (i = 0; i < mono_array_length (modopt); ++i) {
3132 MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
3133 t->modifiers [pos].required = 0;
3134 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3135 pos ++;
3139 return t;
3142 static guint32
3143 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3145 MonoDynamicTable *table;
3146 MonoClass *klass;
3147 MonoType *custom = NULL;
3148 guint32 *values;
3149 guint32 token, pclass, parent, sig;
3150 gchar *name;
3152 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3153 if (token)
3154 return token;
3156 klass = mono_class_from_mono_type (mono_reflection_type_get_handle (fb->typeb));
3157 name = mono_string_to_utf8 (fb->name);
3159 /* fb->type does not include the custom modifiers */
3160 /* FIXME: We should do this in one place when a fieldbuilder is created */
3161 if (fb->modreq || fb->modopt) {
3162 custom = add_custom_modifiers (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type), fb->modreq, fb->modopt);
3163 sig = fieldref_encode_signature (assembly, NULL, custom);
3164 g_free (custom);
3165 } else {
3166 sig = fieldref_encode_signature (assembly, NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
3169 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3170 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3172 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3173 parent >>= MONO_TYPEDEFORREF_BITS;
3175 table = &assembly->tables [MONO_TABLE_MEMBERREF];
3177 if (assembly->save) {
3178 alloc_table (table, table->rows + 1);
3179 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3180 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3181 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3182 values [MONO_MEMBERREF_SIGNATURE] = sig;
3185 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3186 table->next_idx ++;
3187 mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3188 g_free (name);
3189 return token;
3192 static guint32
3193 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3195 SigBuffer buf;
3196 guint32 nargs;
3197 guint32 size;
3198 guint32 i, idx;
3200 if (!assembly->save)
3201 return 0;
3203 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3204 g_assert (helper->type == 2);
3206 if (helper->arguments)
3207 nargs = mono_array_length (helper->arguments);
3208 else
3209 nargs = 0;
3211 size = 10 + (nargs * 10);
3213 sigbuffer_init (&buf, 32);
3215 /* Encode calling convention */
3216 /* Change Any to Standard */
3217 if ((helper->call_conv & 0x03) == 0x03)
3218 helper->call_conv = 0x01;
3219 /* explicit_this implies has_this */
3220 if (helper->call_conv & 0x40)
3221 helper->call_conv &= 0x20;
3223 if (helper->call_conv == 0) { /* Unmanaged */
3224 idx = helper->unmanaged_call_conv - 1;
3225 } else {
3226 /* Managed */
3227 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3228 if (helper->call_conv & 0x02) /* varargs */
3229 idx += 0x05;
3232 sigbuffer_add_byte (&buf, idx);
3233 sigbuffer_add_value (&buf, nargs);
3234 encode_reflection_type (assembly, helper->return_type, &buf);
3235 for (i = 0; i < nargs; ++i) {
3236 MonoArray *modreqs = NULL;
3237 MonoArray *modopts = NULL;
3238 MonoReflectionType *pt;
3240 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3241 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3242 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3243 modopts = mono_array_get (helper->modopts, MonoArray*, i);
3245 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3246 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3247 encode_reflection_type (assembly, pt, &buf);
3249 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3250 sigbuffer_free (&buf);
3252 return idx;
3255 static guint32
3256 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3258 guint32 idx;
3259 MonoDynamicTable *table;
3260 guint32 *values;
3262 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3263 idx = table->next_idx ++;
3264 table->rows ++;
3265 alloc_table (table, table->rows);
3266 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3268 values [MONO_STAND_ALONE_SIGNATURE] =
3269 mono_reflection_encode_sighelper (assembly, helper);
3271 return idx;
3274 static int
3275 reflection_cc_to_file (int call_conv) {
3276 switch (call_conv & 0x3) {
3277 case 0:
3278 case 1: return MONO_CALL_DEFAULT;
3279 case 2: return MONO_CALL_VARARG;
3280 default:
3281 g_assert_not_reached ();
3283 return 0;
3285 #endif /* !DISABLE_REFLECTION_EMIT */
3287 typedef struct {
3288 MonoType *parent;
3289 MonoMethodSignature *sig;
3290 char *name;
3291 guint32 token;
3292 } ArrayMethod;
3294 #ifndef DISABLE_REFLECTION_EMIT
3295 static guint32
3296 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3298 guint32 nparams, i;
3299 GList *tmp;
3300 char *name;
3301 MonoMethodSignature *sig;
3302 ArrayMethod *am;
3303 MonoType *mtype;
3305 name = mono_string_to_utf8 (m->name);
3306 nparams = mono_array_length (m->parameters);
3307 sig = g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3308 sig->hasthis = 1;
3309 sig->sentinelpos = -1;
3310 sig->call_convention = reflection_cc_to_file (m->call_conv);
3311 sig->param_count = nparams;
3312 sig->ret = m->ret ? mono_reflection_type_get_handle (m->ret): &mono_defaults.void_class->byval_arg;
3313 mtype = mono_reflection_type_get_handle (m->parent);
3314 for (i = 0; i < nparams; ++i)
3315 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i);
3317 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3318 am = tmp->data;
3319 if (strcmp (name, am->name) == 0 &&
3320 mono_metadata_type_equal (am->parent, mtype) &&
3321 mono_metadata_signature_equal (am->sig, sig)) {
3322 g_free (name);
3323 g_free (sig);
3324 m->table_idx = am->token & 0xffffff;
3325 return am->token;
3328 am = g_new0 (ArrayMethod, 1);
3329 am->name = name;
3330 am->sig = sig;
3331 am->parent = mtype;
3332 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3333 method_encode_signature (assembly, sig));
3334 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3335 m->table_idx = am->token & 0xffffff;
3336 return am->token;
3340 * Insert into the metadata tables all the info about the TypeBuilder tb.
3341 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3343 static void
3344 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3346 MonoDynamicTable *table;
3347 guint *values;
3348 int i, is_object = 0, is_system = 0;
3349 char *n;
3351 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3352 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3353 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3354 n = mono_string_to_utf8 (tb->name);
3355 if (strcmp (n, "Object") == 0)
3356 is_object++;
3357 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3358 g_free (n);
3359 n = mono_string_to_utf8 (tb->nspace);
3360 if (strcmp (n, "System") == 0)
3361 is_system++;
3362 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3363 g_free (n);
3364 if (tb->parent && !(is_system && is_object) &&
3365 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3366 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
3367 } else {
3368 values [MONO_TYPEDEF_EXTENDS] = 0;
3370 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3371 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3374 * if we have explicitlayout or sequentiallayouts, output data in the
3375 * ClassLayout table.
3377 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3378 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3379 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3380 table->rows++;
3381 alloc_table (table, table->rows);
3382 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3383 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3384 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3385 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3388 /* handle interfaces */
3389 if (tb->interfaces) {
3390 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3391 i = table->rows;
3392 table->rows += mono_array_length (tb->interfaces);
3393 alloc_table (table, table->rows);
3394 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3395 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3396 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3397 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3398 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (iface));
3399 values += MONO_INTERFACEIMPL_SIZE;
3403 /* handle fields */
3404 if (tb->fields) {
3405 table = &assembly->tables [MONO_TABLE_FIELD];
3406 table->rows += tb->num_fields;
3407 alloc_table (table, table->rows);
3408 for (i = 0; i < tb->num_fields; ++i)
3409 mono_image_get_field_info (
3410 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3413 /* handle constructors */
3414 if (tb->ctors) {
3415 table = &assembly->tables [MONO_TABLE_METHOD];
3416 table->rows += mono_array_length (tb->ctors);
3417 alloc_table (table, table->rows);
3418 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3419 mono_image_get_ctor_info (domain,
3420 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3423 /* handle methods */
3424 if (tb->methods) {
3425 table = &assembly->tables [MONO_TABLE_METHOD];
3426 table->rows += tb->num_methods;
3427 alloc_table (table, table->rows);
3428 for (i = 0; i < tb->num_methods; ++i)
3429 mono_image_get_method_info (
3430 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3433 /* Do the same with properties etc.. */
3434 if (tb->events && mono_array_length (tb->events)) {
3435 table = &assembly->tables [MONO_TABLE_EVENT];
3436 table->rows += mono_array_length (tb->events);
3437 alloc_table (table, table->rows);
3438 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3439 table->rows ++;
3440 alloc_table (table, table->rows);
3441 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3442 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3443 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3444 for (i = 0; i < mono_array_length (tb->events); ++i)
3445 mono_image_get_event_info (
3446 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3448 if (tb->properties && mono_array_length (tb->properties)) {
3449 table = &assembly->tables [MONO_TABLE_PROPERTY];
3450 table->rows += mono_array_length (tb->properties);
3451 alloc_table (table, table->rows);
3452 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3453 table->rows ++;
3454 alloc_table (table, table->rows);
3455 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3456 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3457 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3458 for (i = 0; i < mono_array_length (tb->properties); ++i)
3459 mono_image_get_property_info (
3460 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3463 /* handle generic parameters */
3464 if (tb->generic_params) {
3465 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3466 table->rows += mono_array_length (tb->generic_params);
3467 alloc_table (table, table->rows);
3468 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3469 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3471 mono_image_get_generic_param_info (
3472 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3476 mono_image_add_decl_security (assembly,
3477 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3479 if (tb->subtypes) {
3480 MonoDynamicTable *ntable;
3482 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3483 ntable->rows += mono_array_length (tb->subtypes);
3484 alloc_table (ntable, ntable->rows);
3485 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3487 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3488 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3490 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3491 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3492 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3493 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3494 mono_string_to_utf8 (tb->name), tb->table_idx,
3495 ntable->next_idx, ntable->rows);*/
3496 values += MONO_NESTED_CLASS_SIZE;
3497 ntable->next_idx++;
3501 #endif
3503 static void
3504 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
3506 int i;
3508 g_ptr_array_add (types, type); /* FIXME: GC object added to unmanaged memory */
3510 if (!type->subtypes)
3511 return;
3513 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3514 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3515 collect_types (types, subtype);
3519 static gint
3520 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3522 if ((*type1)->table_idx < (*type2)->table_idx)
3523 return -1;
3524 else
3525 if ((*type1)->table_idx > (*type2)->table_idx)
3526 return 1;
3527 else
3528 return 0;
3531 static void
3532 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3533 int i;
3535 if (!pinfo)
3536 return;
3537 for (i = 0; i < mono_array_length (pinfo); ++i) {
3538 MonoReflectionParamBuilder *pb;
3539 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3540 if (!pb)
3541 continue;
3542 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3546 static void
3547 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3548 int i;
3550 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3551 if (tb->fields) {
3552 for (i = 0; i < tb->num_fields; ++i) {
3553 MonoReflectionFieldBuilder* fb;
3554 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3555 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3558 if (tb->events) {
3559 for (i = 0; i < mono_array_length (tb->events); ++i) {
3560 MonoReflectionEventBuilder* eb;
3561 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3562 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3565 if (tb->properties) {
3566 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3567 MonoReflectionPropertyBuilder* pb;
3568 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3569 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3572 if (tb->ctors) {
3573 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3574 MonoReflectionCtorBuilder* cb;
3575 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3576 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3577 params_add_cattrs (assembly, cb->pinfo);
3581 if (tb->methods) {
3582 for (i = 0; i < tb->num_methods; ++i) {
3583 MonoReflectionMethodBuilder* mb;
3584 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3585 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3586 params_add_cattrs (assembly, mb->pinfo);
3590 if (tb->subtypes) {
3591 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3592 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3596 static void
3597 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3599 int i;
3601 mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3603 if (moduleb->global_methods) {
3604 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3605 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3606 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3607 params_add_cattrs (assembly, mb->pinfo);
3611 if (moduleb->global_fields) {
3612 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3613 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3614 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3618 if (moduleb->types) {
3619 for (i = 0; i < moduleb->num_types; ++i)
3620 type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3624 static void
3625 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3627 MonoDynamicTable *table;
3628 guint32 *values;
3629 char blob_size [6];
3630 guchar hash [20];
3631 char *b = blob_size;
3632 char *dir, *path;
3634 table = &assembly->tables [MONO_TABLE_FILE];
3635 table->rows++;
3636 alloc_table (table, table->rows);
3637 values = table->values + table->next_idx * MONO_FILE_SIZE;
3638 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3639 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3640 if (module->image->dynamic) {
3641 /* This depends on the fact that the main module is emitted last */
3642 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3643 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3644 } else {
3645 dir = NULL;
3646 path = g_strdup (module->image->name);
3648 mono_sha1_get_digest_from_file (path, hash);
3649 g_free (dir);
3650 g_free (path);
3651 mono_metadata_encode_value (20, b, &b);
3652 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3653 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3654 table->next_idx ++;
3657 static void
3658 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3660 MonoDynamicTable *table;
3661 int i;
3663 table = &assembly->tables [MONO_TABLE_MODULE];
3664 mb->table_idx = table->next_idx ++;
3665 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3666 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3667 i /= 16;
3668 ++i;
3669 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3670 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3671 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3672 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3675 static guint32
3676 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3677 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3679 MonoDynamicTable *table;
3680 guint32 *values;
3681 guint32 visib, res;
3683 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3684 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3685 return 0;
3687 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3688 table->rows++;
3689 alloc_table (table, table->rows);
3690 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3692 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3693 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3694 if (klass->nested_in)
3695 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3696 else
3697 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3698 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3699 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3701 res = table->next_idx;
3703 table->next_idx ++;
3705 /* Emit nested types */
3706 if (klass->ext && klass->ext->nested_classes) {
3707 GList *tmp;
3709 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
3710 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3713 return res;
3716 static void
3717 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3718 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3720 MonoClass *klass;
3721 guint32 idx, i;
3723 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
3725 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3727 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3728 parent_index, assembly);
3731 * Emit nested types
3732 * We need to do this ourselves since klass->nested_classes is not set up.
3734 if (tb->subtypes) {
3735 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3736 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3740 static void
3741 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3742 guint32 module_index, MonoDynamicImage *assembly)
3744 MonoImage *image = module->image;
3745 MonoTableInfo *t;
3746 guint32 i;
3748 t = &image->tables [MONO_TABLE_TYPEDEF];
3750 for (i = 0; i < t->rows; ++i) {
3751 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3753 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3754 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3758 static void
3759 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
3761 MonoDynamicTable *table;
3762 guint32 *values;
3763 guint32 scope, scope_idx, impl, current_idx;
3764 gboolean forwarder = TRUE;
3765 gpointer iter = NULL;
3766 MonoClass *nested;
3768 if (klass->nested_in) {
3769 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3770 forwarder = FALSE;
3771 } else {
3772 scope = resolution_scope_from_image (assembly, klass->image);
3773 g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3774 scope_idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3775 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3778 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3780 table->rows++;
3781 alloc_table (table, table->rows);
3782 current_idx = table->next_idx;
3783 values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
3785 values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
3786 values [MONO_EXP_TYPE_TYPEDEF] = 0;
3787 values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
3788 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3789 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3791 table->next_idx++;
3793 while ((nested = mono_class_get_nested_types (klass, &iter)))
3794 add_exported_type (assemblyb, assembly, nested, current_idx);
3797 static void
3798 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3800 MonoClass *klass;
3801 int i;
3803 if (!assemblyb->type_forwarders)
3804 return;
3806 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3807 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
3808 MonoType *type;
3809 if (!t)
3810 continue;
3812 type = mono_reflection_type_get_handle (t);
3813 g_assert (type);
3815 klass = mono_class_from_mono_type (type);
3817 add_exported_type (assemblyb, assembly, klass, 0);
3821 #define align_pointer(base,p)\
3822 do {\
3823 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3824 if (__diff & 3)\
3825 (p) += 4 - (__diff & 3);\
3826 } while (0)
3828 static int
3829 compare_constants (const void *a, const void *b)
3831 const guint32 *a_values = a;
3832 const guint32 *b_values = b;
3833 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3836 static int
3837 compare_semantics (const void *a, const void *b)
3839 const guint32 *a_values = a;
3840 const guint32 *b_values = b;
3841 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3842 if (assoc)
3843 return assoc;
3844 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3847 static int
3848 compare_custom_attrs (const void *a, const void *b)
3850 const guint32 *a_values = a;
3851 const guint32 *b_values = b;
3853 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3856 static int
3857 compare_field_marshal (const void *a, const void *b)
3859 const guint32 *a_values = a;
3860 const guint32 *b_values = b;
3862 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3865 static int
3866 compare_nested (const void *a, const void *b)
3868 const guint32 *a_values = a;
3869 const guint32 *b_values = b;
3871 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3874 static int
3875 compare_genericparam (const void *a, const void *b)
3877 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3878 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3880 if ((*b_entry)->owner == (*a_entry)->owner)
3881 return
3882 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam)) -
3883 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam));
3884 else
3885 return (*a_entry)->owner - (*b_entry)->owner;
3888 static int
3889 compare_declsecurity_attrs (const void *a, const void *b)
3891 const guint32 *a_values = a;
3892 const guint32 *b_values = b;
3894 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3897 static int
3898 compare_interface_impl (const void *a, const void *b)
3900 const guint32 *a_values = a;
3901 const guint32 *b_values = b;
3903 int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
3904 if (klass)
3905 return klass;
3907 return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
3910 static void
3911 pad_heap (MonoDynamicStream *sh)
3913 if (sh->index & 3) {
3914 int sz = 4 - (sh->index & 3);
3915 memset (sh->data + sh->index, 0, sz);
3916 sh->index += sz;
3920 struct StreamDesc {
3921 const char *name;
3922 MonoDynamicStream *stream;
3926 * build_compressed_metadata() fills in the blob of data that represents the
3927 * raw metadata as it will be saved in the PE file. The five streams are output
3928 * and the metadata tables are comnpressed from the guint32 array representation,
3929 * to the compressed on-disk format.
3931 static void
3932 build_compressed_metadata (MonoDynamicImage *assembly)
3934 MonoDynamicTable *table;
3935 int i;
3936 guint64 valid_mask = 0;
3937 guint64 sorted_mask;
3938 guint32 heapt_size = 0;
3939 guint32 meta_size = 256; /* allow for header and other stuff */
3940 guint32 table_offset;
3941 guint32 ntables = 0;
3942 guint64 *int64val;
3943 guint32 *int32val;
3944 guint16 *int16val;
3945 MonoImage *meta;
3946 unsigned char *p;
3947 struct StreamDesc stream_desc [5];
3949 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3950 for (i = 0; i < assembly->gen_params->len; i++){
3951 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3952 write_generic_param_entry (assembly, entry);
3955 stream_desc [0].name = "#~";
3956 stream_desc [0].stream = &assembly->tstream;
3957 stream_desc [1].name = "#Strings";
3958 stream_desc [1].stream = &assembly->sheap;
3959 stream_desc [2].name = "#US";
3960 stream_desc [2].stream = &assembly->us;
3961 stream_desc [3].name = "#Blob";
3962 stream_desc [3].stream = &assembly->blob;
3963 stream_desc [4].name = "#GUID";
3964 stream_desc [4].stream = &assembly->guid;
3966 /* tables that are sorted */
3967 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3968 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3969 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3970 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3971 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3972 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
3973 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
3975 /* Compute table sizes */
3976 /* the MonoImage has already been created in mono_image_basic_init() */
3977 meta = &assembly->image;
3979 /* sizes should be multiple of 4 */
3980 pad_heap (&assembly->blob);
3981 pad_heap (&assembly->guid);
3982 pad_heap (&assembly->sheap);
3983 pad_heap (&assembly->us);
3985 /* Setup the info used by compute_sizes () */
3986 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3987 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3988 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3990 meta_size += assembly->blob.index;
3991 meta_size += assembly->guid.index;
3992 meta_size += assembly->sheap.index;
3993 meta_size += assembly->us.index;
3995 for (i=0; i < MONO_TABLE_NUM; ++i)
3996 meta->tables [i].rows = assembly->tables [i].rows;
3998 for (i = 0; i < MONO_TABLE_NUM; i++){
3999 if (meta->tables [i].rows == 0)
4000 continue;
4001 valid_mask |= (guint64)1 << i;
4002 ntables ++;
4003 meta->tables [i].row_size = mono_metadata_compute_size (
4004 meta, i, &meta->tables [i].size_bitfield);
4005 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4007 heapt_size += 24; /* #~ header size */
4008 heapt_size += ntables * 4;
4009 /* make multiple of 4 */
4010 heapt_size += 3;
4011 heapt_size &= ~3;
4012 meta_size += heapt_size;
4013 meta->raw_metadata = g_malloc0 (meta_size);
4014 p = (unsigned char*)meta->raw_metadata;
4015 /* the metadata signature */
4016 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4017 /* version numbers and 4 bytes reserved */
4018 int16val = (guint16*)p;
4019 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4020 *int16val = GUINT16_TO_LE (meta->md_version_minor);
4021 p += 8;
4022 /* version string */
4023 int32val = (guint32*)p;
4024 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4025 p += 4;
4026 memcpy (p, meta->version, strlen (meta->version));
4027 p += GUINT32_FROM_LE (*int32val);
4028 align_pointer (meta->raw_metadata, p);
4029 int16val = (guint16*)p;
4030 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4031 *int16val = GUINT16_TO_LE (5); /* number of streams */
4032 p += 4;
4035 * write the stream info.
4037 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4038 table_offset += 3; table_offset &= ~3;
4040 assembly->tstream.index = heapt_size;
4041 for (i = 0; i < 5; ++i) {
4042 int32val = (guint32*)p;
4043 stream_desc [i].stream->offset = table_offset;
4044 *int32val++ = GUINT32_TO_LE (table_offset);
4045 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4046 table_offset += GUINT32_FROM_LE (*int32val);
4047 table_offset += 3; table_offset &= ~3;
4048 p += 8;
4049 strcpy ((char*)p, stream_desc [i].name);
4050 p += strlen (stream_desc [i].name) + 1;
4051 align_pointer (meta->raw_metadata, p);
4054 * now copy the data, the table stream header and contents goes first.
4056 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4057 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4058 int32val = (guint32*)p;
4059 *int32val = GUINT32_TO_LE (0); /* reserved */
4060 p += 4;
4062 *p++ = 2; /* version */
4063 *p++ = 0;
4065 if (meta->idx_string_wide)
4066 *p |= 0x01;
4067 if (meta->idx_guid_wide)
4068 *p |= 0x02;
4069 if (meta->idx_blob_wide)
4070 *p |= 0x04;
4071 ++p;
4072 *p++ = 1; /* reserved */
4073 int64val = (guint64*)p;
4074 *int64val++ = GUINT64_TO_LE (valid_mask);
4075 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
4076 p += 16;
4077 int32val = (guint32*)p;
4078 for (i = 0; i < MONO_TABLE_NUM; i++){
4079 if (meta->tables [i].rows == 0)
4080 continue;
4081 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4083 p = (unsigned char*)int32val;
4085 /* sort the tables that still need sorting */
4086 table = &assembly->tables [MONO_TABLE_CONSTANT];
4087 if (table->rows)
4088 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4089 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4090 if (table->rows)
4091 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4092 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4093 if (table->rows)
4094 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4095 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4096 if (table->rows)
4097 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4098 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4099 if (table->rows)
4100 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4101 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4102 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4103 if (table->rows)
4104 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4105 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4106 if (table->rows)
4107 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4109 /* compress the tables */
4110 for (i = 0; i < MONO_TABLE_NUM; i++){
4111 int row, col;
4112 guint32 *values;
4113 guint32 bitfield = meta->tables [i].size_bitfield;
4114 if (!meta->tables [i].rows)
4115 continue;
4116 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4117 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4118 meta->tables [i].base = (char*)p;
4119 for (row = 1; row <= meta->tables [i].rows; ++row) {
4120 values = assembly->tables [i].values + row * assembly->tables [i].columns;
4121 for (col = 0; col < assembly->tables [i].columns; ++col) {
4122 switch (mono_metadata_table_size (bitfield, col)) {
4123 case 1:
4124 *p++ = values [col];
4125 break;
4126 case 2:
4127 *p++ = values [col] & 0xff;
4128 *p++ = (values [col] >> 8) & 0xff;
4129 break;
4130 case 4:
4131 *p++ = values [col] & 0xff;
4132 *p++ = (values [col] >> 8) & 0xff;
4133 *p++ = (values [col] >> 16) & 0xff;
4134 *p++ = (values [col] >> 24) & 0xff;
4135 break;
4136 default:
4137 g_assert_not_reached ();
4141 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4144 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4145 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4146 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4147 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4148 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4150 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4154 * Some tables in metadata need to be sorted according to some criteria, but
4155 * when methods and fields are first created with reflection, they may be assigned a token
4156 * that doesn't correspond to the final token they will get assigned after the sorting.
4157 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4158 * with the reflection objects that represent them. Once all the tables are set up, the
4159 * reflection objects will contains the correct table index. fixup_method() will fixup the
4160 * tokens for the method with ILGenerator @ilgen.
4162 static void
4163 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4165 guint32 code_idx = GPOINTER_TO_UINT (value);
4166 MonoReflectionILTokenInfo *iltoken;
4167 MonoReflectionFieldBuilder *field;
4168 MonoReflectionCtorBuilder *ctor;
4169 MonoReflectionMethodBuilder *method;
4170 MonoReflectionTypeBuilder *tb;
4171 MonoReflectionArrayMethod *am;
4172 guint32 i, idx = 0;
4173 unsigned char *target;
4175 for (i = 0; i < ilgen->num_token_fixups; ++i) {
4176 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4177 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4178 switch (target [3]) {
4179 case MONO_TABLE_FIELD:
4180 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4181 field = (MonoReflectionFieldBuilder *)iltoken->member;
4182 idx = field->table_idx;
4183 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4184 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4185 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4186 } else {
4187 g_assert_not_reached ();
4189 break;
4190 case MONO_TABLE_METHOD:
4191 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4192 method = (MonoReflectionMethodBuilder *)iltoken->member;
4193 idx = method->table_idx;
4194 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4195 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4196 idx = ctor->table_idx;
4197 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4198 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4199 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4200 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4201 } else {
4202 g_assert_not_reached ();
4204 break;
4205 case MONO_TABLE_TYPEDEF:
4206 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4207 g_assert_not_reached ();
4208 tb = (MonoReflectionTypeBuilder *)iltoken->member;
4209 idx = tb->table_idx;
4210 break;
4211 case MONO_TABLE_MEMBERREF:
4212 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4213 am = (MonoReflectionArrayMethod*)iltoken->member;
4214 idx = am->table_idx;
4215 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4216 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4217 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4218 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4219 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4220 g_assert (m->klass->generic_class || m->klass->generic_container);
4221 continue;
4222 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4223 continue;
4224 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4225 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4226 g_assert (is_field_on_inst (f));
4227 continue;
4228 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4229 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4230 continue;
4231 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4232 continue;
4233 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4234 continue;
4235 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4236 continue;
4237 } else {
4238 g_assert_not_reached ();
4240 break;
4241 case MONO_TABLE_METHODSPEC:
4242 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4243 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4244 g_assert (mono_method_signature (m)->generic_param_count);
4245 continue;
4246 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4247 continue;
4248 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4249 continue;
4250 } else {
4251 g_assert_not_reached ();
4253 break;
4254 default:
4255 g_error ("got unexpected table 0x%02x in fixup", target [3]);
4257 target [0] = idx & 0xff;
4258 target [1] = (idx >> 8) & 0xff;
4259 target [2] = (idx >> 16) & 0xff;
4264 * fixup_cattrs:
4266 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4267 * value is not known when the table is emitted.
4269 static void
4270 fixup_cattrs (MonoDynamicImage *assembly)
4272 MonoDynamicTable *table;
4273 guint32 *values;
4274 guint32 type, i, idx, token;
4275 MonoObject *ctor;
4277 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4279 for (i = 0; i < table->rows; ++i) {
4280 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4282 type = values [MONO_CUSTOM_ATTR_TYPE];
4283 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4284 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4285 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4286 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4287 g_assert (ctor);
4289 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4290 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4291 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4292 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4298 static void
4299 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4301 MonoDynamicTable *table;
4302 guint32 *values;
4304 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4305 table->rows++;
4306 alloc_table (table, table->rows);
4307 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4308 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4309 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4310 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4311 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4312 table->next_idx++;
4315 static void
4316 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4318 MonoDynamicTable *table;
4319 guint32 *values;
4320 char blob_size [6];
4321 guchar hash [20];
4322 char *b = blob_size;
4323 char *name, *sname;
4324 guint32 idx, offset;
4326 if (rsrc->filename) {
4327 name = mono_string_to_utf8 (rsrc->filename);
4328 sname = g_path_get_basename (name);
4330 table = &assembly->tables [MONO_TABLE_FILE];
4331 table->rows++;
4332 alloc_table (table, table->rows);
4333 values = table->values + table->next_idx * MONO_FILE_SIZE;
4334 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4335 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4336 g_free (sname);
4338 mono_sha1_get_digest_from_file (name, hash);
4339 mono_metadata_encode_value (20, b, &b);
4340 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4341 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4342 g_free (name);
4343 idx = table->next_idx++;
4344 rsrc->offset = 0;
4345 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4346 } else {
4347 char sizebuf [4];
4348 char *data;
4349 guint len;
4350 if (rsrc->data) {
4351 data = mono_array_addr (rsrc->data, char, 0);
4352 len = mono_array_length (rsrc->data);
4353 } else {
4354 data = NULL;
4355 len = 0;
4357 offset = len;
4358 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4359 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4360 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4361 mono_image_add_stream_data (&assembly->resources, data, len);
4363 if (!mb->is_main)
4365 * The entry should be emitted into the MANIFESTRESOURCE table of
4366 * the main module, but that needs to reference the FILE table
4367 * which isn't emitted yet.
4369 return;
4370 else
4371 idx = 0;
4374 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4377 static void
4378 set_version_from_string (MonoString *version, guint32 *values)
4380 gchar *ver, *p, *str;
4381 guint32 i;
4383 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4384 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4385 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4386 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4387 if (!version)
4388 return;
4389 ver = str = mono_string_to_utf8 (version);
4390 for (i = 0; i < 4; ++i) {
4391 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4392 switch (*p) {
4393 case '.':
4394 p++;
4395 break;
4396 case '*':
4397 /* handle Revision and Build */
4398 p++;
4399 break;
4401 ver = p;
4403 g_free (str);
4406 static guint32
4407 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4408 gsize len;
4409 guint32 token = 0;
4410 char blob_size [6];
4411 char *b = blob_size;
4413 if (!pkey)
4414 return token;
4416 len = mono_array_length (pkey);
4417 mono_metadata_encode_value (len, b, &b);
4418 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4419 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4421 assembly->public_key = g_malloc (len);
4422 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4423 assembly->public_key_len = len;
4425 /* Special case: check for ECMA key (16 bytes) */
4426 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4427 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4428 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4429 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4430 /* minimum key size (in 2.0) is 384 bits */
4431 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4432 } else {
4433 /* FIXME - verifier */
4434 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4435 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4437 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
4439 return token;
4442 static void
4443 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4445 MonoDynamicTable *table;
4446 MonoDynamicImage *assembly;
4447 MonoReflectionAssemblyBuilder *assemblyb;
4448 MonoDomain *domain;
4449 guint32 *values;
4450 int i;
4451 guint32 module_index;
4453 assemblyb = moduleb->assemblyb;
4454 assembly = moduleb->dynamic_image;
4455 domain = mono_object_domain (assemblyb);
4457 /* Emit ASSEMBLY table */
4458 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4459 alloc_table (table, 1);
4460 values = table->values + MONO_ASSEMBLY_SIZE;
4461 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4462 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4463 if (assemblyb->culture) {
4464 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4465 } else {
4466 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4468 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4469 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4470 set_version_from_string (assemblyb->version, values);
4472 /* Emit FILE + EXPORTED_TYPE table */
4473 module_index = 0;
4474 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4475 int j;
4476 MonoReflectionModuleBuilder *file_module =
4477 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4478 if (file_module != moduleb) {
4479 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4480 module_index ++;
4481 if (file_module->types) {
4482 for (j = 0; j < file_module->num_types; ++j) {
4483 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4484 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4489 if (assemblyb->loaded_modules) {
4490 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4491 MonoReflectionModule *file_module =
4492 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4493 mono_image_fill_file_table (domain, file_module, assembly);
4494 module_index ++;
4495 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4498 if (assemblyb->type_forwarders)
4499 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4501 /* Emit MANIFESTRESOURCE table */
4502 module_index = 0;
4503 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4504 int j;
4505 MonoReflectionModuleBuilder *file_module =
4506 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4507 /* The table for the main module is emitted later */
4508 if (file_module != moduleb) {
4509 module_index ++;
4510 if (file_module->resources) {
4511 int len = mono_array_length (file_module->resources);
4512 for (j = 0; j < len; ++j) {
4513 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4514 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4521 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4524 * mono_image_build_metadata() will fill the info in all the needed metadata tables
4525 * for the modulebuilder @moduleb.
4526 * At the end of the process, method and field tokens are fixed up and the
4527 * on-disk compressed metadata representation is created.
4529 void
4530 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4532 MonoDynamicTable *table;
4533 MonoDynamicImage *assembly;
4534 MonoReflectionAssemblyBuilder *assemblyb;
4535 MonoDomain *domain;
4536 GPtrArray *types;
4537 guint32 *values;
4538 int i, j;
4540 assemblyb = moduleb->assemblyb;
4541 assembly = moduleb->dynamic_image;
4542 domain = mono_object_domain (assemblyb);
4544 if (assembly->text_rva)
4545 return;
4547 assembly->text_rva = START_TEXT_RVA;
4549 if (moduleb->is_main) {
4550 mono_image_emit_manifest (moduleb);
4553 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4554 table->rows = 1; /* .<Module> */
4555 table->next_idx++;
4556 alloc_table (table, table->rows);
4558 * Set the first entry.
4560 values = table->values + table->columns;
4561 values [MONO_TYPEDEF_FLAGS] = 0;
4562 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4563 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4564 values [MONO_TYPEDEF_EXTENDS] = 0;
4565 values [MONO_TYPEDEF_FIELD_LIST] = 1;
4566 values [MONO_TYPEDEF_METHOD_LIST] = 1;
4569 * handle global methods
4570 * FIXME: test what to do when global methods are defined in multiple modules.
4572 if (moduleb->global_methods) {
4573 table = &assembly->tables [MONO_TABLE_METHOD];
4574 table->rows += mono_array_length (moduleb->global_methods);
4575 alloc_table (table, table->rows);
4576 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4577 mono_image_get_method_info (
4578 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4580 if (moduleb->global_fields) {
4581 table = &assembly->tables [MONO_TABLE_FIELD];
4582 table->rows += mono_array_length (moduleb->global_fields);
4583 alloc_table (table, table->rows);
4584 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4585 mono_image_get_field_info (
4586 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4589 table = &assembly->tables [MONO_TABLE_MODULE];
4590 alloc_table (table, 1);
4591 mono_image_fill_module_table (domain, moduleb, assembly);
4593 /* Collect all types into a list sorted by their table_idx */
4594 types = g_ptr_array_new ();
4596 if (moduleb->types)
4597 for (i = 0; i < moduleb->num_types; ++i) {
4598 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4599 collect_types (types, type);
4602 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
4603 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4604 table->rows += types->len;
4605 alloc_table (table, table->rows);
4608 * Emit type names + namespaces at one place inside the string heap,
4609 * so load_class_names () needs to touch fewer pages.
4611 for (i = 0; i < types->len; ++i) {
4612 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4613 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4615 for (i = 0; i < types->len; ++i) {
4616 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4617 string_heap_insert_mstring (&assembly->sheap, tb->name);
4620 for (i = 0; i < types->len; ++i) {
4621 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4622 mono_image_get_type_info (domain, type, assembly);
4626 * table->rows is already set above and in mono_image_fill_module_table.
4628 /* add all the custom attributes at the end, once all the indexes are stable */
4629 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4631 /* CAS assembly permissions */
4632 if (assemblyb->permissions_minimum)
4633 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4634 if (assemblyb->permissions_optional)
4635 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4636 if (assemblyb->permissions_refused)
4637 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4639 module_add_cattrs (assembly, moduleb);
4641 /* fixup tokens */
4642 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4644 /* Create the MethodImpl table. We do this after emitting all methods so we already know
4645 * the final tokens and don't need another fixup pass. */
4647 if (moduleb->global_methods) {
4648 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4649 MonoReflectionMethodBuilder *mb = mono_array_get (
4650 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4651 mono_image_add_methodimpl (assembly, mb);
4655 for (i = 0; i < types->len; ++i) {
4656 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4657 if (type->methods) {
4658 for (j = 0; j < type->num_methods; ++j) {
4659 MonoReflectionMethodBuilder *mb = mono_array_get (
4660 type->methods, MonoReflectionMethodBuilder*, j);
4662 mono_image_add_methodimpl (assembly, mb);
4667 g_ptr_array_free (types, TRUE);
4669 fixup_cattrs (assembly);
4672 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4674 void
4675 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4677 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4680 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4683 typedef struct {
4684 guint32 import_lookup_table;
4685 guint32 timestamp;
4686 guint32 forwarder;
4687 guint32 name_rva;
4688 guint32 import_address_table_rva;
4689 } MonoIDT;
4691 typedef struct {
4692 guint32 name_rva;
4693 guint32 flags;
4694 } MonoILT;
4696 #ifndef DISABLE_REFLECTION_EMIT
4699 * mono_image_insert_string:
4700 * @module: module builder object
4701 * @str: a string
4703 * Insert @str into the user string stream of @module.
4705 guint32
4706 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4708 MonoDynamicImage *assembly;
4709 guint32 idx;
4710 char buf [16];
4711 char *b = buf;
4713 MONO_ARCH_SAVE_REGS;
4715 if (!module->dynamic_image)
4716 mono_image_module_basic_init (module);
4718 assembly = module->dynamic_image;
4720 if (assembly->save) {
4721 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4722 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4723 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4725 char *swapped = g_malloc (2 * mono_string_length (str));
4726 const char *p = (const char*)mono_string_chars (str);
4728 swap_with_size (swapped, p, 2, mono_string_length (str));
4729 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4730 g_free (swapped);
4732 #else
4733 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4734 #endif
4735 mono_image_add_stream_data (&assembly->us, "", 1);
4736 } else {
4737 idx = assembly->us.index ++;
4740 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4742 return MONO_TOKEN_STRING | idx;
4745 guint32
4746 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4748 MonoClass *klass;
4749 guint32 token = 0;
4751 klass = obj->vtable->klass;
4752 if (strcmp (klass->name, "MonoMethod") == 0) {
4753 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4754 MonoMethodSignature *sig, *old;
4755 guint32 sig_token, parent;
4756 int nargs, i;
4758 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4760 nargs = mono_array_length (opt_param_types);
4761 old = mono_method_signature (method);
4762 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4764 sig->hasthis = old->hasthis;
4765 sig->explicit_this = old->explicit_this;
4766 sig->call_convention = old->call_convention;
4767 sig->generic_param_count = old->generic_param_count;
4768 sig->param_count = old->param_count + nargs;
4769 sig->sentinelpos = old->param_count;
4770 sig->ret = old->ret;
4772 for (i = 0; i < old->param_count; i++)
4773 sig->params [i] = old->params [i];
4775 for (i = 0; i < nargs; i++) {
4776 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4777 sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt);
4780 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4781 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4782 parent >>= MONO_TYPEDEFORREF_BITS;
4784 parent <<= MONO_MEMBERREF_PARENT_BITS;
4785 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4787 sig_token = method_encode_signature (assembly, sig);
4788 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4789 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4790 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4791 ReflectionMethodBuilder rmb;
4792 guint32 parent, sig;
4793 char *name;
4795 reflection_methodbuilder_from_method_builder (&rmb, mb);
4796 rmb.opt_types = opt_param_types;
4798 sig = method_builder_encode_signature (assembly, &rmb);
4800 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
4801 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4803 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4804 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4806 name = mono_string_to_utf8 (rmb.name);
4807 token = mono_image_get_varargs_method_token (
4808 assembly, parent, name, sig);
4809 g_free (name);
4810 } else {
4811 g_error ("requested method token for %s\n", klass->name);
4814 return token;
4818 * mono_image_create_token:
4819 * @assembly: a dynamic assembly
4820 * @obj:
4821 * @register_token: Whenever to register the token in the assembly->tokens hash.
4823 * Get a token to insert in the IL code stream for the given MemberInfo.
4824 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
4825 * the table_idx-es were recomputed, so registering the token would overwrite an existing
4826 * entry.
4828 guint32
4829 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
4830 gboolean create_methodspec, gboolean register_token)
4832 MonoClass *klass;
4833 guint32 token = 0;
4835 klass = obj->vtable->klass;
4837 /* Check for user defined reflection objects */
4838 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
4839 if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0))
4840 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported")); \
4842 if (strcmp (klass->name, "MethodBuilder") == 0) {
4843 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4844 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4846 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
4847 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4848 else
4849 token = mono_image_get_methodbuilder_token (assembly, mb, create_methodspec);
4850 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4851 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4852 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4853 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4855 if (tb->module->dynamic_image == assembly && !tb->generic_params)
4856 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4857 else
4858 token = mono_image_get_ctorbuilder_token (assembly, mb);
4859 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4860 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4861 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4862 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4863 if (tb->generic_params) {
4864 token = mono_image_get_generic_field_token (assembly, fb);
4865 } else {
4866 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4868 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4869 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4870 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4871 } else if (strcmp (klass->name, "MonoType") == 0) {
4872 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4873 MonoClass *mc = mono_class_from_mono_type (type);
4874 token = mono_metadata_token_from_dor (
4875 mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL));
4876 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4877 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4878 token = mono_metadata_token_from_dor (
4879 mono_image_typedef_or_ref (assembly, type));
4880 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4881 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4882 token = mono_metadata_token_from_dor (
4883 mono_image_typedef_or_ref (assembly, type));
4884 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4885 strcmp (klass->name, "MonoMethod") == 0 ||
4886 strcmp (klass->name, "MonoGenericMethod") == 0 ||
4887 strcmp (klass->name, "MonoGenericCMethod") == 0) {
4888 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4889 if (m->method->is_inflated) {
4890 if (create_methodspec)
4891 token = mono_image_get_methodspec_token (assembly, m->method);
4892 else
4893 token = mono_image_get_inflated_method_token (assembly, m->method);
4894 } else if ((m->method->klass->image == &assembly->image) &&
4895 !m->method->klass->generic_class) {
4896 static guint32 method_table_idx = 0xffffff;
4897 if (m->method->klass->wastypebuilder) {
4898 /* we use the same token as the one that was assigned
4899 * to the Methodbuilder.
4900 * FIXME: do the equivalent for Fields.
4902 token = m->method->token;
4903 } else {
4905 * Each token should have a unique index, but the indexes are
4906 * assigned by managed code, so we don't know about them. An
4907 * easy solution is to count backwards...
4909 method_table_idx --;
4910 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4912 } else {
4913 token = mono_image_get_methodref_token (assembly, m->method, create_methodspec);
4915 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4916 } else if (strcmp (klass->name, "MonoField") == 0) {
4917 MonoReflectionField *f = (MonoReflectionField *)obj;
4918 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
4919 static guint32 field_table_idx = 0xffffff;
4920 field_table_idx --;
4921 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4922 } else {
4923 token = mono_image_get_fieldref_token (assembly, f);
4925 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4926 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4927 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4928 token = mono_image_get_array_token (assembly, m);
4929 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4930 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4931 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4932 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
4933 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4934 token = mono_metadata_token_from_dor (
4935 mono_image_typedef_or_ref (assembly, type));
4936 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
4937 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
4938 token = mono_image_get_field_on_inst_token (assembly, f);
4939 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
4940 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
4941 token = mono_image_get_ctor_on_inst_token (assembly, c, create_methodspec);
4942 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
4943 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
4944 token = mono_image_get_method_on_inst_token (assembly, m, create_methodspec);
4945 } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
4946 MonoReflectionType *type = (MonoReflectionType *)obj;
4947 token = mono_metadata_token_from_dor (
4948 mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (type)));
4949 } else {
4950 g_error ("requested token for %s\n", klass->name);
4953 if (register_token)
4954 mono_image_register_token (assembly, token, obj);
4956 return token;
4960 * mono_image_register_token:
4962 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
4963 * the Module.ResolveXXXToken () methods to work.
4965 void
4966 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
4968 MonoObject *prev = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4969 if (prev) {
4970 /* There could be multiple MethodInfo objects with the same token */
4971 //g_assert (prev == obj);
4972 } else {
4973 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4977 static MonoDynamicImage*
4978 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4980 static const guchar entrycode [16] = {0xff, 0x25, 0};
4981 MonoDynamicImage *image;
4982 int i;
4984 const char *version;
4986 if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
4987 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
4988 else
4989 version = mono_get_runtime_info ()->runtime_version;
4991 #if HAVE_BOEHM_GC
4992 image = GC_MALLOC (sizeof (MonoDynamicImage));
4993 #else
4994 image = g_new0 (MonoDynamicImage, 1);
4995 #endif
4997 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
4999 /*g_print ("created image %p\n", image);*/
5000 /* keep in sync with image.c */
5001 image->image.name = assembly_name;
5002 image->image.assembly_name = image->image.name; /* they may be different */
5003 image->image.module_name = module_name;
5004 image->image.version = g_strdup (version);
5005 image->image.md_version_major = 1;
5006 image->image.md_version_minor = 1;
5007 image->image.dynamic = TRUE;
5009 image->image.references = g_new0 (MonoAssembly*, 1);
5010 image->image.references [0] = NULL;
5012 mono_image_init (&image->image);
5014 image->token_fixups = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5015 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5016 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5017 image->method_aux_hash = g_hash_table_new (NULL, NULL);
5018 image->handleref = g_hash_table_new (NULL, NULL);
5019 image->handleref_managed = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5020 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5021 image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5022 image->methodspec = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5023 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5024 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5025 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5026 image->gen_params = g_ptr_array_new ();
5028 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5029 string_heap_init (&image->sheap);
5030 mono_image_add_stream_data (&image->us, "", 1);
5031 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5032 /* import tables... */
5033 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5034 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5035 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5036 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5037 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5038 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5039 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5040 stream_data_align (&image->code);
5042 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5044 for (i=0; i < MONO_TABLE_NUM; ++i) {
5045 image->tables [i].next_idx = 1;
5046 image->tables [i].columns = table_sizes [i];
5049 image->image.assembly = (MonoAssembly*)assembly;
5050 image->run = assembly->run;
5051 image->save = assembly->save;
5052 image->pe_kind = 0x1; /* ILOnly */
5053 image->machine = 0x14c; /* I386 */
5055 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5057 return image;
5059 #endif
5061 static void
5062 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5064 g_free (key);
5067 void
5068 mono_dynamic_image_free (MonoDynamicImage *image)
5070 MonoDynamicImage *di = image;
5071 GList *list;
5072 int i;
5074 if (di->methodspec)
5075 mono_g_hash_table_destroy (di->methodspec);
5076 if (di->typespec)
5077 g_hash_table_destroy (di->typespec);
5078 if (di->typeref)
5079 g_hash_table_destroy (di->typeref);
5080 if (di->handleref)
5081 g_hash_table_destroy (di->handleref);
5082 if (di->handleref_managed)
5083 mono_g_hash_table_destroy (di->handleref_managed);
5084 if (di->tokens)
5085 mono_g_hash_table_destroy (di->tokens);
5086 if (di->generic_def_objects)
5087 mono_g_hash_table_destroy (di->generic_def_objects);
5088 if (di->blob_cache) {
5089 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5090 g_hash_table_destroy (di->blob_cache);
5092 if (di->standalonesig_cache)
5093 g_hash_table_destroy (di->standalonesig_cache);
5094 for (list = di->array_methods; list; list = list->next) {
5095 ArrayMethod *am = (ArrayMethod *)list->data;
5096 g_free (am->sig);
5097 g_free (am->name);
5098 g_free (am);
5100 g_list_free (di->array_methods);
5101 if (di->gen_params) {
5102 for (i = 0; i < di->gen_params->len; i++) {
5103 GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
5104 if (entry->gparam->type.type) {
5105 MonoGenericParam *param = entry->gparam->type.type->data.generic_param;
5106 g_free ((char*)mono_generic_param_info (param)->name);
5107 g_free (param);
5109 mono_gc_deregister_root ((char*) &entry->gparam);
5110 g_free (entry);
5112 g_ptr_array_free (di->gen_params, TRUE);
5114 if (di->token_fixups)
5115 mono_g_hash_table_destroy (di->token_fixups);
5116 if (di->method_to_table_idx)
5117 g_hash_table_destroy (di->method_to_table_idx);
5118 if (di->field_to_table_idx)
5119 g_hash_table_destroy (di->field_to_table_idx);
5120 if (di->method_aux_hash)
5121 g_hash_table_destroy (di->method_aux_hash);
5122 g_free (di->strong_name);
5123 g_free (di->win32_res);
5124 if (di->public_key)
5125 g_free (di->public_key);
5127 /*g_print ("string heap destroy for image %p\n", di);*/
5128 mono_dynamic_stream_reset (&di->sheap);
5129 mono_dynamic_stream_reset (&di->code);
5130 mono_dynamic_stream_reset (&di->resources);
5131 mono_dynamic_stream_reset (&di->us);
5132 mono_dynamic_stream_reset (&di->blob);
5133 mono_dynamic_stream_reset (&di->tstream);
5134 mono_dynamic_stream_reset (&di->guid);
5135 for (i = 0; i < MONO_TABLE_NUM; ++i) {
5136 g_free (di->tables [i].values);
5140 #ifndef DISABLE_REFLECTION_EMIT
5143 * mono_image_basic_init:
5144 * @assembly: an assembly builder object
5146 * Create the MonoImage that represents the assembly builder and setup some
5147 * of the helper hash table and the basic metadata streams.
5149 void
5150 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5152 MonoDynamicAssembly *assembly;
5153 MonoDynamicImage *image;
5154 MonoDomain *domain = mono_object_domain (assemblyb);
5156 MONO_ARCH_SAVE_REGS;
5158 if (assemblyb->dynamic_assembly)
5159 return;
5161 #if HAVE_BOEHM_GC
5162 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
5163 #else
5164 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5165 #endif
5167 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5169 assembly->assembly.ref_count = 1;
5170 assembly->assembly.dynamic = TRUE;
5171 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5172 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5173 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5174 if (assemblyb->culture)
5175 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5176 else
5177 assembly->assembly.aname.culture = g_strdup ("");
5179 if (assemblyb->version) {
5180 char *vstr = mono_string_to_utf8 (assemblyb->version);
5181 char **version = g_strsplit (vstr, ".", 4);
5182 char **parts = version;
5183 assembly->assembly.aname.major = atoi (*parts++);
5184 assembly->assembly.aname.minor = atoi (*parts++);
5185 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5186 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5188 g_strfreev (version);
5189 g_free (vstr);
5190 } else {
5191 assembly->assembly.aname.major = 0;
5192 assembly->assembly.aname.minor = 0;
5193 assembly->assembly.aname.build = 0;
5194 assembly->assembly.aname.revision = 0;
5197 assembly->run = assemblyb->access != 2;
5198 assembly->save = assemblyb->access != 1;
5199 assembly->domain = domain;
5201 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5202 image->initial_image = TRUE;
5203 assembly->assembly.aname.name = image->image.name;
5204 assembly->assembly.image = &image->image;
5205 if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5206 /* -1 to correct for the trailing NULL byte */
5207 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5208 g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5210 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);
5213 mono_domain_assemblies_lock (domain);
5214 domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
5215 mono_domain_assemblies_unlock (domain);
5217 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5219 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5221 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5224 #endif /* !DISABLE_REFLECTION_EMIT */
5226 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5228 static int
5229 calc_section_size (MonoDynamicImage *assembly)
5231 int nsections = 0;
5233 /* alignment constraints */
5234 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5235 g_assert ((assembly->code.index % 4) == 0);
5236 assembly->meta_size += 3;
5237 assembly->meta_size &= ~3;
5238 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5239 g_assert ((assembly->resources.index % 4) == 0);
5241 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5242 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5243 nsections++;
5245 if (assembly->win32_res) {
5246 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5248 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5249 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5250 nsections++;
5253 assembly->sections [MONO_SECTION_RELOC].size = 12;
5254 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5255 nsections++;
5257 return nsections;
5260 typedef struct {
5261 guint32 id;
5262 guint32 offset;
5263 GSList *children;
5264 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5265 } ResTreeNode;
5267 static int
5268 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5270 ResTreeNode *t1 = (ResTreeNode*)a;
5271 ResTreeNode *t2 = (ResTreeNode*)b;
5273 return t1->id - t2->id;
5277 * resource_tree_create:
5279 * Organize the resources into a resource tree.
5281 static ResTreeNode *
5282 resource_tree_create (MonoArray *win32_resources)
5284 ResTreeNode *tree, *res_node, *type_node, *lang_node;
5285 GSList *l;
5286 int i;
5288 tree = g_new0 (ResTreeNode, 1);
5290 for (i = 0; i < mono_array_length (win32_resources); ++i) {
5291 MonoReflectionWin32Resource *win32_res =
5292 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5294 /* Create node */
5296 /* FIXME: BUG: this stores managed references in unmanaged memory */
5297 lang_node = g_new0 (ResTreeNode, 1);
5298 lang_node->id = win32_res->lang_id;
5299 lang_node->win32_res = win32_res;
5301 /* Create type node if neccesary */
5302 type_node = NULL;
5303 for (l = tree->children; l; l = l->next)
5304 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5305 type_node = (ResTreeNode*)l->data;
5306 break;
5309 if (!type_node) {
5310 type_node = g_new0 (ResTreeNode, 1);
5311 type_node->id = win32_res->res_type;
5314 * The resource types have to be sorted otherwise
5315 * Windows Explorer can't display the version information.
5317 tree->children = g_slist_insert_sorted (tree->children,
5318 type_node, resource_tree_compare_by_id);
5321 /* Create res node if neccesary */
5322 res_node = NULL;
5323 for (l = type_node->children; l; l = l->next)
5324 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5325 res_node = (ResTreeNode*)l->data;
5326 break;
5329 if (!res_node) {
5330 res_node = g_new0 (ResTreeNode, 1);
5331 res_node->id = win32_res->res_id;
5332 type_node->children = g_slist_append (type_node->children, res_node);
5335 res_node->children = g_slist_append (res_node->children, lang_node);
5338 return tree;
5342 * resource_tree_encode:
5344 * Encode the resource tree into the format used in the PE file.
5346 static void
5347 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5349 char *entries;
5350 MonoPEResourceDir dir;
5351 MonoPEResourceDirEntry dir_entry;
5352 MonoPEResourceDataEntry data_entry;
5353 GSList *l;
5354 guint32 res_id_entries;
5357 * For the format of the resource directory, see the article
5358 * "An In-Depth Look into the Win32 Portable Executable File Format" by
5359 * Matt Pietrek
5362 memset (&dir, 0, sizeof (dir));
5363 memset (&dir_entry, 0, sizeof (dir_entry));
5364 memset (&data_entry, 0, sizeof (data_entry));
5366 g_assert (sizeof (dir) == 16);
5367 g_assert (sizeof (dir_entry) == 8);
5368 g_assert (sizeof (data_entry) == 16);
5370 node->offset = p - begin;
5372 /* IMAGE_RESOURCE_DIRECTORY */
5373 res_id_entries = g_slist_length (node->children);
5374 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5376 memcpy (p, &dir, sizeof (dir));
5377 p += sizeof (dir);
5379 /* Reserve space for entries */
5380 entries = p;
5381 p += sizeof (dir_entry) * res_id_entries;
5383 /* Write children */
5384 for (l = node->children; l; l = l->next) {
5385 ResTreeNode *child = (ResTreeNode*)l->data;
5387 if (child->win32_res) {
5388 guint32 size;
5390 child->offset = p - begin;
5392 /* IMAGE_RESOURCE_DATA_ENTRY */
5393 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5394 size = mono_array_length (child->win32_res->res_data);
5395 data_entry.rde_size = GUINT32_TO_LE (size);
5397 memcpy (p, &data_entry, sizeof (data_entry));
5398 p += sizeof (data_entry);
5400 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5401 p += size;
5402 } else {
5403 resource_tree_encode (child, begin, p, &p);
5407 /* IMAGE_RESOURCE_ENTRY */
5408 for (l = node->children; l; l = l->next) {
5409 ResTreeNode *child = (ResTreeNode*)l->data;
5411 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5412 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5414 memcpy (entries, &dir_entry, sizeof (dir_entry));
5415 entries += sizeof (dir_entry);
5418 *endbuf = p;
5421 static void
5422 resource_tree_free (ResTreeNode * node)
5424 GSList * list;
5425 for (list = node->children; list; list = list->next)
5426 resource_tree_free ((ResTreeNode*)list->data);
5427 g_slist_free(node->children);
5428 g_free (node);
5431 static void
5432 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5434 char *buf;
5435 char *p;
5436 guint32 size, i;
5437 MonoReflectionWin32Resource *win32_res;
5438 ResTreeNode *tree;
5440 if (!assemblyb->win32_resources)
5441 return;
5444 * Resources are stored in a three level tree inside the PE file.
5445 * - level one contains a node for each type of resource
5446 * - level two contains a node for each resource
5447 * - level three contains a node for each instance of a resource for a
5448 * specific language.
5451 tree = resource_tree_create (assemblyb->win32_resources);
5453 /* Estimate the size of the encoded tree */
5454 size = 0;
5455 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5456 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5457 size += mono_array_length (win32_res->res_data);
5459 /* Directory structure */
5460 size += mono_array_length (assemblyb->win32_resources) * 256;
5461 p = buf = g_malloc (size);
5463 resource_tree_encode (tree, p, p, &p);
5465 g_assert (p - buf <= size);
5467 assembly->win32_res = g_malloc (p - buf);
5468 assembly->win32_res_size = p - buf;
5469 memcpy (assembly->win32_res, buf, p - buf);
5471 g_free (buf);
5472 resource_tree_free (tree);
5475 static void
5476 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5478 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5479 int i;
5481 p += sizeof (MonoPEResourceDir);
5482 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5483 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5484 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5485 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5486 fixup_resource_directory (res_section, child, rva);
5487 } else {
5488 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5489 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5492 p += sizeof (MonoPEResourceDirEntry);
5496 static void
5497 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5499 guint32 dummy;
5500 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5501 g_error ("WriteFile returned %d\n", GetLastError ());
5505 * mono_image_create_pefile:
5506 * @mb: a module builder object
5508 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
5509 * assembly->pefile where it can be easily retrieved later in chunks.
5511 void
5512 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5514 MonoMSDOSHeader *msdos;
5515 MonoDotNetHeader *header;
5516 MonoSectionTable *section;
5517 MonoCLIHeader *cli_header;
5518 guint32 size, image_size, virtual_base, text_offset;
5519 guint32 header_start, section_start, file_offset, virtual_offset;
5520 MonoDynamicImage *assembly;
5521 MonoReflectionAssemblyBuilder *assemblyb;
5522 MonoDynamicStream pefile_stream = {0};
5523 MonoDynamicStream *pefile = &pefile_stream;
5524 int i, nsections;
5525 guint32 *rva, value;
5526 guchar *p;
5527 static const unsigned char msheader[] = {
5528 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5529 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5530 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5531 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5532 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5533 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5534 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5535 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5538 assemblyb = mb->assemblyb;
5540 mono_image_basic_init (assemblyb);
5541 assembly = mb->dynamic_image;
5543 assembly->pe_kind = assemblyb->pe_kind;
5544 assembly->machine = assemblyb->machine;
5545 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5546 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5548 mono_image_build_metadata (mb);
5550 if (mb->is_main && assemblyb->resources) {
5551 int len = mono_array_length (assemblyb->resources);
5552 for (i = 0; i < len; ++i)
5553 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5556 if (mb->resources) {
5557 int len = mono_array_length (mb->resources);
5558 for (i = 0; i < len; ++i)
5559 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5562 build_compressed_metadata (assembly);
5564 if (mb->is_main)
5565 assembly_add_win32_resources (assembly, assemblyb);
5567 nsections = calc_section_size (assembly);
5569 /* The DOS header and stub */
5570 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5571 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5573 /* the dotnet header */
5574 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5576 /* the section tables */
5577 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5579 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5580 virtual_offset = VIRT_ALIGN;
5581 image_size = 0;
5583 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5584 if (!assembly->sections [i].size)
5585 continue;
5586 /* align offsets */
5587 file_offset += FILE_ALIGN - 1;
5588 file_offset &= ~(FILE_ALIGN - 1);
5589 virtual_offset += VIRT_ALIGN - 1;
5590 virtual_offset &= ~(VIRT_ALIGN - 1);
5592 assembly->sections [i].offset = file_offset;
5593 assembly->sections [i].rva = virtual_offset;
5595 file_offset += assembly->sections [i].size;
5596 virtual_offset += assembly->sections [i].size;
5597 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5600 file_offset += FILE_ALIGN - 1;
5601 file_offset &= ~(FILE_ALIGN - 1);
5603 image_size += section_start + sizeof (MonoSectionTable) * nsections;
5605 /* back-patch info */
5606 msdos = (MonoMSDOSHeader*)pefile->data;
5607 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5609 header = (MonoDotNetHeader*)(pefile->data + header_start);
5610 header->pesig [0] = 'P';
5611 header->pesig [1] = 'E';
5613 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5614 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5615 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5616 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5617 if (assemblyb->pekind == 1) {
5618 /* it's a dll */
5619 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5620 } else {
5621 /* it's an exe */
5622 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5625 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5627 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5628 header->pe.pe_major = 6;
5629 header->pe.pe_minor = 0;
5630 size = assembly->sections [MONO_SECTION_TEXT].size;
5631 size += FILE_ALIGN - 1;
5632 size &= ~(FILE_ALIGN - 1);
5633 header->pe.pe_code_size = GUINT32_FROM_LE(size);
5634 size = assembly->sections [MONO_SECTION_RSRC].size;
5635 size += FILE_ALIGN - 1;
5636 size &= ~(FILE_ALIGN - 1);
5637 header->pe.pe_data_size = GUINT32_FROM_LE(size);
5638 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5639 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5640 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5641 /* pe_rva_entry_point always at the beginning of the text section */
5642 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5644 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5645 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5646 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5647 header->nt.pe_os_major = GUINT16_FROM_LE (4);
5648 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5649 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5650 size = section_start;
5651 size += FILE_ALIGN - 1;
5652 size &= ~(FILE_ALIGN - 1);
5653 header->nt.pe_header_size = GUINT32_FROM_LE (size);
5654 size = image_size;
5655 size += VIRT_ALIGN - 1;
5656 size &= ~(VIRT_ALIGN - 1);
5657 header->nt.pe_image_size = GUINT32_FROM_LE (size);
5660 // Translate the PEFileKind value to the value expected by the Windows loader
5663 short kind;
5666 // PEFileKinds.Dll == 1
5667 // PEFileKinds.ConsoleApplication == 2
5668 // PEFileKinds.WindowApplication == 3
5670 // need to get:
5671 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5672 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5674 if (assemblyb->pekind == 3)
5675 kind = 2;
5676 else
5677 kind = 3;
5679 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5681 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5682 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5683 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5684 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5685 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5686 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
5688 /* fill data directory entries */
5690 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
5691 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5693 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
5694 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
5696 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
5697 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
5698 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
5699 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5700 /* patch entrypoint name */
5701 if (assemblyb->pekind == 1)
5702 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
5703 else
5704 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
5705 /* patch imported function RVA name */
5706 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
5707 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
5709 /* the import table */
5710 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
5711 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
5712 /* patch imported dll RVA name and other entries in the dir */
5713 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
5714 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
5715 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
5716 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5717 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
5718 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
5720 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
5721 value = (assembly->text_rva + assembly->imp_names_offset);
5722 *p++ = (value) & 0xff;
5723 *p++ = (value >> 8) & (0xff);
5724 *p++ = (value >> 16) & (0xff);
5725 *p++ = (value >> 24) & (0xff);
5727 /* the CLI header info */
5728 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
5729 cli_header->ch_size = GUINT32_FROM_LE (72);
5730 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
5731 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
5732 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
5733 if (assemblyb->entry_point) {
5734 guint32 table_idx = 0;
5735 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
5736 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
5737 table_idx = methodb->table_idx;
5738 } else {
5739 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
5741 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
5742 } else {
5743 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
5745 /* The embedded managed resources */
5746 text_offset = assembly->text_rva + assembly->code.index;
5747 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
5748 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
5749 text_offset += assembly->resources.index;
5750 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
5751 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
5752 text_offset += assembly->meta_size;
5753 if (assembly->strong_name_size) {
5754 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
5755 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
5756 text_offset += assembly->strong_name_size;
5759 /* write the section tables and section content */
5760 section = (MonoSectionTable*)(pefile->data + section_start);
5761 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5762 static const char section_names [][7] = {
5763 ".text", ".rsrc", ".reloc"
5765 if (!assembly->sections [i].size)
5766 continue;
5767 strcpy (section->st_name, section_names [i]);
5768 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5769 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5770 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5771 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5772 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5773 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5774 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5775 section ++;
5778 checked_write_file (file, pefile->data, pefile->index);
5780 mono_dynamic_stream_reset (pefile);
5782 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5783 if (!assembly->sections [i].size)
5784 continue;
5786 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5787 g_error ("SetFilePointer returned %d\n", GetLastError ());
5789 switch (i) {
5790 case MONO_SECTION_TEXT:
5791 /* patch entry point */
5792 p = (guchar*)(assembly->code.data + 2);
5793 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5794 *p++ = (value) & 0xff;
5795 *p++ = (value >> 8) & 0xff;
5796 *p++ = (value >> 16) & 0xff;
5797 *p++ = (value >> 24) & 0xff;
5799 checked_write_file (file, assembly->code.data, assembly->code.index);
5800 checked_write_file (file, assembly->resources.data, assembly->resources.index);
5801 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5802 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5805 g_free (assembly->image.raw_metadata);
5806 break;
5807 case MONO_SECTION_RELOC: {
5808 struct {
5809 guint32 page_rva;
5810 guint32 block_size;
5811 guint16 type_and_offset;
5812 guint16 term;
5813 } reloc;
5815 g_assert (sizeof (reloc) == 12);
5817 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5818 reloc.block_size = GUINT32_FROM_LE (12);
5821 * the entrypoint is always at the start of the text section
5822 * 3 is IMAGE_REL_BASED_HIGHLOW
5823 * 2 is patch_size_rva - text_rva
5825 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5826 reloc.term = 0;
5828 checked_write_file (file, &reloc, sizeof (reloc));
5830 break;
5832 case MONO_SECTION_RSRC:
5833 if (assembly->win32_res) {
5835 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5836 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5837 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5839 break;
5840 default:
5841 g_assert_not_reached ();
5845 /* check that the file is properly padded */
5846 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5847 g_error ("SetFilePointer returned %d\n", GetLastError ());
5848 if (! SetEndOfFile (file))
5849 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5851 mono_dynamic_stream_reset (&assembly->code);
5852 mono_dynamic_stream_reset (&assembly->us);
5853 mono_dynamic_stream_reset (&assembly->blob);
5854 mono_dynamic_stream_reset (&assembly->guid);
5855 mono_dynamic_stream_reset (&assembly->sheap);
5857 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5858 g_hash_table_destroy (assembly->blob_cache);
5859 assembly->blob_cache = NULL;
5862 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5864 void
5865 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5867 g_assert_not_reached ();
5870 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5872 #ifndef DISABLE_REFLECTION_EMIT
5874 MonoReflectionModule *
5875 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5877 char *name;
5878 MonoImage *image;
5879 MonoImageOpenStatus status;
5880 MonoDynamicAssembly *assembly;
5881 guint32 module_count;
5882 MonoImage **new_modules;
5883 gboolean *new_modules_loaded;
5885 name = mono_string_to_utf8 (fileName);
5887 image = mono_image_open (name, &status);
5888 if (!image) {
5889 MonoException *exc;
5890 if (status == MONO_IMAGE_ERROR_ERRNO)
5891 exc = mono_get_exception_file_not_found (fileName);
5892 else
5893 exc = mono_get_exception_bad_image_format (name);
5894 g_free (name);
5895 mono_raise_exception (exc);
5898 g_free (name);
5900 assembly = ab->dynamic_assembly;
5901 image->assembly = (MonoAssembly*)assembly;
5903 module_count = image->assembly->image->module_count;
5904 new_modules = g_new0 (MonoImage *, module_count + 1);
5905 new_modules_loaded = g_new0 (gboolean, module_count + 1);
5907 if (image->assembly->image->modules)
5908 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5909 if (image->assembly->image->modules_loaded)
5910 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
5911 new_modules [module_count] = image;
5912 new_modules_loaded [module_count] = TRUE;
5913 mono_image_addref (image);
5915 g_free (image->assembly->image->modules);
5916 image->assembly->image->modules = new_modules;
5917 image->assembly->image->modules_loaded = new_modules_loaded;
5918 image->assembly->image->module_count ++;
5920 mono_assembly_load_references (image, &status);
5921 if (status) {
5922 mono_image_close (image);
5923 mono_raise_exception (mono_get_exception_file_not_found (fileName));
5926 return mono_module_get_object (mono_domain_get (), image);
5929 #endif /* DISABLE_REFLECTION_EMIT */
5932 * We need to return always the same object for MethodInfo, FieldInfo etc..
5933 * but we need to consider the reflected type.
5934 * type uses a different hash, since it uses custom hash/equal functions.
5937 typedef struct {
5938 gpointer item;
5939 MonoClass *refclass;
5940 } ReflectedEntry;
5942 static gboolean
5943 reflected_equal (gconstpointer a, gconstpointer b) {
5944 const ReflectedEntry *ea = a;
5945 const ReflectedEntry *eb = b;
5947 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
5950 static guint
5951 reflected_hash (gconstpointer a) {
5952 const ReflectedEntry *ea = a;
5953 return mono_aligned_addr_hash (ea->item);
5956 #define CHECK_OBJECT(t,p,k) \
5957 do { \
5958 t _obj; \
5959 ReflectedEntry e; \
5960 e.item = (p); \
5961 e.refclass = (k); \
5962 mono_domain_lock (domain); \
5963 if (!domain->refobject_hash) \
5964 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5965 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
5966 mono_domain_unlock (domain); \
5967 return _obj; \
5969 mono_domain_unlock (domain); \
5970 } while (0)
5972 #ifdef HAVE_BOEHM_GC
5973 /* ReflectedEntry doesn't need to be GC tracked */
5974 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
5975 #define FREE_REFENTRY(entry) g_free ((entry))
5976 #define REFENTRY_REQUIRES_CLEANUP
5977 #else
5978 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5979 /* FIXME: */
5980 #define FREE_REFENTRY(entry)
5981 #endif
5983 #define CACHE_OBJECT(t,p,o,k) \
5984 do { \
5985 t _obj; \
5986 ReflectedEntry pe; \
5987 pe.item = (p); \
5988 pe.refclass = (k); \
5989 mono_domain_lock (domain); \
5990 if (!domain->refobject_hash) \
5991 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5992 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
5993 if (!_obj) { \
5994 ReflectedEntry *e = ALLOC_REFENTRY; \
5995 e->item = (p); \
5996 e->refclass = (k); \
5997 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
5998 _obj = o; \
6000 mono_domain_unlock (domain); \
6001 return _obj; \
6002 } while (0)
6004 static void
6005 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6007 mono_domain_lock (domain);
6008 if (domain->refobject_hash) {
6009 ReflectedEntry pe;
6010 gpointer orig_pe, orig_value;
6012 pe.item = o;
6013 pe.refclass = klass;
6014 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6015 mono_g_hash_table_remove (domain->refobject_hash, &pe);
6016 FREE_REFENTRY (orig_pe);
6019 mono_domain_unlock (domain);
6022 #ifdef REFENTRY_REQUIRES_CLEANUP
6023 static void
6024 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6026 FREE_REFENTRY (key);
6028 #endif
6030 void
6031 mono_reflection_cleanup_domain (MonoDomain *domain)
6033 if (domain->refobject_hash) {
6034 /*let's avoid scanning the whole hashtable if not needed*/
6035 #ifdef REFENTRY_REQUIRES_CLEANUP
6036 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6037 #endif
6038 mono_g_hash_table_destroy (domain->refobject_hash);
6039 domain->refobject_hash = NULL;
6043 #ifndef DISABLE_REFLECTION_EMIT
6044 static gpointer
6045 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6047 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6050 static gpointer
6051 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6053 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6056 void
6057 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6059 MonoDynamicImage *image = moduleb->dynamic_image;
6060 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6061 if (!image) {
6062 MonoError error;
6063 int module_count;
6064 MonoImage **new_modules;
6065 MonoImage *ass;
6066 char *name, *fqname;
6068 * FIXME: we already created an image in mono_image_basic_init (), but
6069 * we don't know which module it belongs to, since that is only
6070 * determined at assembly save time.
6072 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6073 name = mono_string_to_utf8 (ab->name);
6074 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6075 if (!mono_error_ok (&error)) {
6076 g_free (name);
6077 mono_error_raise_exception (&error);
6079 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6081 moduleb->module.image = &image->image;
6082 moduleb->dynamic_image = image;
6083 register_module (mono_object_domain (moduleb), moduleb, image);
6085 /* register the module with the assembly */
6086 ass = ab->dynamic_assembly->assembly.image;
6087 module_count = ass->module_count;
6088 new_modules = g_new0 (MonoImage *, module_count + 1);
6090 if (ass->modules)
6091 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6092 new_modules [module_count] = &image->image;
6093 mono_image_addref (&image->image);
6095 g_free (ass->modules);
6096 ass->modules = new_modules;
6097 ass->module_count ++;
6101 void
6102 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6104 MonoDynamicImage *image = moduleb->dynamic_image;
6106 g_assert (type->type);
6107 image->wrappers_type = mono_class_from_mono_type (type->type);
6110 #endif
6113 * mono_assembly_get_object:
6114 * @domain: an app domain
6115 * @assembly: an assembly
6117 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6119 MonoReflectionAssembly*
6120 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6122 static MonoClass *assembly_type;
6123 MonoReflectionAssembly *res;
6125 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6126 if (!assembly_type) {
6127 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoAssembly");
6128 if (class == NULL)
6129 class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Assembly");
6130 g_assert (class);
6131 assembly_type = class;
6133 res = (MonoReflectionAssembly *)mono_object_new (domain, assembly_type);
6134 res->assembly = assembly;
6136 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6141 MonoReflectionModule*
6142 mono_module_get_object (MonoDomain *domain, MonoImage *image)
6144 static MonoClass *module_type;
6145 MonoReflectionModule *res;
6146 char* basename;
6148 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6149 if (!module_type) {
6150 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6151 if (class == NULL)
6152 class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6153 g_assert (class);
6154 module_type = class;
6156 res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6158 res->image = image;
6159 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6161 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6162 basename = g_path_get_basename (image->name);
6163 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6164 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6166 g_free (basename);
6168 if (image->assembly->image == image) {
6169 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6170 } else {
6171 int i;
6172 res->token = 0;
6173 if (image->assembly->image->modules) {
6174 for (i = 0; i < image->assembly->image->module_count; i++) {
6175 if (image->assembly->image->modules [i] == image)
6176 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6178 g_assert (res->token);
6182 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6185 MonoReflectionModule*
6186 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6188 static MonoClass *module_type;
6189 MonoReflectionModule *res;
6190 MonoTableInfo *table;
6191 guint32 cols [MONO_FILE_SIZE];
6192 const char *name;
6193 guint32 i, name_idx;
6194 const char *val;
6196 if (!module_type) {
6197 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6198 if (class == NULL)
6199 class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6200 g_assert (class);
6201 module_type = class;
6203 res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6205 table = &image->tables [MONO_TABLE_FILE];
6206 g_assert (table_index < table->rows);
6207 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6209 res->image = NULL;
6210 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6211 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6213 /* Check whenever the row has a corresponding row in the moduleref table */
6214 table = &image->tables [MONO_TABLE_MODULEREF];
6215 for (i = 0; i < table->rows; ++i) {
6216 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6217 val = mono_metadata_string_heap (image, name_idx);
6218 if (strcmp (val, name) == 0)
6219 res->image = image->modules [i];
6222 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6223 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6224 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6225 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6226 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6228 return res;
6231 static gboolean
6232 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
6234 if ((t1->type != t2->type) ||
6235 (t1->byref != t2->byref))
6236 return FALSE;
6238 switch (t1->type) {
6239 case MONO_TYPE_VOID:
6240 case MONO_TYPE_BOOLEAN:
6241 case MONO_TYPE_CHAR:
6242 case MONO_TYPE_I1:
6243 case MONO_TYPE_U1:
6244 case MONO_TYPE_I2:
6245 case MONO_TYPE_U2:
6246 case MONO_TYPE_I4:
6247 case MONO_TYPE_U4:
6248 case MONO_TYPE_I8:
6249 case MONO_TYPE_U8:
6250 case MONO_TYPE_R4:
6251 case MONO_TYPE_R8:
6252 case MONO_TYPE_STRING:
6253 case MONO_TYPE_I:
6254 case MONO_TYPE_U:
6255 case MONO_TYPE_OBJECT:
6256 case MONO_TYPE_TYPEDBYREF:
6257 return TRUE;
6258 case MONO_TYPE_VALUETYPE:
6259 case MONO_TYPE_CLASS:
6260 case MONO_TYPE_SZARRAY:
6261 return t1->data.klass == t2->data.klass;
6262 case MONO_TYPE_PTR:
6263 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
6264 case MONO_TYPE_ARRAY:
6265 if (t1->data.array->rank != t2->data.array->rank)
6266 return FALSE;
6267 return t1->data.array->eklass == t2->data.array->eklass;
6268 case MONO_TYPE_GENERICINST: {
6269 int i;
6270 MonoGenericInst *i1 = t1->data.generic_class->context.class_inst;
6271 MonoGenericInst *i2 = t2->data.generic_class->context.class_inst;
6272 if (i1->type_argc != i2->type_argc)
6273 return FALSE;
6274 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
6275 &t2->data.generic_class->container_class->byval_arg))
6276 return FALSE;
6277 /* FIXME: we should probably just compare the instance pointers directly. */
6278 for (i = 0; i < i1->type_argc; ++i) {
6279 if (!mono_metadata_type_equal (i1->type_argv [i], i2->type_argv [i]))
6280 return FALSE;
6282 return TRUE;
6284 case MONO_TYPE_VAR:
6285 case MONO_TYPE_MVAR:
6286 return t1->data.generic_param == t2->data.generic_param;
6287 default:
6288 g_error ("implement type compare for %0x!", t1->type);
6289 return FALSE;
6292 return FALSE;
6295 static guint
6296 mymono_metadata_type_hash (MonoType *t1)
6298 guint hash;
6300 hash = t1->type;
6302 hash |= t1->byref << 6; /* do not collide with t1->type values */
6303 switch (t1->type) {
6304 case MONO_TYPE_VALUETYPE:
6305 case MONO_TYPE_CLASS:
6306 case MONO_TYPE_SZARRAY:
6307 /* check if the distribution is good enough */
6308 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
6309 case MONO_TYPE_PTR:
6310 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
6311 case MONO_TYPE_GENERICINST: {
6312 int i;
6313 MonoGenericInst *inst = t1->data.generic_class->context.class_inst;
6314 hash += g_str_hash (t1->data.generic_class->container_class->name);
6315 hash *= 13;
6316 for (i = 0; i < inst->type_argc; ++i) {
6317 hash += mymono_metadata_type_hash (inst->type_argv [i]);
6318 hash *= 13;
6320 return hash;
6323 return hash;
6326 static MonoReflectionGenericClass*
6327 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
6329 static MonoClass *System_Reflection_MonoGenericClass;
6330 MonoReflectionGenericClass *res;
6331 MonoClass *klass, *gklass;
6332 MonoGenericInst *ginst;
6333 MonoArray *type_args;
6334 int i;
6335 MonoObject *tb;
6337 g_assert (0); /*This code path should not be taken anymore, all MGC instantiation must happen in managed code*/
6339 if (!System_Reflection_MonoGenericClass) {
6340 System_Reflection_MonoGenericClass = mono_class_from_name (
6341 mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
6342 g_assert (System_Reflection_MonoGenericClass);
6345 klass = mono_class_from_mono_type (geninst);
6346 gklass = klass->generic_class->container_class;
6348 mono_class_init (klass);
6350 #ifdef HAVE_SGEN_GC
6351 res = (MonoReflectionGenericClass *) mono_gc_alloc_pinned_obj (mono_class_vtable (domain, System_Reflection_MonoGenericClass), mono_class_instance_size (System_Reflection_MonoGenericClass));
6352 #else
6353 res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
6354 #endif
6356 res->type.type = geninst;
6357 tb = mono_class_get_ref_info (gklass);
6358 g_assert (tb);
6359 g_assert (!strcmp (tb->vtable->klass->name, "TypeBuilder"));
6360 MONO_OBJECT_SETREF (res, generic_type, tb);
6362 ginst = klass->generic_class->context.class_inst;
6363 type_args = mono_array_new (domain, mono_defaults.systemtype_class, ginst->type_argc);
6364 for (i = 0; i < ginst->type_argc; ++i)
6365 mono_array_setref (type_args, i, mono_type_get_object (domain, ginst->type_argv [i]));
6366 MONO_OBJECT_SETREF (res, type_arguments, type_args);
6368 return res;
6371 static gboolean
6372 verify_safe_for_managed_space (MonoType *type)
6374 switch (type->type) {
6375 #ifdef DEBUG_HARDER
6376 case MONO_TYPE_ARRAY:
6377 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6378 case MONO_TYPE_PTR:
6379 return verify_safe_for_managed_space (type->data.type);
6380 case MONO_TYPE_SZARRAY:
6381 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6382 case MONO_TYPE_GENERICINST: {
6383 MonoGenericInst *inst = type->data.generic_class->inst;
6384 int i;
6385 if (!inst->is_open)
6386 break;
6387 for (i = 0; i < inst->type_argc; ++i)
6388 if (!verify_safe_for_managed_space (inst->type_argv [i]))
6389 return FALSE;
6390 break;
6392 #endif
6393 case MONO_TYPE_VAR:
6394 case MONO_TYPE_MVAR:
6395 return TRUE;
6397 return TRUE;
6401 * mono_type_get_object:
6402 * @domain: an app domain
6403 * @type: a type
6405 * Return an System.MonoType object representing the type @type.
6407 MonoReflectionType*
6408 mono_type_get_object (MonoDomain *domain, MonoType *type)
6410 MonoReflectionType *res;
6411 MonoClass *klass = mono_class_from_mono_type (type);
6413 /*we must avoid using @type as it might have come
6414 * from a mono_metadata_type_dup and the caller
6415 * expects that is can be freed.
6416 * Using the right type from
6418 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6420 /* void is very common */
6421 if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6422 return (MonoReflectionType*)domain->typeof_void;
6425 * If the vtable of the given class was already created, we can use
6426 * the MonoType from there and avoid all locking and hash table lookups.
6428 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6429 * that the resulting object is different.
6431 if (type == &klass->byval_arg && !klass->image->dynamic) {
6432 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6433 if (vtable && vtable->type)
6434 return vtable->type;
6437 mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6438 mono_domain_lock (domain);
6439 if (!domain->type_hash)
6440 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash,
6441 (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
6442 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
6443 mono_domain_unlock (domain);
6444 mono_loader_unlock ();
6445 return res;
6447 /* Create a MonoGenericClass object for instantiations of not finished TypeBuilders */
6448 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder) {
6449 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
6450 mono_g_hash_table_insert (domain->type_hash, type, res);
6451 mono_domain_unlock (domain);
6452 mono_loader_unlock ();
6453 return res;
6456 if (!verify_safe_for_managed_space (type)) {
6457 mono_domain_unlock (domain);
6458 mono_loader_unlock ();
6459 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6462 if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
6463 gboolean is_type_done = TRUE;
6464 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
6465 * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
6466 * We can't simply close the types as this will interfere with other parts of the generics machinery.
6468 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
6469 MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
6471 if (gparam->owner && gparam->owner->is_method) {
6472 MonoMethod *method = gparam->owner->owner.method;
6473 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
6474 is_type_done = FALSE;
6475 } else if (gparam->owner && !gparam->owner->is_method) {
6476 MonoClass *klass = gparam->owner->owner.klass;
6477 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
6478 is_type_done = FALSE;
6482 /* g_assert_not_reached (); */
6483 /* should this be considered an error condition? */
6484 if (is_type_done && !type->byref) {
6485 mono_domain_unlock (domain);
6486 mono_loader_unlock ();
6487 return mono_class_get_ref_info (klass);
6490 // FIXME: Get rid of this, do it in the icalls for Type
6491 mono_class_init (klass);
6492 #ifdef HAVE_SGEN_GC
6493 res = (MonoReflectionType *)mono_gc_alloc_pinned_obj (mono_class_vtable (domain, mono_defaults.monotype_class), mono_class_instance_size (mono_defaults.monotype_class));
6494 #else
6495 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
6496 #endif
6497 res->type = type;
6498 mono_g_hash_table_insert (domain->type_hash, type, res);
6500 if (type->type == MONO_TYPE_VOID)
6501 domain->typeof_void = (MonoObject*)res;
6503 mono_domain_unlock (domain);
6504 mono_loader_unlock ();
6505 return res;
6509 * mono_method_get_object:
6510 * @domain: an app domain
6511 * @method: a method
6512 * @refclass: the reflected type (can be NULL)
6514 * Return an System.Reflection.MonoMethod object representing the method @method.
6516 MonoReflectionMethod*
6517 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6520 * We use the same C representation for methods and constructors, but the type
6521 * name in C# is different.
6523 static MonoClass *System_Reflection_MonoMethod = NULL;
6524 static MonoClass *System_Reflection_MonoCMethod = NULL;
6525 static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6526 static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6527 MonoClass *klass;
6528 MonoReflectionMethod *ret;
6530 if (method->is_inflated) {
6531 MonoReflectionGenericMethod *gret;
6533 refclass = method->klass;
6534 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6535 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6536 if (!System_Reflection_MonoGenericCMethod)
6537 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6538 klass = System_Reflection_MonoGenericCMethod;
6539 } else {
6540 if (!System_Reflection_MonoGenericMethod)
6541 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6542 klass = System_Reflection_MonoGenericMethod;
6544 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6545 gret->method.method = method;
6546 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6547 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6548 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6551 if (!refclass)
6552 refclass = method->klass;
6554 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6555 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6556 if (!System_Reflection_MonoCMethod)
6557 System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6558 klass = System_Reflection_MonoCMethod;
6560 else {
6561 if (!System_Reflection_MonoMethod)
6562 System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6563 klass = System_Reflection_MonoMethod;
6565 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6566 ret->method = method;
6567 MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6568 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6572 * mono_method_clear_object:
6574 * Clear the cached reflection objects for the dynamic method METHOD.
6576 void
6577 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
6579 MonoClass *klass;
6580 g_assert (method->dynamic);
6582 klass = method->klass;
6583 while (klass) {
6584 clear_cached_object (domain, method, klass);
6585 klass = klass->parent;
6587 /* Added by mono_param_get_objects () */
6588 clear_cached_object (domain, &(method->signature), NULL);
6589 klass = method->klass;
6590 while (klass) {
6591 clear_cached_object (domain, &(method->signature), klass);
6592 klass = klass->parent;
6597 * mono_field_get_object:
6598 * @domain: an app domain
6599 * @klass: a type
6600 * @field: a field
6602 * Return an System.Reflection.MonoField object representing the field @field
6603 * in class @klass.
6605 MonoReflectionField*
6606 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6608 MonoReflectionField *res;
6609 static MonoClass *monofield_klass;
6611 CHECK_OBJECT (MonoReflectionField *, field, klass);
6612 if (!monofield_klass)
6613 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6614 res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6615 res->klass = klass;
6616 res->field = field;
6617 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6618 if (is_field_on_inst (field))
6619 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6620 else
6621 res->attrs = field->type->attrs;
6622 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6623 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6627 * mono_property_get_object:
6628 * @domain: an app domain
6629 * @klass: a type
6630 * @property: a property
6632 * Return an System.Reflection.MonoProperty object representing the property @property
6633 * in class @klass.
6635 MonoReflectionProperty*
6636 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6638 MonoReflectionProperty *res;
6639 static MonoClass *monoproperty_klass;
6641 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6642 if (!monoproperty_klass)
6643 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6644 res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6645 res->klass = klass;
6646 res->property = property;
6647 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6651 * mono_event_get_object:
6652 * @domain: an app domain
6653 * @klass: a type
6654 * @event: a event
6656 * Return an System.Reflection.MonoEvent object representing the event @event
6657 * in class @klass.
6659 MonoReflectionEvent*
6660 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6662 MonoReflectionEvent *res;
6663 MonoReflectionMonoEvent *mono_event;
6664 static MonoClass *monoevent_klass;
6666 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6667 if (!monoevent_klass)
6668 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6669 mono_event = (MonoReflectionMonoEvent *)mono_object_new (domain, monoevent_klass);
6670 mono_event->klass = klass;
6671 mono_event->event = event;
6672 res = (MonoReflectionEvent*)mono_event;
6673 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6677 * mono_get_reflection_missing_object:
6678 * @domain: Domain where the object lives
6680 * Returns the System.Reflection.Missing.Value singleton object
6681 * (of type System.Reflection.Missing).
6683 * Used as the value for ParameterInfo.DefaultValue when Optional
6684 * is present
6686 static MonoObject *
6687 mono_get_reflection_missing_object (MonoDomain *domain)
6689 MonoObject *obj;
6690 static MonoClassField *missing_value_field = NULL;
6692 if (!missing_value_field) {
6693 MonoClass *missing_klass;
6694 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6695 mono_class_init (missing_klass);
6696 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6697 g_assert (missing_value_field);
6699 obj = mono_field_get_value_object (domain, missing_value_field, NULL);
6700 g_assert (obj);
6701 return obj;
6704 static MonoObject*
6705 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6707 if (!*dbnull)
6708 *dbnull = mono_get_dbnull_object (domain);
6709 return *dbnull;
6712 static MonoObject*
6713 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6715 if (!*reflection_missing)
6716 *reflection_missing = mono_get_reflection_missing_object (domain);
6717 return *reflection_missing;
6721 * mono_param_get_objects:
6722 * @domain: an app domain
6723 * @method: a method
6725 * Return an System.Reflection.ParameterInfo array object representing the parameters
6726 * in the method @method.
6728 MonoArray*
6729 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6731 static MonoClass *System_Reflection_ParameterInfo;
6732 static MonoClass *System_Reflection_ParameterInfo_array;
6733 MonoArray *res = NULL;
6734 MonoReflectionMethod *member = NULL;
6735 MonoReflectionParameter *param = NULL;
6736 char **names, **blobs = NULL;
6737 guint32 *types = NULL;
6738 MonoType *type = NULL;
6739 MonoObject *dbnull = NULL;
6740 MonoObject *missing = NULL;
6741 MonoMarshalSpec **mspecs;
6742 MonoMethodSignature *sig;
6743 MonoVTable *pinfo_vtable;
6744 int i;
6746 if (!System_Reflection_ParameterInfo_array) {
6747 MonoClass *klass;
6749 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6750 mono_memory_barrier ();
6751 System_Reflection_ParameterInfo = klass;
6753 klass = mono_array_class_get (klass, 1);
6754 mono_memory_barrier ();
6755 System_Reflection_ParameterInfo_array = klass;
6758 if (!mono_method_signature (method)->param_count)
6759 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6761 /* Note: the cache is based on the address of the signature into the method
6762 * since we already cache MethodInfos with the method as keys.
6764 CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
6766 sig = mono_method_signature (method);
6767 member = mono_method_get_object (domain, method, refclass);
6768 names = g_new (char *, sig->param_count);
6769 mono_method_get_param_names (method, (const char **) names);
6771 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
6772 mono_method_get_marshal_info (method, mspecs);
6774 res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
6775 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
6776 for (i = 0; i < sig->param_count; ++i) {
6777 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
6778 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
6779 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
6780 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
6781 param->PositionImpl = i;
6782 param->AttrsImpl = sig->params [i]->attrs;
6784 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
6785 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6786 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6787 else
6788 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6789 } else {
6791 if (!blobs) {
6792 blobs = g_new0 (char *, sig->param_count);
6793 types = g_new0 (guint32, sig->param_count);
6794 get_default_param_value_blobs (method, blobs, types);
6797 /* Build MonoType for the type from the Constant Table */
6798 if (!type)
6799 type = g_new0 (MonoType, 1);
6800 type->type = types [i];
6801 type->data.klass = NULL;
6802 if (types [i] == MONO_TYPE_CLASS)
6803 type->data.klass = mono_defaults.object_class;
6804 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
6805 /* For enums, types [i] contains the base type */
6807 type->type = MONO_TYPE_VALUETYPE;
6808 type->data.klass = mono_class_from_mono_type (sig->params [i]);
6809 } else
6810 type->data.klass = mono_class_from_mono_type (type);
6812 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
6814 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6815 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
6816 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6817 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6818 else
6819 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6824 if (mspecs [i + 1])
6825 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
6827 mono_array_setref (res, i, param);
6829 g_free (names);
6830 g_free (blobs);
6831 g_free (types);
6832 g_free (type);
6834 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
6835 if (mspecs [i])
6836 mono_metadata_free_marshal_spec (mspecs [i]);
6837 g_free (mspecs);
6839 CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
6842 MonoArray*
6843 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
6845 return mono_param_get_objects_internal (domain, method, NULL);
6849 * mono_method_body_get_object:
6850 * @domain: an app domain
6851 * @method: a method
6853 * Return an System.Reflection.MethodBody object representing the method @method.
6855 MonoReflectionMethodBody*
6856 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
6858 static MonoClass *System_Reflection_MethodBody = NULL;
6859 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
6860 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
6861 MonoReflectionMethodBody *ret;
6862 MonoMethodHeader *header;
6863 guint32 method_rva, local_var_sig_token;
6864 char *ptr;
6865 unsigned char format, flags;
6866 int i;
6868 if (!System_Reflection_MethodBody)
6869 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
6870 if (!System_Reflection_LocalVariableInfo)
6871 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
6872 if (!System_Reflection_ExceptionHandlingClause)
6873 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
6875 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
6877 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6878 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
6879 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
6880 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
6881 return NULL;
6882 header = mono_method_get_header (method);
6884 /* Obtain local vars signature token */
6885 method_rva = mono_metadata_decode_row_col (&method->klass->image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
6886 ptr = mono_image_rva_map (method->klass->image, method_rva);
6887 flags = *(const unsigned char *) ptr;
6888 format = flags & METHOD_HEADER_FORMAT_MASK;
6889 switch (format){
6890 case METHOD_HEADER_TINY_FORMAT:
6891 local_var_sig_token = 0;
6892 break;
6893 case METHOD_HEADER_FAT_FORMAT:
6894 ptr += 2;
6895 ptr += 2;
6896 ptr += 4;
6897 local_var_sig_token = read32 (ptr);
6898 break;
6899 default:
6900 g_assert_not_reached ();
6903 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
6905 ret->init_locals = header->init_locals;
6906 ret->max_stack = header->max_stack;
6907 ret->local_var_sig_token = local_var_sig_token;
6908 MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
6909 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
6911 /* Locals */
6912 MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
6913 for (i = 0; i < header->num_locals; ++i) {
6914 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
6915 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
6916 info->is_pinned = header->locals [i]->pinned;
6917 info->local_index = i;
6918 mono_array_setref (ret->locals, i, info);
6921 /* Exceptions */
6922 MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
6923 for (i = 0; i < header->num_clauses; ++i) {
6924 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
6925 MonoExceptionClause *clause = &header->clauses [i];
6927 info->flags = clause->flags;
6928 info->try_offset = clause->try_offset;
6929 info->try_length = clause->try_len;
6930 info->handler_offset = clause->handler_offset;
6931 info->handler_length = clause->handler_len;
6932 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
6933 info->filter_offset = clause->data.filter_offset;
6934 else if (clause->data.catch_class)
6935 MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
6937 mono_array_setref (ret->clauses, i, info);
6940 mono_metadata_free_mh (header);
6941 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
6942 return ret;
6946 * mono_get_dbnull_object:
6947 * @domain: Domain where the object lives
6949 * Returns the System.DBNull.Value singleton object
6951 * Used as the value for ParameterInfo.DefaultValue
6953 MonoObject *
6954 mono_get_dbnull_object (MonoDomain *domain)
6956 MonoObject *obj;
6957 static MonoClassField *dbnull_value_field = NULL;
6959 if (!dbnull_value_field) {
6960 MonoClass *dbnull_klass;
6961 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
6962 mono_class_init (dbnull_klass);
6963 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
6964 g_assert (dbnull_value_field);
6966 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
6967 g_assert (obj);
6968 return obj;
6971 static void
6972 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
6974 guint32 param_index, i, lastp, crow = 0;
6975 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
6976 gint32 idx;
6978 MonoClass *klass = method->klass;
6979 MonoImage *image = klass->image;
6980 MonoMethodSignature *methodsig = mono_method_signature (method);
6982 MonoTableInfo *constt;
6983 MonoTableInfo *methodt;
6984 MonoTableInfo *paramt;
6986 if (!methodsig->param_count)
6987 return;
6989 mono_class_init (klass);
6991 if (klass->image->dynamic) {
6992 MonoReflectionMethodAux *aux;
6993 if (method->is_inflated)
6994 method = ((MonoMethodInflated*)method)->declaring;
6995 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6996 if (aux && aux->param_defaults) {
6997 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
6998 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7000 return;
7003 methodt = &klass->image->tables [MONO_TABLE_METHOD];
7004 paramt = &klass->image->tables [MONO_TABLE_PARAM];
7005 constt = &image->tables [MONO_TABLE_CONSTANT];
7007 idx = mono_method_get_index (method) - 1;
7008 g_assert (idx != -1);
7010 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7011 if (idx + 1 < methodt->rows)
7012 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7013 else
7014 lastp = paramt->rows + 1;
7016 for (i = param_index; i < lastp; ++i) {
7017 guint32 paramseq;
7019 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7020 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7022 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7023 continue;
7025 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7026 if (!crow) {
7027 continue;
7030 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7031 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7032 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7035 return;
7038 MonoObject *
7039 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7041 void *retval;
7042 MonoClass *klass;
7043 MonoObject *object;
7044 MonoType *basetype = type;
7046 if (!blob)
7047 return NULL;
7049 klass = mono_class_from_mono_type (type);
7050 if (klass->valuetype) {
7051 object = mono_object_new (domain, klass);
7052 retval = ((gchar *) object + sizeof (MonoObject));
7053 if (klass->enumtype)
7054 basetype = mono_class_enum_basetype (klass);
7055 } else {
7056 retval = &object;
7059 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
7060 return object;
7061 else
7062 return NULL;
7065 static int
7066 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7067 int found_sep;
7068 char *s;
7070 memset (assembly, 0, sizeof (MonoAssemblyName));
7071 assembly->name = p;
7072 assembly->culture = "";
7073 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7075 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
7076 p++;
7077 found_sep = 0;
7078 while (g_ascii_isspace (*p) || *p == ',') {
7079 *p++ = 0;
7080 found_sep = 1;
7081 continue;
7083 /* failed */
7084 if (!found_sep)
7085 return 1;
7086 while (*p) {
7087 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7088 p += 8;
7089 assembly->major = strtoul (p, &s, 10);
7090 if (s == p || *s != '.')
7091 return 1;
7092 p = ++s;
7093 assembly->minor = strtoul (p, &s, 10);
7094 if (s == p || *s != '.')
7095 return 1;
7096 p = ++s;
7097 assembly->build = strtoul (p, &s, 10);
7098 if (s == p || *s != '.')
7099 return 1;
7100 p = ++s;
7101 assembly->revision = strtoul (p, &s, 10);
7102 if (s == p)
7103 return 1;
7104 p = s;
7105 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7106 p += 8;
7107 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7108 assembly->culture = "";
7109 p += 7;
7110 } else {
7111 assembly->culture = p;
7112 while (*p && *p != ',') {
7113 p++;
7116 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7117 p += 15;
7118 if (strncmp (p, "null", 4) == 0) {
7119 p += 4;
7120 } else {
7121 int len;
7122 gchar *start = p;
7123 while (*p && *p != ',') {
7124 p++;
7126 len = (p - start + 1);
7127 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7128 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7129 g_strlcpy ((char*)assembly->public_key_token, start, len);
7131 } else {
7132 while (*p && *p != ',')
7133 p++;
7135 found_sep = 0;
7136 while (g_ascii_isspace (*p) || *p == ',') {
7137 *p++ = 0;
7138 found_sep = 1;
7139 continue;
7141 /* failed */
7142 if (!found_sep)
7143 return 1;
7146 return 0;
7150 * mono_reflection_parse_type:
7151 * @name: type name
7153 * Parse a type name as accepted by the GetType () method and output the info
7154 * extracted in the info structure.
7155 * the name param will be mangled, so, make a copy before passing it to this function.
7156 * The fields in info will be valid until the memory pointed to by name is valid.
7158 * See also mono_type_get_name () below.
7160 * Returns: 0 on parse error.
7162 static int
7163 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7164 MonoTypeNameParse *info)
7166 char *start, *p, *w, *temp, *last_point, *startn;
7167 int in_modifiers = 0;
7168 int isbyref = 0, rank, arity = 0, i;
7170 start = p = w = name;
7172 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7173 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7174 info->name = info->name_space = NULL;
7175 info->nested = NULL;
7176 info->modifiers = NULL;
7177 info->type_arguments = NULL;
7179 /* last_point separates the namespace from the name */
7180 last_point = NULL;
7181 /* Skips spaces */
7182 while (*p == ' ') p++, start++, w++, name++;
7184 while (*p) {
7185 switch (*p) {
7186 case '+':
7187 *p = 0; /* NULL terminate the name */
7188 startn = p + 1;
7189 info->nested = g_list_append (info->nested, startn);
7190 /* we have parsed the nesting namespace + name */
7191 if (info->name)
7192 break;
7193 if (last_point) {
7194 info->name_space = start;
7195 *last_point = 0;
7196 info->name = last_point + 1;
7197 } else {
7198 info->name_space = (char *)"";
7199 info->name = start;
7201 break;
7202 case '.':
7203 last_point = p;
7204 break;
7205 case '\\':
7206 ++p;
7207 break;
7208 case '&':
7209 case '*':
7210 case '[':
7211 case ',':
7212 case ']':
7213 in_modifiers = 1;
7214 break;
7215 case '`':
7216 ++p;
7217 i = strtol (p, &temp, 10);
7218 arity += i;
7219 if (p == temp)
7220 return 0;
7221 p = temp-1;
7222 break;
7223 default:
7224 break;
7226 if (in_modifiers)
7227 break;
7228 // *w++ = *p++;
7229 p++;
7232 if (!info->name) {
7233 if (last_point) {
7234 info->name_space = start;
7235 *last_point = 0;
7236 info->name = last_point + 1;
7237 } else {
7238 info->name_space = (char *)"";
7239 info->name = start;
7242 while (*p) {
7243 switch (*p) {
7244 case '&':
7245 if (isbyref) /* only one level allowed by the spec */
7246 return 0;
7247 isbyref = 1;
7248 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7249 *p++ = 0;
7250 break;
7251 case '*':
7252 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7253 *p++ = 0;
7254 break;
7255 case '[':
7256 if (arity != 0) {
7257 *p++ = 0;
7258 info->type_arguments = g_ptr_array_new ();
7259 for (i = 0; i < arity; i++) {
7260 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7261 gboolean fqname = FALSE;
7263 g_ptr_array_add (info->type_arguments, subinfo);
7265 if (*p == '[') {
7266 p++;
7267 fqname = TRUE;
7270 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7271 return 0;
7273 if (fqname) {
7274 char *aname;
7276 if (*p != ',')
7277 return 0;
7278 *p++ = 0;
7280 aname = p;
7281 while (*p && (*p != ']'))
7282 p++;
7284 if (*p != ']')
7285 return 0;
7287 *p++ = 0;
7288 while (*aname) {
7289 if (g_ascii_isspace (*aname)) {
7290 ++aname;
7291 continue;
7293 break;
7295 if (!*aname ||
7296 !assembly_name_to_aname (&subinfo->assembly, aname))
7297 return 0;
7300 if (i + 1 < arity) {
7301 if (*p != ',')
7302 return 0;
7303 } else {
7304 if (*p != ']')
7305 return 0;
7307 *p++ = 0;
7310 arity = 0;
7311 break;
7313 rank = 1;
7314 *p++ = 0;
7315 while (*p) {
7316 if (*p == ']')
7317 break;
7318 if (*p == ',')
7319 rank++;
7320 else if (*p == '*') /* '*' means unknown lower bound */
7321 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7322 else
7323 return 0;
7324 ++p;
7326 if (*p++ != ']')
7327 return 0;
7328 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7329 break;
7330 case ']':
7331 if (is_recursed)
7332 goto end;
7333 return 0;
7334 case ',':
7335 if (is_recursed)
7336 goto end;
7337 *p++ = 0;
7338 while (*p) {
7339 if (g_ascii_isspace (*p)) {
7340 ++p;
7341 continue;
7343 break;
7345 if (!*p)
7346 return 0; /* missing assembly name */
7347 if (!assembly_name_to_aname (&info->assembly, p))
7348 return 0;
7349 break;
7350 default:
7351 return 0;
7353 if (info->assembly.name)
7354 break;
7356 // *w = 0; /* terminate class name */
7357 end:
7358 if (!info->name || !*info->name)
7359 return 0;
7360 if (endptr)
7361 *endptr = p;
7362 /* add other consistency checks */
7363 return 1;
7367 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7369 return _mono_reflection_parse_type (name, NULL, FALSE, info);
7372 static MonoType*
7373 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7375 gboolean type_resolve = FALSE;
7376 MonoType *type;
7377 MonoImage *rootimage = image;
7379 if (info->assembly.name) {
7380 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7381 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7383 * This could happen in the AOT compiler case when the search hook is not
7384 * installed.
7386 assembly = image->assembly;
7387 if (!assembly) {
7388 /* then we must load the assembly ourselve - see #60439 */
7389 assembly = mono_assembly_load (&info->assembly, NULL, NULL);
7390 if (!assembly)
7391 return NULL;
7393 image = assembly->image;
7394 } else if (!image) {
7395 image = mono_defaults.corlib;
7398 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7399 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7400 image = mono_defaults.corlib;
7401 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7404 return type;
7407 static MonoType*
7408 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7410 MonoClass *klass;
7411 GList *mod;
7412 int modval;
7413 gboolean bounded = FALSE;
7415 if (!image)
7416 image = mono_defaults.corlib;
7418 if (ignorecase)
7419 klass = mono_class_from_name_case (image, info->name_space, info->name);
7420 else
7421 klass = mono_class_from_name (image, info->name_space, info->name);
7422 if (!klass)
7423 return NULL;
7424 for (mod = info->nested; mod; mod = mod->next) {
7425 gpointer iter = NULL;
7426 MonoClass *parent;
7428 parent = klass;
7429 mono_class_init (parent);
7431 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7432 if (ignorecase) {
7433 if (mono_utf8_strcasecmp (klass->name, mod->data) == 0)
7434 break;
7435 } else {
7436 if (strcmp (klass->name, mod->data) == 0)
7437 break;
7440 if (!klass)
7441 break;
7443 if (!klass)
7444 return NULL;
7445 mono_class_init (klass);
7447 if (info->type_arguments) {
7448 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7449 MonoReflectionType *the_type;
7450 MonoType *instance;
7451 int i;
7453 for (i = 0; i < info->type_arguments->len; i++) {
7454 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7456 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7457 if (!type_args [i]) {
7458 g_free (type_args);
7459 return NULL;
7463 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7465 instance = mono_reflection_bind_generic_parameters (
7466 the_type, info->type_arguments->len, type_args);
7468 g_free (type_args);
7469 if (!instance)
7470 return NULL;
7472 klass = mono_class_from_mono_type (instance);
7475 for (mod = info->modifiers; mod; mod = mod->next) {
7476 modval = GPOINTER_TO_UINT (mod->data);
7477 if (!modval) { /* byref: must be last modifier */
7478 return &klass->this_arg;
7479 } else if (modval == -1) {
7480 klass = mono_ptr_class_get (&klass->byval_arg);
7481 } else if (modval == -2) {
7482 bounded = TRUE;
7483 } else { /* array rank */
7484 klass = mono_bounded_array_class_get (klass, modval, bounded);
7486 mono_class_init (klass);
7489 return &klass->byval_arg;
7493 * mono_reflection_get_type:
7494 * @image: a metadata context
7495 * @info: type description structure
7496 * @ignorecase: flag for case-insensitive string compares
7497 * @type_resolve: whenever type resolve was already tried
7499 * Build a MonoType from the type description in @info.
7503 MonoType*
7504 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7505 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7508 static MonoType*
7509 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7511 MonoReflectionAssemblyBuilder *abuilder;
7512 MonoType *type;
7513 int i;
7515 g_assert (assembly->dynamic);
7516 abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (((MonoDynamicAssembly*)assembly)->domain, assembly);
7518 /* Enumerate all modules */
7520 type = NULL;
7521 if (abuilder->modules) {
7522 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7523 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7524 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7525 if (type)
7526 break;
7530 if (!type && abuilder->loaded_modules) {
7531 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7532 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7533 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7534 if (type)
7535 break;
7539 return type;
7542 MonoType*
7543 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7545 MonoType *type;
7546 MonoReflectionAssembly *assembly;
7547 GString *fullName;
7548 GList *mod;
7550 if (image && image->dynamic)
7551 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7552 else
7553 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7554 if (type)
7555 return type;
7556 if (!mono_domain_has_type_resolve (mono_domain_get ()))
7557 return NULL;
7559 if (type_resolve) {
7560 if (*type_resolve)
7561 return NULL;
7562 else
7563 *type_resolve = TRUE;
7566 /* Reconstruct the type name */
7567 fullName = g_string_new ("");
7568 if (info->name_space && (info->name_space [0] != '\0'))
7569 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7570 else
7571 g_string_printf (fullName, "%s", info->name);
7572 for (mod = info->nested; mod; mod = mod->next)
7573 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7575 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7576 if (assembly) {
7577 if (assembly->assembly->dynamic)
7578 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7579 else
7580 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
7581 info, ignorecase);
7583 g_string_free (fullName, TRUE);
7584 return type;
7587 void
7588 mono_reflection_free_type_info (MonoTypeNameParse *info)
7590 g_list_free (info->modifiers);
7591 g_list_free (info->nested);
7593 if (info->type_arguments) {
7594 int i;
7596 for (i = 0; i < info->type_arguments->len; i++) {
7597 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7599 mono_reflection_free_type_info (subinfo);
7600 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7601 g_free (subinfo);
7604 g_ptr_array_free (info->type_arguments, TRUE);
7609 * mono_reflection_type_from_name:
7610 * @name: type name.
7611 * @image: a metadata context (can be NULL).
7613 * Retrieves a MonoType from its @name. If the name is not fully qualified,
7614 * it defaults to get the type from @image or, if @image is NULL or loading
7615 * from it fails, uses corlib.
7618 MonoType*
7619 mono_reflection_type_from_name (char *name, MonoImage *image)
7621 MonoType *type = NULL;
7622 MonoTypeNameParse info;
7623 char *tmp;
7625 /* Make a copy since parse_type modifies its argument */
7626 tmp = g_strdup (name);
7628 /*g_print ("requested type %s\n", str);*/
7629 if (mono_reflection_parse_type (tmp, &info)) {
7630 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7633 g_free (tmp);
7634 mono_reflection_free_type_info (&info);
7635 return type;
7639 * mono_reflection_get_token:
7641 * Return the metadata token of OBJ which should be an object
7642 * representing a metadata element.
7644 guint32
7645 mono_reflection_get_token (MonoObject *obj)
7647 MonoClass *klass;
7648 guint32 token = 0;
7650 klass = obj->vtable->klass;
7652 if (strcmp (klass->name, "MethodBuilder") == 0) {
7653 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7655 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7656 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7657 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7659 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7660 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7661 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7663 /* Call mono_image_create_token so the object gets added to the tokens hash table */
7664 token = mono_image_create_token (((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image, obj, FALSE, TRUE);
7665 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7666 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7667 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7668 } else if (strcmp (klass->name, "MonoType") == 0) {
7669 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
7670 token = mono_class_from_mono_type (type)->type_token;
7671 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7672 strcmp (klass->name, "MonoMethod") == 0 ||
7673 strcmp (klass->name, "MonoGenericMethod") == 0 ||
7674 strcmp (klass->name, "MonoGenericCMethod") == 0) {
7675 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7676 if (m->method->is_inflated) {
7677 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7678 return inflated->declaring->token;
7679 } else {
7680 token = m->method->token;
7682 } else if (strcmp (klass->name, "MonoField") == 0) {
7683 MonoReflectionField *f = (MonoReflectionField*)obj;
7685 if (is_field_on_inst (f->field)) {
7686 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
7687 int field_index = f->field - dgclass->fields;
7688 MonoObject *obj;
7690 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
7691 obj = dgclass->field_objects [field_index];
7692 return mono_reflection_get_token (obj);
7694 token = mono_class_get_field_token (f->field);
7695 } else if (strcmp (klass->name, "MonoProperty") == 0) {
7696 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7698 token = mono_class_get_property_token (p->property);
7699 } else if (strcmp (klass->name, "MonoEvent") == 0) {
7700 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
7702 token = mono_class_get_event_token (p->event);
7703 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
7704 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7705 MonoClass *member_class = mono_object_class (p->MemberImpl);
7706 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
7708 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7709 } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
7710 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7712 token = m->token;
7713 } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
7714 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7715 } else {
7716 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7717 MonoException *ex = mono_get_exception_not_implemented (msg);
7718 g_free (msg);
7719 mono_raise_exception (ex);
7722 return token;
7725 static void*
7726 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
7728 int slen, type = t->type;
7729 MonoClass *tklass = t->data.klass;
7731 handle_enum:
7732 switch (type) {
7733 case MONO_TYPE_U1:
7734 case MONO_TYPE_I1:
7735 case MONO_TYPE_BOOLEAN: {
7736 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7737 *bval = *p;
7738 *end = p + 1;
7739 return bval;
7741 case MONO_TYPE_CHAR:
7742 case MONO_TYPE_U2:
7743 case MONO_TYPE_I2: {
7744 guint16 *val = g_malloc (sizeof (guint16));
7745 *val = read16 (p);
7746 *end = p + 2;
7747 return val;
7749 #if SIZEOF_VOID_P == 4
7750 case MONO_TYPE_U:
7751 case MONO_TYPE_I:
7752 #endif
7753 case MONO_TYPE_R4:
7754 case MONO_TYPE_U4:
7755 case MONO_TYPE_I4: {
7756 guint32 *val = g_malloc (sizeof (guint32));
7757 *val = read32 (p);
7758 *end = p + 4;
7759 return val;
7761 #if SIZEOF_VOID_P == 8
7762 case MONO_TYPE_U: /* error out instead? this should probably not happen */
7763 case MONO_TYPE_I:
7764 #endif
7765 case MONO_TYPE_U8:
7766 case MONO_TYPE_I8: {
7767 guint64 *val = g_malloc (sizeof (guint64));
7768 *val = read64 (p);
7769 *end = p + 8;
7770 return val;
7772 case MONO_TYPE_R8: {
7773 double *val = g_malloc (sizeof (double));
7774 readr8 (p, val);
7775 *end = p + 8;
7776 return val;
7778 case MONO_TYPE_VALUETYPE:
7779 if (t->data.klass->enumtype) {
7780 type = mono_class_enum_basetype (t->data.klass)->type;
7781 goto handle_enum;
7782 } else {
7783 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7785 break;
7786 case MONO_TYPE_STRING:
7787 if (*p == (char)0xFF) {
7788 *end = p + 1;
7789 return NULL;
7791 slen = mono_metadata_decode_value (p, &p);
7792 *end = p + slen;
7793 return mono_string_new_len (mono_domain_get (), p, slen);
7794 case MONO_TYPE_CLASS: {
7795 char *n;
7796 MonoType *t;
7797 if (*p == (char)0xFF) {
7798 *end = p + 1;
7799 return NULL;
7801 handle_type:
7802 slen = mono_metadata_decode_value (p, &p);
7803 n = g_memdup (p, slen + 1);
7804 n [slen] = 0;
7805 t = mono_reflection_type_from_name (n, image);
7806 if (!t)
7807 g_warning ("Cannot load type '%s'", n);
7808 g_free (n);
7809 *end = p + slen;
7810 if (t)
7811 return mono_type_get_object (mono_domain_get (), t);
7812 else
7813 return NULL;
7815 case MONO_TYPE_OBJECT: {
7816 char subt = *p++;
7817 MonoObject *obj;
7818 MonoClass *subc = NULL;
7819 void *val;
7821 if (subt == 0x50) {
7822 goto handle_type;
7823 } else if (subt == 0x0E) {
7824 type = MONO_TYPE_STRING;
7825 goto handle_enum;
7826 } else if (subt == 0x1D) {
7827 MonoType simple_type = {{0}};
7828 int etype = *p;
7829 p ++;
7831 if (etype == 0x51)
7832 /* See Partition II, Appendix B3 */
7833 etype = MONO_TYPE_OBJECT;
7834 type = MONO_TYPE_SZARRAY;
7835 simple_type.type = etype;
7836 tklass = mono_class_from_mono_type (&simple_type);
7837 goto handle_enum;
7838 } else if (subt == 0x55) {
7839 char *n;
7840 MonoType *t;
7841 slen = mono_metadata_decode_value (p, &p);
7842 n = g_memdup (p, slen + 1);
7843 n [slen] = 0;
7844 t = mono_reflection_type_from_name (n, image);
7845 if (!t)
7846 g_error ("Cannot load type '%s'", n);
7847 g_free (n);
7848 p += slen;
7849 subc = mono_class_from_mono_type (t);
7850 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
7851 MonoType simple_type = {{0}};
7852 simple_type.type = subt;
7853 subc = mono_class_from_mono_type (&simple_type);
7854 } else {
7855 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
7857 val = load_cattr_value (image, &subc->byval_arg, p, end);
7858 obj = mono_object_new (mono_domain_get (), subc);
7859 g_assert (!subc->has_references);
7860 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
7861 g_free (val);
7862 return obj;
7864 case MONO_TYPE_SZARRAY: {
7865 MonoArray *arr;
7866 guint32 i, alen, basetype;
7867 alen = read32 (p);
7868 p += 4;
7869 if (alen == 0xffffffff) {
7870 *end = p;
7871 return NULL;
7873 arr = mono_array_new (mono_domain_get(), tklass, alen);
7874 basetype = tklass->byval_arg.type;
7875 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
7876 basetype = mono_class_enum_basetype (tklass)->type;
7877 switch (basetype)
7879 case MONO_TYPE_U1:
7880 case MONO_TYPE_I1:
7881 case MONO_TYPE_BOOLEAN:
7882 for (i = 0; i < alen; i++) {
7883 MonoBoolean val = *p++;
7884 mono_array_set (arr, MonoBoolean, i, val);
7886 break;
7887 case MONO_TYPE_CHAR:
7888 case MONO_TYPE_U2:
7889 case MONO_TYPE_I2:
7890 for (i = 0; i < alen; i++) {
7891 guint16 val = read16 (p);
7892 mono_array_set (arr, guint16, i, val);
7893 p += 2;
7895 break;
7896 case MONO_TYPE_R4:
7897 case MONO_TYPE_U4:
7898 case MONO_TYPE_I4:
7899 for (i = 0; i < alen; i++) {
7900 guint32 val = read32 (p);
7901 mono_array_set (arr, guint32, i, val);
7902 p += 4;
7904 break;
7905 case MONO_TYPE_R8:
7906 for (i = 0; i < alen; i++) {
7907 double val;
7908 readr8 (p, &val);
7909 mono_array_set (arr, double, i, val);
7910 p += 8;
7912 break;
7913 case MONO_TYPE_U8:
7914 case MONO_TYPE_I8:
7915 for (i = 0; i < alen; i++) {
7916 guint64 val = read64 (p);
7917 mono_array_set (arr, guint64, i, val);
7918 p += 8;
7920 break;
7921 case MONO_TYPE_CLASS:
7922 case MONO_TYPE_OBJECT:
7923 case MONO_TYPE_STRING:
7924 for (i = 0; i < alen; i++) {
7925 MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
7926 mono_array_setref (arr, i, item);
7928 break;
7929 default:
7930 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
7932 *end=p;
7933 return arr;
7935 default:
7936 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
7938 return NULL;
7941 static MonoObject*
7942 create_cattr_typed_arg (MonoType *t, MonoObject *val)
7944 static MonoClass *klass;
7945 static MonoMethod *ctor;
7946 MonoObject *retval;
7947 void *params [2], *unboxed;
7949 if (!klass)
7950 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
7951 if (!ctor)
7952 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7954 params [0] = mono_type_get_object (mono_domain_get (), t);
7955 params [1] = val;
7956 retval = mono_object_new (mono_domain_get (), klass);
7957 unboxed = mono_object_unbox (retval);
7958 mono_runtime_invoke (ctor, unboxed, params, NULL);
7960 return retval;
7963 static MonoObject*
7964 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
7966 static MonoClass *klass;
7967 static MonoMethod *ctor;
7968 MonoObject *retval;
7969 void *unboxed, *params [2];
7971 if (!klass)
7972 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
7973 if (!ctor)
7974 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7976 params [0] = minfo;
7977 params [1] = typedarg;
7978 retval = mono_object_new (mono_domain_get (), klass);
7979 unboxed = mono_object_unbox (retval);
7980 mono_runtime_invoke (ctor, unboxed, params, NULL);
7982 return retval;
7985 static gboolean
7986 type_is_reference (MonoType *type)
7988 switch (type->type) {
7989 case MONO_TYPE_BOOLEAN:
7990 case MONO_TYPE_CHAR:
7991 case MONO_TYPE_U:
7992 case MONO_TYPE_I:
7993 case MONO_TYPE_U1:
7994 case MONO_TYPE_I1:
7995 case MONO_TYPE_U2:
7996 case MONO_TYPE_I2:
7997 case MONO_TYPE_U4:
7998 case MONO_TYPE_I4:
7999 case MONO_TYPE_U8:
8000 case MONO_TYPE_I8:
8001 case MONO_TYPE_R8:
8002 case MONO_TYPE_R4:
8003 case MONO_TYPE_VALUETYPE:
8004 return FALSE;
8005 default:
8006 return TRUE;
8010 static void
8011 free_param_data (MonoMethodSignature *sig, void **params) {
8012 int i;
8013 for (i = 0; i < sig->param_count; ++i) {
8014 if (!type_is_reference (sig->params [i]))
8015 g_free (params [i]);
8020 * Find the field index in the metadata FieldDef table.
8022 static guint32
8023 find_field_index (MonoClass *klass, MonoClassField *field) {
8024 int i;
8026 for (i = 0; i < klass->field.count; ++i) {
8027 if (field == &klass->fields [i])
8028 return klass->field.first + 1 + i;
8030 return 0;
8034 * Find the property index in the metadata Property table.
8036 static guint32
8037 find_property_index (MonoClass *klass, MonoProperty *property) {
8038 int i;
8040 for (i = 0; i < klass->ext->property.count; ++i) {
8041 if (property == &klass->ext->properties [i])
8042 return klass->ext->property.first + 1 + i;
8044 return 0;
8048 * Find the event index in the metadata Event table.
8050 static guint32
8051 find_event_index (MonoClass *klass, MonoEvent *event) {
8052 int i;
8054 for (i = 0; i < klass->ext->event.count; ++i) {
8055 if (event == &klass->ext->events [i])
8056 return klass->ext->event.first + 1 + i;
8058 return 0;
8061 static MonoObject*
8062 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
8064 const char *p = (const char*)data;
8065 const char *named;
8066 guint32 i, j, num_named;
8067 MonoObject *attr;
8068 void *params_buf [32];
8069 void **params;
8070 MonoMethodSignature *sig;
8072 mono_class_init (method->klass);
8074 if (len == 0) {
8075 attr = mono_object_new (mono_domain_get (), method->klass);
8076 mono_runtime_invoke (method, attr, NULL, NULL);
8077 return attr;
8080 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8081 return NULL;
8083 /*g_print ("got attr %s\n", method->klass->name);*/
8085 sig = mono_method_signature (method);
8086 if (sig->param_count < 32)
8087 params = params_buf;
8088 else
8089 /* Allocate using GC so it gets GC tracking */
8090 params = mono_gc_alloc_fixed (sig->param_count * sizeof (void*), NULL);
8092 /* skip prolog */
8093 p += 2;
8094 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8095 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8098 named = p;
8099 attr = mono_object_new (mono_domain_get (), method->klass);
8100 mono_runtime_invoke (method, attr, params, NULL);
8101 free_param_data (method->signature, params);
8102 num_named = read16 (named);
8103 named += 2;
8104 for (j = 0; j < num_named; j++) {
8105 gint name_len;
8106 char *name, named_type, data_type;
8107 named_type = *named++;
8108 data_type = *named++; /* type of data */
8109 if (data_type == MONO_TYPE_SZARRAY)
8110 data_type = *named++;
8111 if (data_type == MONO_TYPE_ENUM) {
8112 gint type_len;
8113 char *type_name;
8114 type_len = mono_metadata_decode_blob_size (named, &named);
8115 type_name = g_malloc (type_len + 1);
8116 memcpy (type_name, named, type_len);
8117 type_name [type_len] = 0;
8118 named += type_len;
8119 /* FIXME: lookup the type and check type consistency */
8120 g_free (type_name);
8122 name_len = mono_metadata_decode_blob_size (named, &named);
8123 name = g_malloc (name_len + 1);
8124 memcpy (name, named, name_len);
8125 name [name_len] = 0;
8126 named += name_len;
8127 if (named_type == 0x53) {
8128 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
8129 void *val = load_cattr_value (image, field->type, named, &named);
8130 mono_field_set_value (attr, field, val);
8131 if (!type_is_reference (field->type))
8132 g_free (val);
8133 } else if (named_type == 0x54) {
8134 MonoProperty *prop;
8135 void *pparams [1];
8136 MonoType *prop_type;
8138 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
8139 /* can we have more that 1 arg in a custom attr named property? */
8140 prop_type = prop->get? mono_method_signature (prop->get)->ret :
8141 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8142 pparams [0] = load_cattr_value (image, prop_type, named, &named);
8143 mono_property_set_value (prop, attr, pparams, NULL);
8144 if (!type_is_reference (prop_type))
8145 g_free (pparams [0]);
8147 g_free (name);
8150 if (params != params_buf)
8151 mono_gc_free_fixed (params);
8153 return attr;
8157 * mono_reflection_create_custom_attr_data_args:
8159 * Create an array of typed and named arguments from the cattr blob given by DATA.
8160 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
8161 * NAMED_ARG_INFO will contain information about the named arguments.
8163 void
8164 mono_reflection_create_custom_attr_data_args (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoArray **typed_args, MonoArray **named_args, CattrNamedArg **named_arg_info)
8166 MonoArray *typedargs, *namedargs;
8167 MonoClass *attrklass;
8168 MonoDomain *domain;
8169 const char *p = (const char*)data;
8170 const char *named;
8171 guint32 i, j, num_named;
8172 CattrNamedArg *arginfo = NULL;
8174 mono_class_init (method->klass);
8176 *typed_args = NULL;
8177 *named_args = NULL;
8178 *named_arg_info = NULL;
8180 domain = mono_domain_get ();
8182 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8183 return;
8185 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
8187 /* skip prolog */
8188 p += 2;
8189 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8190 MonoObject *obj;
8191 void *val;
8193 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8194 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
8195 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
8196 mono_array_setref (typedargs, i, obj);
8198 if (!type_is_reference (mono_method_signature (method)->params [i]))
8199 g_free (val);
8202 named = p;
8203 num_named = read16 (named);
8204 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
8205 named += 2;
8206 attrklass = method->klass;
8208 arginfo = g_new0 (CattrNamedArg, num_named);
8209 *named_arg_info = arginfo;
8211 for (j = 0; j < num_named; j++) {
8212 gint name_len;
8213 char *name, named_type, data_type;
8214 named_type = *named++;
8215 data_type = *named++; /* type of data */
8216 if (data_type == MONO_TYPE_SZARRAY)
8217 data_type = *named++;
8218 if (data_type == MONO_TYPE_ENUM) {
8219 gint type_len;
8220 char *type_name;
8221 type_len = mono_metadata_decode_blob_size (named, &named);
8222 type_name = g_malloc (type_len + 1);
8223 memcpy (type_name, named, type_len);
8224 type_name [type_len] = 0;
8225 named += type_len;
8226 /* FIXME: lookup the type and check type consistency */
8227 g_free (type_name);
8229 name_len = mono_metadata_decode_blob_size (named, &named);
8230 name = g_malloc (name_len + 1);
8231 memcpy (name, named, name_len);
8232 name [name_len] = 0;
8233 named += name_len;
8234 if (named_type == 0x53) {
8235 MonoObject *obj;
8236 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
8237 void *val;
8239 arginfo [j].type = field->type;
8240 arginfo [j].field = field;
8242 val = load_cattr_value (image, field->type, named, &named);
8243 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
8244 mono_array_setref (namedargs, j, obj);
8245 if (!type_is_reference (field->type))
8246 g_free (val);
8247 } else if (named_type == 0x54) {
8248 MonoObject *obj;
8249 MonoType *prop_type;
8250 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
8251 void *val;
8253 prop_type = prop->get? mono_method_signature (prop->get)->ret :
8254 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8256 arginfo [j].type = prop_type;
8257 arginfo [j].prop = prop;
8259 val = load_cattr_value (image, prop_type, named, &named);
8260 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
8261 mono_array_setref (namedargs, j, obj);
8262 if (!type_is_reference (prop_type))
8263 g_free (val);
8265 g_free (name);
8268 *typed_args = typedargs;
8269 *named_args = namedargs;
8272 static MonoObject*
8273 create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
8275 MonoArray *typedargs, *namedargs;
8276 static MonoMethod *ctor;
8277 MonoDomain *domain;
8278 MonoObject *attr;
8279 void *params [3];
8280 CattrNamedArg *arginfo;
8281 int i;
8283 mono_class_init (method->klass);
8285 if (!ctor)
8286 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 3);
8288 domain = mono_domain_get ();
8289 if (len == 0) {
8290 /* This is for Attributes with no parameters */
8291 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8292 params [0] = mono_method_get_object (domain, method, NULL);
8293 params [1] = params [2] = NULL;
8294 mono_runtime_invoke (method, attr, params, NULL);
8295 return attr;
8298 mono_reflection_create_custom_attr_data_args (image, method, data, len, &typedargs, &namedargs, &arginfo);
8299 if (!typedargs || !namedargs)
8300 return NULL;
8302 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8303 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
8304 MonoObject *typedarg;
8306 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
8307 mono_array_setref (typedargs, i, typedarg);
8310 for (i = 0; i < mono_array_length (namedargs); ++i) {
8311 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
8312 MonoObject *typedarg, *namedarg, *minfo;
8314 if (arginfo [i].prop)
8315 minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
8316 else
8317 minfo = (MonoObject*)mono_field_get_object (domain, NULL, arginfo [i].field);
8319 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
8320 namedarg = create_cattr_named_arg (minfo, typedarg);
8322 mono_array_setref (namedargs, i, namedarg);
8325 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8326 params [0] = mono_method_get_object (domain, method, NULL);
8327 params [1] = typedargs;
8328 params [2] = namedargs;
8329 mono_runtime_invoke (ctor, attr, params, NULL);
8330 return attr;
8333 MonoArray*
8334 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
8336 MonoArray *result;
8337 MonoObject *attr;
8338 int i;
8340 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, cinfo->num_attrs);
8341 for (i = 0; i < cinfo->num_attrs; ++i) {
8342 if (!cinfo->attrs [i].ctor)
8343 /* The cattr type is not finished yet */
8344 /* We should include the type name but cinfo doesn't contain it */
8345 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
8346 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
8347 mono_array_setref (result, i, attr);
8349 return result;
8352 static MonoArray*
8353 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass)
8355 MonoArray *result;
8356 MonoObject *attr;
8357 int i, n;
8359 n = 0;
8360 for (i = 0; i < cinfo->num_attrs; ++i) {
8361 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
8362 n ++;
8365 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
8366 n = 0;
8367 for (i = 0; i < cinfo->num_attrs; ++i) {
8368 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
8369 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
8370 mono_array_setref (result, n, attr);
8371 n ++;
8374 return result;
8377 static MonoArray*
8378 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
8380 MonoArray *result;
8381 MonoObject *attr;
8382 int i;
8384 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
8385 for (i = 0; i < cinfo->num_attrs; ++i) {
8386 attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
8387 mono_array_setref (result, i, attr);
8389 return result;
8393 * mono_custom_attrs_from_index:
8395 * Returns: NULL if no attributes are found or if a loading error occurs.
8397 MonoCustomAttrInfo*
8398 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
8400 guint32 mtoken, i, len;
8401 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
8402 MonoTableInfo *ca;
8403 MonoCustomAttrInfo *ainfo;
8404 GList *tmp, *list = NULL;
8405 const char *data;
8407 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
8409 i = mono_metadata_custom_attrs_from_index (image, idx);
8410 if (!i)
8411 return NULL;
8412 i --;
8413 while (i < ca->rows) {
8414 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
8415 break;
8416 list = g_list_prepend (list, GUINT_TO_POINTER (i));
8417 ++i;
8419 len = g_list_length (list);
8420 if (!len)
8421 return NULL;
8422 ainfo = g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
8423 ainfo->num_attrs = len;
8424 ainfo->image = image;
8425 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
8426 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
8427 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
8428 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
8429 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
8430 mtoken |= MONO_TOKEN_METHOD_DEF;
8431 break;
8432 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
8433 mtoken |= MONO_TOKEN_MEMBER_REF;
8434 break;
8435 default:
8436 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
8437 break;
8439 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
8440 if (!ainfo->attrs [i].ctor) {
8441 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
8442 g_list_free (list);
8443 g_free (ainfo);
8444 return NULL;
8446 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
8447 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
8448 ainfo->attrs [i].data = (guchar*)data;
8450 g_list_free (list);
8452 return ainfo;
8455 MonoCustomAttrInfo*
8456 mono_custom_attrs_from_method (MonoMethod *method)
8458 guint32 idx;
8461 * An instantiated method has the same cattrs as the generic method definition.
8463 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8464 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8466 if (method->is_inflated)
8467 method = ((MonoMethodInflated *) method)->declaring;
8469 if (method->dynamic || method->klass->image->dynamic)
8470 return lookup_custom_attr (method->klass->image, method);
8472 if (!method->token)
8473 /* Synthetic methods */
8474 return NULL;
8476 idx = mono_method_get_index (method);
8477 idx <<= MONO_CUSTOM_ATTR_BITS;
8478 idx |= MONO_CUSTOM_ATTR_METHODDEF;
8479 return mono_custom_attrs_from_index (method->klass->image, idx);
8482 MonoCustomAttrInfo*
8483 mono_custom_attrs_from_class (MonoClass *klass)
8485 guint32 idx;
8487 if (klass->generic_class)
8488 klass = klass->generic_class->container_class;
8490 if (klass->image->dynamic)
8491 return lookup_custom_attr (klass->image, klass);
8493 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
8494 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
8495 idx <<= MONO_CUSTOM_ATTR_BITS;
8496 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
8497 } else {
8498 idx = mono_metadata_token_index (klass->type_token);
8499 idx <<= MONO_CUSTOM_ATTR_BITS;
8500 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
8502 return mono_custom_attrs_from_index (klass->image, idx);
8505 MonoCustomAttrInfo*
8506 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
8508 guint32 idx;
8510 if (assembly->image->dynamic)
8511 return lookup_custom_attr (assembly->image, assembly);
8512 idx = 1; /* there is only one assembly */
8513 idx <<= MONO_CUSTOM_ATTR_BITS;
8514 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
8515 return mono_custom_attrs_from_index (assembly->image, idx);
8518 static MonoCustomAttrInfo*
8519 mono_custom_attrs_from_module (MonoImage *image)
8521 guint32 idx;
8523 if (image->dynamic)
8524 return lookup_custom_attr (image, image);
8525 idx = 1; /* there is only one module */
8526 idx <<= MONO_CUSTOM_ATTR_BITS;
8527 idx |= MONO_CUSTOM_ATTR_MODULE;
8528 return mono_custom_attrs_from_index (image, idx);
8531 MonoCustomAttrInfo*
8532 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
8534 guint32 idx;
8536 if (klass->image->dynamic) {
8537 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
8538 return lookup_custom_attr (klass->image, property);
8540 idx = find_property_index (klass, property);
8541 idx <<= MONO_CUSTOM_ATTR_BITS;
8542 idx |= MONO_CUSTOM_ATTR_PROPERTY;
8543 return mono_custom_attrs_from_index (klass->image, idx);
8546 MonoCustomAttrInfo*
8547 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
8549 guint32 idx;
8551 if (klass->image->dynamic) {
8552 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
8553 return lookup_custom_attr (klass->image, event);
8555 idx = find_event_index (klass, event);
8556 idx <<= MONO_CUSTOM_ATTR_BITS;
8557 idx |= MONO_CUSTOM_ATTR_EVENT;
8558 return mono_custom_attrs_from_index (klass->image, idx);
8561 MonoCustomAttrInfo*
8562 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
8564 guint32 idx;
8565 if (klass->image->dynamic) {
8566 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
8567 return lookup_custom_attr (klass->image, field);
8569 idx = find_field_index (klass, field);
8570 idx <<= MONO_CUSTOM_ATTR_BITS;
8571 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
8572 return mono_custom_attrs_from_index (klass->image, idx);
8575 MonoCustomAttrInfo*
8576 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
8578 MonoTableInfo *ca;
8579 guint32 i, idx, method_index;
8580 guint32 param_list, param_last, param_pos, found;
8581 MonoImage *image;
8582 MonoReflectionMethodAux *aux;
8585 * An instantiated method has the same cattrs as the generic method definition.
8587 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8588 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8590 if (method->is_inflated)
8591 method = ((MonoMethodInflated *) method)->declaring;
8593 if (method->klass->image->dynamic) {
8594 MonoCustomAttrInfo *res, *ainfo;
8595 int size;
8597 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8598 if (!aux || !aux->param_cattr)
8599 return NULL;
8601 /* Need to copy since it will be freed later */
8602 ainfo = aux->param_cattr [param];
8603 if (!ainfo)
8604 return NULL;
8605 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
8606 res = g_malloc0 (size);
8607 memcpy (res, ainfo, size);
8608 return res;
8611 image = method->klass->image;
8612 method_index = mono_method_get_index (method);
8613 ca = &image->tables [MONO_TABLE_METHOD];
8615 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
8616 if (method_index == ca->rows) {
8617 ca = &image->tables [MONO_TABLE_PARAM];
8618 param_last = ca->rows + 1;
8619 } else {
8620 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
8621 ca = &image->tables [MONO_TABLE_PARAM];
8623 found = FALSE;
8624 for (i = param_list; i < param_last; ++i) {
8625 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
8626 if (param_pos == param) {
8627 found = TRUE;
8628 break;
8631 if (!found)
8632 return NULL;
8633 idx = i;
8634 idx <<= MONO_CUSTOM_ATTR_BITS;
8635 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
8636 return mono_custom_attrs_from_index (image, idx);
8639 gboolean
8640 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8642 int i;
8643 MonoClass *klass;
8644 for (i = 0; i < ainfo->num_attrs; ++i) {
8645 klass = ainfo->attrs [i].ctor->klass;
8646 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
8647 return TRUE;
8649 return FALSE;
8652 MonoObject*
8653 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8655 int i, attr_index;
8656 MonoClass *klass;
8657 MonoArray *attrs;
8659 attr_index = -1;
8660 for (i = 0; i < ainfo->num_attrs; ++i) {
8661 klass = ainfo->attrs [i].ctor->klass;
8662 if (mono_class_has_parent (klass, attr_klass)) {
8663 attr_index = i;
8664 break;
8667 if (attr_index == -1)
8668 return NULL;
8670 attrs = mono_custom_attrs_construct (ainfo);
8671 if (attrs)
8672 return mono_array_get (attrs, MonoObject*, attr_index);
8673 else
8674 return NULL;
8678 * mono_reflection_get_custom_attrs_info:
8679 * @obj: a reflection object handle
8681 * Return the custom attribute info for attributes defined for the
8682 * reflection handle @obj. The objects.
8684 * FIXME this function leaks like a sieve for SRE objects.
8686 MonoCustomAttrInfo*
8687 mono_reflection_get_custom_attrs_info (MonoObject *obj)
8689 MonoClass *klass;
8690 MonoCustomAttrInfo *cinfo = NULL;
8692 klass = obj->vtable->klass;
8693 if (klass == mono_defaults.monotype_class) {
8694 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
8695 klass = mono_class_from_mono_type (type);
8696 cinfo = mono_custom_attrs_from_class (klass);
8697 } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
8698 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
8699 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
8700 } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
8701 MonoReflectionModule *module = (MonoReflectionModule*)obj;
8702 cinfo = mono_custom_attrs_from_module (module->image);
8703 } else if (strcmp ("MonoProperty", klass->name) == 0) {
8704 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
8705 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
8706 } else if (strcmp ("MonoEvent", klass->name) == 0) {
8707 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
8708 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
8709 } else if (strcmp ("MonoField", klass->name) == 0) {
8710 MonoReflectionField *rfield = (MonoReflectionField*)obj;
8711 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
8712 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
8713 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8714 cinfo = mono_custom_attrs_from_method (rmethod->method);
8715 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
8716 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8717 cinfo = mono_custom_attrs_from_method (rmethod->method);
8718 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
8719 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
8720 MonoClass *member_class = mono_object_class (param->MemberImpl);
8721 if (mono_class_is_reflection_method_or_constructor (member_class)) {
8722 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8723 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
8724 } else if (is_sr_mono_property (member_class)) {
8725 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
8726 MonoMethod *method;
8727 if (!(method = prop->property->get))
8728 method = prop->property->set;
8729 g_assert (method);
8731 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8733 #ifndef DISABLE_REFLECTION_EMIT
8734 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
8735 MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl);
8736 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8737 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
8738 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
8739 MonoMethod *method = NULL;
8740 if (is_sre_ctor_builder (mono_object_class (c->cb)))
8741 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
8742 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
8743 method = ((MonoReflectionMethod *)c->cb)->method;
8744 else
8745 g_error ("mono_reflection_get_custom_attrs_info:: can't handle a CTBI with base_method of type %s", mono_type_get_full_name (member_class));
8747 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8749 #endif
8750 else {
8751 char *type_name = mono_type_get_full_name (member_class);
8752 char *msg = g_strdup_printf ("Custom attributes on a ParamInfo with member %s are not supported", type_name);
8753 MonoException *ex = mono_get_exception_not_supported (msg);
8754 g_free (type_name);
8755 g_free (msg);
8756 mono_raise_exception (ex);
8758 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
8759 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
8760 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
8761 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
8762 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8763 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
8764 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
8765 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
8766 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
8767 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
8768 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8769 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
8770 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
8771 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8772 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
8773 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
8774 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8775 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
8776 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
8777 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
8778 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
8779 } else { /* handle other types here... */
8780 g_error ("get custom attrs not yet supported for %s", klass->name);
8783 return cinfo;
8787 * mono_reflection_get_custom_attrs_by_type:
8788 * @obj: a reflection object handle
8790 * Return an array with all the custom attributes defined of the
8791 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
8792 * of that type are returned. The objects are fully build. Return NULL if a loading error
8793 * occurs.
8795 MonoArray*
8796 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass)
8798 MonoArray *result;
8799 MonoCustomAttrInfo *cinfo;
8801 cinfo = mono_reflection_get_custom_attrs_info (obj);
8802 if (cinfo) {
8803 if (attr_klass)
8804 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass);
8805 else
8806 result = mono_custom_attrs_construct (cinfo);
8807 if (!cinfo->cached)
8808 mono_custom_attrs_free (cinfo);
8809 } else {
8810 if (mono_loader_get_last_error ())
8811 return NULL;
8812 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
8815 return result;
8819 * mono_reflection_get_custom_attrs:
8820 * @obj: a reflection object handle
8822 * Return an array with all the custom attributes defined of the
8823 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
8824 * occurs.
8826 MonoArray*
8827 mono_reflection_get_custom_attrs (MonoObject *obj)
8829 return mono_reflection_get_custom_attrs_by_type (obj, NULL);
8833 * mono_reflection_get_custom_attrs_data:
8834 * @obj: a reflection obj handle
8836 * Returns an array of System.Reflection.CustomAttributeData,
8837 * which include information about attributes reflected on
8838 * types loaded using the Reflection Only methods
8840 MonoArray*
8841 mono_reflection_get_custom_attrs_data (MonoObject *obj)
8843 MonoArray *result;
8844 MonoCustomAttrInfo *cinfo;
8846 cinfo = mono_reflection_get_custom_attrs_info (obj);
8847 if (cinfo) {
8848 result = mono_custom_attrs_data_construct (cinfo);
8849 if (!cinfo->cached)
8850 mono_custom_attrs_free (cinfo);
8851 } else
8852 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
8854 return result;
8857 static MonoReflectionType*
8858 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
8860 static MonoMethod *method_get_underlying_system_type = NULL;
8861 MonoMethod *usertype_method;
8863 if (!method_get_underlying_system_type)
8864 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
8865 usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
8866 return (MonoReflectionType *) mono_runtime_invoke (usertype_method, t, NULL, NULL);
8870 static gboolean
8871 is_corlib_type (MonoClass *class)
8873 return class->image == mono_defaults.corlib;
8876 #define check_corlib_type_cached(_class, _namespace, _name) do { \
8877 static MonoClass *cached_class; \
8878 if (cached_class) \
8879 return cached_class == _class; \
8880 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
8881 cached_class = _class; \
8882 return TRUE; \
8884 return FALSE; \
8885 } while (0) \
8888 #ifndef DISABLE_REFLECTION_EMIT
8889 static gboolean
8890 is_sre_array (MonoClass *class)
8892 check_corlib_type_cached (class, "System.Reflection.Emit", "ArrayType");
8895 static gboolean
8896 is_sre_byref (MonoClass *class)
8898 check_corlib_type_cached (class, "System.Reflection.Emit", "ByRefType");
8901 static gboolean
8902 is_sre_pointer (MonoClass *class)
8904 check_corlib_type_cached (class, "System.Reflection.Emit", "PointerType");
8907 static gboolean
8908 is_sre_generic_instance (MonoClass *class)
8910 check_corlib_type_cached (class, "System.Reflection", "MonoGenericClass");
8913 static gboolean
8914 is_sre_type_builder (MonoClass *class)
8916 check_corlib_type_cached (class, "System.Reflection.Emit", "TypeBuilder");
8919 static gboolean
8920 is_sre_method_builder (MonoClass *class)
8922 check_corlib_type_cached (class, "System.Reflection.Emit", "MethodBuilder");
8925 static gboolean
8926 is_sre_ctor_builder (MonoClass *class)
8928 check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorBuilder");
8931 static gboolean
8932 is_sre_field_builder (MonoClass *class)
8934 check_corlib_type_cached (class, "System.Reflection.Emit", "FieldBuilder");
8937 static gboolean
8938 is_sre_method_on_tb_inst (MonoClass *class)
8940 check_corlib_type_cached (class, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
8943 static gboolean
8944 is_sre_ctor_on_tb_inst (MonoClass *class)
8946 check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
8949 MonoType*
8950 mono_reflection_type_get_handle (MonoReflectionType* ref)
8952 MonoClass *class;
8953 if (!ref)
8954 return NULL;
8955 if (ref->type)
8956 return ref->type;
8958 if (is_usertype (ref)) {
8959 ref = mono_reflection_type_get_underlying_system_type (ref);
8960 if (ref == NULL || is_usertype (ref))
8961 return NULL;
8962 if (ref->type)
8963 return ref->type;
8966 class = mono_object_class (ref);
8968 if (is_sre_array (class)) {
8969 MonoType *res;
8970 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
8971 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
8972 g_assert (base);
8973 if (sre_array->rank == 0) //single dimentional array
8974 res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
8975 else
8976 res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
8977 sre_array->type.type = res;
8978 return res;
8979 } else if (is_sre_byref (class)) {
8980 MonoType *res;
8981 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
8982 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
8983 g_assert (base);
8984 res = &mono_class_from_mono_type (base)->this_arg;
8985 sre_byref->type.type = res;
8986 return res;
8987 } else if (is_sre_pointer (class)) {
8988 MonoType *res;
8989 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
8990 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
8991 g_assert (base);
8992 res = &mono_ptr_class_get (base)->byval_arg;
8993 sre_pointer->type.type = res;
8994 return res;
8995 } else if (is_sre_generic_instance (class)) {
8996 MonoType *res, **types;
8997 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
8998 int i, count;
9000 count = mono_array_length (gclass->type_arguments);
9001 types = g_new0 (MonoType*, count);
9002 for (i = 0; i < count; ++i) {
9003 MonoReflectionType *t = mono_array_get (gclass->type_arguments, gpointer, i);
9004 types [i] = mono_reflection_type_get_handle (t);
9005 if (!types[i]) {
9006 g_free (types);
9007 return NULL;
9011 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
9012 g_free (types);
9013 g_assert (res);
9014 gclass->type.type = res;
9015 return res;
9018 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
9019 return NULL;
9024 void
9025 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
9027 mono_reflection_type_get_handle (type);
9030 void
9031 mono_reflection_register_with_runtime (MonoReflectionType *type)
9033 MonoType *res = mono_reflection_type_get_handle (type);
9034 MonoDomain *domain = mono_object_domain ((MonoObject*)type);
9035 MonoClass *class;
9037 if (!res)
9038 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
9040 class = mono_class_from_mono_type (res);
9042 mono_loader_lock (); /*same locking as mono_type_get_object*/
9043 mono_domain_lock (domain);
9045 if (!class->image->dynamic) {
9046 mono_class_setup_supertypes (class);
9047 } else {
9048 if (!domain->type_hash)
9049 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash,
9050 (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
9051 mono_g_hash_table_insert (domain->type_hash, res, type);
9053 mono_domain_unlock (domain);
9054 mono_loader_unlock ();
9058 * LOCKING: Assumes the loader lock is held.
9060 static MonoMethodSignature*
9061 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
9062 MonoMethodSignature *sig;
9063 int count, i;
9065 count = parameters? mono_array_length (parameters): 0;
9067 sig = image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
9068 sig->param_count = count;
9069 sig->sentinelpos = -1; /* FIXME */
9070 for (i = 0; i < count; ++i)
9071 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
9072 return sig;
9076 * LOCKING: Assumes the loader lock is held.
9078 static MonoMethodSignature*
9079 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
9080 MonoMethodSignature *sig;
9082 sig = parameters_to_signature (image, ctor->parameters);
9083 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9084 sig->ret = &mono_defaults.void_class->byval_arg;
9085 return sig;
9089 * LOCKING: Assumes the loader lock is held.
9091 static MonoMethodSignature*
9092 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
9093 MonoMethodSignature *sig;
9095 sig = parameters_to_signature (image, method->parameters);
9096 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9097 sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
9098 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
9099 return sig;
9102 static MonoMethodSignature*
9103 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
9104 MonoMethodSignature *sig;
9106 sig = parameters_to_signature (NULL, method->parameters);
9107 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9108 sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
9109 sig->generic_param_count = 0;
9110 return sig;
9113 static void
9114 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
9116 MonoClass *klass = mono_object_class (prop);
9117 if (strcmp (klass->name, "PropertyBuilder") == 0) {
9118 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
9119 *name = mono_string_to_utf8 (pb->name);
9120 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
9121 } else {
9122 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
9123 *name = g_strdup (p->property->name);
9124 if (p->property->get)
9125 *type = mono_method_signature (p->property->get)->ret;
9126 else
9127 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
9131 static void
9132 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
9134 MonoClass *klass = mono_object_class (field);
9135 if (strcmp (klass->name, "FieldBuilder") == 0) {
9136 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
9137 *name = mono_string_to_utf8 (fb->name);
9138 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9139 } else {
9140 MonoReflectionField *f = (MonoReflectionField *)field;
9141 *name = g_strdup (mono_field_get_name (f->field));
9142 *type = f->field->type;
9146 #else /* DISABLE_REFLECTION_EMIT */
9148 void
9149 mono_reflection_register_with_runtime (MonoReflectionType *type)
9151 /* This is empty */
9154 static gboolean
9155 is_sre_type_builder (MonoClass *class)
9157 return FALSE;
9160 static gboolean
9161 is_sre_generic_instance (MonoClass *class)
9163 return FALSE;
9166 #endif /* !DISABLE_REFLECTION_EMIT */
9169 static gboolean
9170 is_sr_mono_field (MonoClass *class)
9172 check_corlib_type_cached (class, "System.Reflection", "MonoField");
9175 static gboolean
9176 is_sr_mono_property (MonoClass *class)
9178 check_corlib_type_cached (class, "System.Reflection", "MonoProperty");
9181 static gboolean
9182 is_sr_mono_method (MonoClass *class)
9184 check_corlib_type_cached (class, "System.Reflection", "MonoMethod");
9187 static gboolean
9188 is_sr_mono_cmethod (MonoClass *class)
9190 check_corlib_type_cached (class, "System.Reflection", "MonoCMethod");
9193 static gboolean
9194 is_sr_mono_generic_method (MonoClass *class)
9196 check_corlib_type_cached (class, "System.Reflection", "MonoGenericMethod");
9199 static gboolean
9200 is_sr_mono_generic_cmethod (MonoClass *class)
9202 check_corlib_type_cached (class, "System.Reflection", "MonoGenericCMethod");
9205 gboolean
9206 mono_class_is_reflection_method_or_constructor (MonoClass *class)
9208 return is_sr_mono_method (class) || is_sr_mono_cmethod (class) || is_sr_mono_generic_method (class) || is_sr_mono_generic_cmethod (class);
9211 static gboolean
9212 is_usertype (MonoReflectionType *ref)
9214 MonoClass *class = mono_object_class (ref);
9215 return class->image != mono_defaults.corlib || strcmp ("TypeDelegator", class->name) == 0;
9218 static MonoReflectionType*
9219 mono_reflection_type_resolve_user_types (MonoReflectionType *type)
9221 if (!type || type->type)
9222 return type;
9224 if (is_usertype (type)) {
9225 type = mono_reflection_type_get_underlying_system_type (type);
9226 if (is_usertype (type))
9227 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported22"));
9230 return type;
9233 * Encode a value in a custom attribute stream of bytes.
9234 * The value to encode is either supplied as an object in argument val
9235 * (valuetypes are boxed), or as a pointer to the data in the
9236 * argument argval.
9237 * @type represents the type of the value
9238 * @buffer is the start of the buffer
9239 * @p the current position in the buffer
9240 * @buflen contains the size of the buffer and is used to return the new buffer size
9241 * if this needs to be realloced.
9242 * @retbuffer and @retp return the start and the position of the buffer
9244 static void
9245 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
9247 MonoTypeEnum simple_type;
9249 if ((p-buffer) + 10 >= *buflen) {
9250 char *newbuf;
9251 *buflen *= 2;
9252 newbuf = g_realloc (buffer, *buflen);
9253 p = newbuf + (p-buffer);
9254 buffer = newbuf;
9256 if (!argval)
9257 argval = ((char*)arg + sizeof (MonoObject));
9258 simple_type = type->type;
9259 handle_enum:
9260 switch (simple_type) {
9261 case MONO_TYPE_BOOLEAN:
9262 case MONO_TYPE_U1:
9263 case MONO_TYPE_I1:
9264 *p++ = *argval;
9265 break;
9266 case MONO_TYPE_CHAR:
9267 case MONO_TYPE_U2:
9268 case MONO_TYPE_I2:
9269 swap_with_size (p, argval, 2, 1);
9270 p += 2;
9271 break;
9272 case MONO_TYPE_U4:
9273 case MONO_TYPE_I4:
9274 case MONO_TYPE_R4:
9275 swap_with_size (p, argval, 4, 1);
9276 p += 4;
9277 break;
9278 case MONO_TYPE_R8:
9279 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
9280 p [0] = argval [4];
9281 p [1] = argval [5];
9282 p [2] = argval [6];
9283 p [3] = argval [7];
9284 p [4] = argval [0];
9285 p [5] = argval [1];
9286 p [6] = argval [2];
9287 p [7] = argval [3];
9288 #else
9289 swap_with_size (p, argval, 8, 1);
9290 #endif
9291 p += 8;
9292 break;
9293 case MONO_TYPE_U8:
9294 case MONO_TYPE_I8:
9295 swap_with_size (p, argval, 8, 1);
9296 p += 8;
9297 break;
9298 case MONO_TYPE_VALUETYPE:
9299 if (type->data.klass->enumtype) {
9300 simple_type = mono_class_enum_basetype (type->data.klass)->type;
9301 goto handle_enum;
9302 } else {
9303 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
9305 break;
9306 case MONO_TYPE_STRING: {
9307 char *str;
9308 guint32 slen;
9309 if (!arg) {
9310 *p++ = 0xFF;
9311 break;
9313 str = mono_string_to_utf8 ((MonoString*)arg);
9314 slen = strlen (str);
9315 if ((p-buffer) + 10 + slen >= *buflen) {
9316 char *newbuf;
9317 *buflen *= 2;
9318 *buflen += slen;
9319 newbuf = g_realloc (buffer, *buflen);
9320 p = newbuf + (p-buffer);
9321 buffer = newbuf;
9323 mono_metadata_encode_value (slen, p, &p);
9324 memcpy (p, str, slen);
9325 p += slen;
9326 g_free (str);
9327 break;
9329 case MONO_TYPE_CLASS: {
9330 char *str;
9331 guint32 slen;
9332 if (!arg) {
9333 *p++ = 0xFF;
9334 break;
9336 handle_type:
9337 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
9338 slen = strlen (str);
9339 if ((p-buffer) + 10 + slen >= *buflen) {
9340 char *newbuf;
9341 *buflen *= 2;
9342 *buflen += slen;
9343 newbuf = g_realloc (buffer, *buflen);
9344 p = newbuf + (p-buffer);
9345 buffer = newbuf;
9347 mono_metadata_encode_value (slen, p, &p);
9348 memcpy (p, str, slen);
9349 p += slen;
9350 g_free (str);
9351 break;
9353 case MONO_TYPE_SZARRAY: {
9354 int len, i;
9355 MonoClass *eclass, *arg_eclass;
9357 if (!arg) {
9358 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
9359 break;
9361 len = mono_array_length ((MonoArray*)arg);
9362 *p++ = len & 0xff;
9363 *p++ = (len >> 8) & 0xff;
9364 *p++ = (len >> 16) & 0xff;
9365 *p++ = (len >> 24) & 0xff;
9366 *retp = p;
9367 *retbuffer = buffer;
9368 eclass = type->data.klass;
9369 arg_eclass = mono_object_class (arg)->element_class;
9371 if (!eclass) {
9372 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
9373 eclass = mono_defaults.object_class;
9375 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
9376 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9377 int elsize = mono_class_array_element_size (arg_eclass);
9378 for (i = 0; i < len; ++i) {
9379 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
9380 elptr += elsize;
9382 } else if (eclass->valuetype && arg_eclass->valuetype) {
9383 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9384 int elsize = mono_class_array_element_size (eclass);
9385 for (i = 0; i < len; ++i) {
9386 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
9387 elptr += elsize;
9389 } else {
9390 for (i = 0; i < len; ++i) {
9391 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
9394 break;
9396 case MONO_TYPE_OBJECT: {
9397 MonoClass *klass;
9398 char *str;
9399 guint32 slen;
9402 * The parameter type is 'object' but the type of the actual
9403 * argument is not. So we have to add type information to the blob
9404 * too. This is completely undocumented in the spec.
9407 if (arg == NULL) {
9408 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
9409 *p++ = 0xFF;
9410 break;
9413 klass = mono_object_class (arg);
9415 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
9416 *p++ = 0x50;
9417 goto handle_type;
9418 } else if (klass->enumtype) {
9419 *p++ = 0x55;
9420 } else if (klass == mono_defaults.string_class) {
9421 simple_type = MONO_TYPE_STRING;
9422 *p++ = 0x0E;
9423 goto handle_enum;
9424 } else if (klass->rank == 1) {
9425 *p++ = 0x1D;
9426 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
9427 /* See Partition II, Appendix B3 */
9428 *p++ = 0x51;
9429 else
9430 *p++ = klass->element_class->byval_arg.type;
9431 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
9432 break;
9433 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
9434 *p++ = simple_type = klass->byval_arg.type;
9435 goto handle_enum;
9436 } else {
9437 g_error ("unhandled type in custom attr");
9439 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
9440 slen = strlen (str);
9441 if ((p-buffer) + 10 + slen >= *buflen) {
9442 char *newbuf;
9443 *buflen *= 2;
9444 *buflen += slen;
9445 newbuf = g_realloc (buffer, *buflen);
9446 p = newbuf + (p-buffer);
9447 buffer = newbuf;
9449 mono_metadata_encode_value (slen, p, &p);
9450 memcpy (p, str, slen);
9451 p += slen;
9452 g_free (str);
9453 simple_type = mono_class_enum_basetype (klass)->type;
9454 goto handle_enum;
9456 default:
9457 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
9459 *retp = p;
9460 *retbuffer = buffer;
9463 static void
9464 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
9466 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9467 char *str = type_get_qualified_name (type, NULL);
9468 int slen = strlen (str);
9470 *p++ = 0x55;
9472 * This seems to be optional...
9473 * *p++ = 0x80;
9475 mono_metadata_encode_value (slen, p, &p);
9476 memcpy (p, str, slen);
9477 p += slen;
9478 g_free (str);
9479 } else if (type->type == MONO_TYPE_OBJECT) {
9480 *p++ = 0x51;
9481 } else if (type->type == MONO_TYPE_CLASS) {
9482 /* it should be a type: encode_cattr_value () has the check */
9483 *p++ = 0x50;
9484 } else {
9485 mono_metadata_encode_value (type->type, p, &p);
9486 if (type->type == MONO_TYPE_SZARRAY)
9487 /* See the examples in Partition VI, Annex B */
9488 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
9491 *retp = p;
9494 #ifndef DISABLE_REFLECTION_EMIT
9495 static void
9496 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
9498 int len;
9499 /* Preallocate a large enough buffer */
9500 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9501 char *str = type_get_qualified_name (type, NULL);
9502 len = strlen (str);
9503 g_free (str);
9504 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
9505 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
9506 len = strlen (str);
9507 g_free (str);
9508 } else {
9509 len = 0;
9511 len += strlen (name);
9513 if ((p-buffer) + 20 + len >= *buflen) {
9514 char *newbuf;
9515 *buflen *= 2;
9516 *buflen += len;
9517 newbuf = g_realloc (buffer, *buflen);
9518 p = newbuf + (p-buffer);
9519 buffer = newbuf;
9522 encode_field_or_prop_type (type, p, &p);
9524 len = strlen (name);
9525 mono_metadata_encode_value (len, p, &p);
9526 memcpy (p, name, len);
9527 p += len;
9528 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
9529 *retp = p;
9530 *retbuffer = buffer;
9534 * mono_reflection_get_custom_attrs_blob:
9535 * @ctor: custom attribute constructor
9536 * @ctorArgs: arguments o the constructor
9537 * @properties:
9538 * @propValues:
9539 * @fields:
9540 * @fieldValues:
9542 * Creates the blob of data that needs to be saved in the metadata and that represents
9543 * the custom attributed described by @ctor, @ctorArgs etc.
9544 * Returns: a Byte array representing the blob of data.
9546 MonoArray*
9547 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
9549 MonoArray *result;
9550 MonoMethodSignature *sig;
9551 MonoObject *arg;
9552 char *buffer, *p;
9553 guint32 buflen, i;
9555 MONO_ARCH_SAVE_REGS;
9557 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
9558 /* sig is freed later so allocate it in the heap */
9559 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
9560 } else {
9561 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
9564 g_assert (mono_array_length (ctorArgs) == sig->param_count);
9565 buflen = 256;
9566 p = buffer = g_malloc (buflen);
9567 /* write the prolog */
9568 *p++ = 1;
9569 *p++ = 0;
9570 for (i = 0; i < sig->param_count; ++i) {
9571 arg = mono_array_get (ctorArgs, MonoObject*, i);
9572 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
9574 i = 0;
9575 if (properties)
9576 i += mono_array_length (properties);
9577 if (fields)
9578 i += mono_array_length (fields);
9579 *p++ = i & 0xff;
9580 *p++ = (i >> 8) & 0xff;
9581 if (properties) {
9582 MonoObject *prop;
9583 for (i = 0; i < mono_array_length (properties); ++i) {
9584 MonoType *ptype;
9585 char *pname;
9587 prop = mono_array_get (properties, gpointer, i);
9588 get_prop_name_and_type (prop, &pname, &ptype);
9589 *p++ = 0x54; /* PROPERTY signature */
9590 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
9591 g_free (pname);
9595 if (fields) {
9596 MonoObject *field;
9597 for (i = 0; i < mono_array_length (fields); ++i) {
9598 MonoType *ftype;
9599 char *fname;
9601 field = mono_array_get (fields, gpointer, i);
9602 get_field_name_and_type (field, &fname, &ftype);
9603 *p++ = 0x53; /* FIELD signature */
9604 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
9605 g_free (fname);
9609 g_assert (p - buffer <= buflen);
9610 buflen = p - buffer;
9611 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9612 p = mono_array_addr (result, char, 0);
9613 memcpy (p, buffer, buflen);
9614 g_free (buffer);
9615 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
9616 g_free (sig);
9617 return result;
9621 * mono_reflection_setup_internal_class:
9622 * @tb: a TypeBuilder object
9624 * Creates a MonoClass that represents the TypeBuilder.
9625 * This is a trick that lets us simplify a lot of reflection code
9626 * (and will allow us to support Build and Run assemblies easier).
9628 void
9629 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
9631 MonoError error;
9632 MonoClass *klass, *parent;
9634 MONO_ARCH_SAVE_REGS;
9636 RESOLVE_TYPE (tb->parent);
9638 mono_loader_lock ();
9640 if (tb->parent) {
9641 /* check so we can compile corlib correctly */
9642 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
9643 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
9644 parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
9645 } else {
9646 parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
9648 } else {
9649 parent = NULL;
9652 /* the type has already being created: it means we just have to change the parent */
9653 if (tb->type.type) {
9654 klass = mono_class_from_mono_type (tb->type.type);
9655 klass->parent = NULL;
9656 /* fool mono_class_setup_parent */
9657 klass->supertypes = NULL;
9658 mono_class_setup_parent (klass, parent);
9659 mono_class_setup_mono_type (klass);
9660 mono_loader_unlock ();
9661 return;
9664 klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
9666 klass->image = &tb->module->dynamic_image->image;
9668 klass->inited = 1; /* we lie to the runtime */
9669 klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
9670 if (!mono_error_ok (&error))
9671 goto failure;
9672 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
9673 if (!mono_error_ok (&error))
9674 goto failure;
9675 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
9676 klass->flags = tb->attrs;
9678 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
9680 klass->element_class = klass;
9682 if (mono_class_get_ref_info (klass) == NULL) {
9684 mono_class_set_ref_info (klass, tb);
9686 /* Put into cache so mono_class_get () will find it.
9687 Skip nested types as those should not be available on the global scope. */
9688 if (!tb->nesting_type) {
9689 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
9690 } else {
9691 klass->image->reflection_info_unregister_classes =
9692 g_slist_prepend (klass->image->reflection_info_unregister_classes, klass);
9694 } else {
9695 g_assert (mono_class_get_ref_info (klass) == tb);
9698 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
9699 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
9701 if (parent != NULL) {
9702 mono_class_setup_parent (klass, parent);
9703 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
9704 const char *old_n = klass->name;
9705 /* trick to get relative numbering right when compiling corlib */
9706 klass->name = "BuildingObject";
9707 mono_class_setup_parent (klass, mono_defaults.object_class);
9708 klass->name = old_n;
9711 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
9712 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
9713 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
9714 klass->instance_size = sizeof (MonoObject);
9715 klass->size_inited = 1;
9716 mono_class_setup_vtable_general (klass, NULL, 0);
9719 mono_class_setup_mono_type (klass);
9721 mono_class_setup_supertypes (klass);
9724 * FIXME: handle interfaces.
9727 tb->type.type = &klass->byval_arg;
9729 if (tb->nesting_type) {
9730 g_assert (tb->nesting_type->type);
9731 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
9734 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
9736 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
9738 mono_loader_unlock ();
9739 return;
9741 failure:
9742 mono_loader_unlock ();
9743 mono_error_raise_exception (&error);
9747 * mono_reflection_setup_generic_class:
9748 * @tb: a TypeBuilder object
9750 * Setup the generic class before adding the first generic parameter.
9752 void
9753 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
9758 * mono_reflection_create_generic_class:
9759 * @tb: a TypeBuilder object
9761 * Creates the generic class after all generic parameters have been added.
9763 void
9764 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
9766 MonoClass *klass;
9767 int count, i;
9769 MONO_ARCH_SAVE_REGS;
9771 klass = mono_class_from_mono_type (tb->type.type);
9773 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
9775 if (klass->generic_container || (count == 0))
9776 return;
9778 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
9780 klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
9782 klass->generic_container->owner.klass = klass;
9783 klass->generic_container->type_argc = count;
9784 klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
9786 klass->is_generic = 1;
9788 for (i = 0; i < count; i++) {
9789 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
9790 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
9791 klass->generic_container->type_params [i] = *param;
9792 /*Make sure we are a diferent type instance */
9793 klass->generic_container->type_params [i].param.owner = klass->generic_container;
9794 klass->generic_container->type_params [i].info.pklass = NULL;
9795 klass->generic_container->type_params [i].info.flags = gparam->attrs;
9797 g_assert (klass->generic_container->type_params [i].param.owner);
9800 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
9804 * mono_reflection_create_internal_class:
9805 * @tb: a TypeBuilder object
9807 * Actually create the MonoClass that is associated with the TypeBuilder.
9809 void
9810 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
9812 MonoClass *klass;
9814 MONO_ARCH_SAVE_REGS;
9816 klass = mono_class_from_mono_type (tb->type.type);
9818 mono_loader_lock ();
9819 if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
9820 MonoReflectionFieldBuilder *fb;
9821 MonoClass *ec;
9822 MonoType *enum_basetype;
9824 g_assert (tb->fields != NULL);
9825 g_assert (mono_array_length (tb->fields) >= 1);
9827 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
9829 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
9830 mono_loader_unlock ();
9831 return;
9834 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9835 klass->element_class = mono_class_from_mono_type (enum_basetype);
9836 if (!klass->element_class)
9837 klass->element_class = mono_class_from_mono_type (enum_basetype);
9840 * get the element_class from the current corlib.
9842 ec = default_class_from_mono_type (enum_basetype);
9843 klass->instance_size = ec->instance_size;
9844 klass->size_inited = 1;
9846 * this is almost safe to do with enums and it's needed to be able
9847 * to create objects of the enum type (for use in SetConstant).
9849 /* FIXME: Does this mean enums can't have method overrides ? */
9850 mono_class_setup_vtable_general (klass, NULL, 0);
9852 mono_loader_unlock ();
9855 static MonoMarshalSpec*
9856 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
9857 MonoReflectionMarshal *minfo)
9859 MonoMarshalSpec *res;
9861 res = image_g_new0 (image, MonoMarshalSpec, 1);
9862 res->native = minfo->type;
9864 switch (minfo->type) {
9865 case MONO_NATIVE_LPARRAY:
9866 res->data.array_data.elem_type = minfo->eltype;
9867 if (minfo->has_size) {
9868 res->data.array_data.param_num = minfo->param_num;
9869 res->data.array_data.num_elem = minfo->count;
9870 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
9872 else {
9873 res->data.array_data.param_num = -1;
9874 res->data.array_data.num_elem = -1;
9875 res->data.array_data.elem_mult = -1;
9877 break;
9879 case MONO_NATIVE_BYVALTSTR:
9880 case MONO_NATIVE_BYVALARRAY:
9881 res->data.array_data.num_elem = minfo->count;
9882 break;
9884 case MONO_NATIVE_CUSTOM:
9885 if (minfo->marshaltyperef)
9886 res->data.custom_data.custom_name =
9887 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
9888 if (minfo->mcookie)
9889 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
9890 break;
9892 default:
9893 break;
9896 return res;
9898 #endif /* !DISABLE_REFLECTION_EMIT */
9900 MonoReflectionMarshal*
9901 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
9902 MonoMarshalSpec *spec)
9904 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
9905 MonoReflectionMarshal *minfo;
9906 MonoType *mtype;
9908 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
9909 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
9910 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
9911 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
9914 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
9915 minfo->type = spec->native;
9917 switch (minfo->type) {
9918 case MONO_NATIVE_LPARRAY:
9919 minfo->eltype = spec->data.array_data.elem_type;
9920 minfo->count = spec->data.array_data.num_elem;
9921 minfo->param_num = spec->data.array_data.param_num;
9922 break;
9924 case MONO_NATIVE_BYVALTSTR:
9925 case MONO_NATIVE_BYVALARRAY:
9926 minfo->count = spec->data.array_data.num_elem;
9927 break;
9929 case MONO_NATIVE_CUSTOM:
9930 if (spec->data.custom_data.custom_name) {
9931 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
9932 if (mtype)
9933 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
9935 MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
9937 if (spec->data.custom_data.cookie)
9938 MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
9939 break;
9941 default:
9942 break;
9945 return minfo;
9948 #ifndef DISABLE_REFLECTION_EMIT
9949 static MonoMethod*
9950 reflection_methodbuilder_to_mono_method (MonoClass *klass,
9951 ReflectionMethodBuilder *rmb,
9952 MonoMethodSignature *sig)
9954 MonoError error;
9955 MonoMethod *m;
9956 MonoMethodWrapper *wrapperm;
9957 MonoMarshalSpec **specs;
9958 MonoReflectionMethodAux *method_aux;
9959 MonoImage *image;
9960 gboolean dynamic;
9961 int i;
9963 mono_error_init (&error);
9965 * Methods created using a MethodBuilder should have their memory allocated
9966 * inside the image mempool, while dynamic methods should have their memory
9967 * malloc'd.
9969 dynamic = rmb->refs != NULL;
9970 image = dynamic ? NULL : klass->image;
9972 if (!dynamic)
9973 g_assert (!klass->generic_class);
9975 mono_loader_lock ();
9977 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
9978 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
9979 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
9980 else
9981 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
9983 wrapperm = (MonoMethodWrapper*)m;
9985 m->dynamic = dynamic;
9986 m->slot = -1;
9987 m->flags = rmb->attrs;
9988 m->iflags = rmb->iattrs;
9989 m->name = mono_string_to_utf8_image (image, rmb->name, &error);
9990 g_assert (mono_error_ok (&error));
9991 m->klass = klass;
9992 m->signature = sig;
9993 m->sre_method = TRUE;
9994 m->skip_visibility = rmb->skip_visibility;
9995 if (rmb->table_idx)
9996 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
9998 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
9999 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
10000 m->string_ctor = 1;
10002 m->signature->pinvoke = 1;
10003 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
10004 m->signature->pinvoke = 1;
10006 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10008 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
10009 g_assert (mono_error_ok (&error));
10010 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
10011 g_assert (mono_error_ok (&error));
10013 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
10015 if (klass->image->dynamic)
10016 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10018 mono_loader_unlock ();
10020 return m;
10021 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
10022 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
10023 MonoMethodHeader *header;
10024 guint32 code_size;
10025 gint32 max_stack, i;
10026 gint32 num_locals = 0;
10027 gint32 num_clauses = 0;
10028 guint8 *code;
10030 if (rmb->ilgen) {
10031 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
10032 code_size = rmb->ilgen->code_len;
10033 max_stack = rmb->ilgen->max_stack;
10034 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
10035 if (rmb->ilgen->ex_handlers)
10036 num_clauses = method_count_clauses (rmb->ilgen);
10037 } else {
10038 if (rmb->code) {
10039 code = mono_array_addr (rmb->code, guint8, 0);
10040 code_size = mono_array_length (rmb->code);
10041 /* we probably need to run a verifier on the code... */
10042 max_stack = 8;
10044 else {
10045 code = NULL;
10046 code_size = 0;
10047 max_stack = 8;
10051 header = image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
10052 header->code_size = code_size;
10053 header->code = image_g_malloc (image, code_size);
10054 memcpy ((char*)header->code, code, code_size);
10055 header->max_stack = max_stack;
10056 header->init_locals = rmb->init_locals;
10057 header->num_locals = num_locals;
10059 for (i = 0; i < num_locals; ++i) {
10060 MonoReflectionLocalBuilder *lb =
10061 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
10063 header->locals [i] = image_g_new0 (image, MonoType, 1);
10064 memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
10067 header->num_clauses = num_clauses;
10068 if (num_clauses) {
10069 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
10070 rmb->ilgen, num_clauses);
10073 wrapperm->header = header;
10076 if (rmb->generic_params) {
10077 int count = mono_array_length (rmb->generic_params);
10078 MonoGenericContainer *container = rmb->generic_container;
10080 g_assert (container);
10082 container->type_argc = count;
10083 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
10084 container->owner.method = m;
10086 m->is_generic = TRUE;
10087 mono_method_set_generic_container (m, container);
10089 for (i = 0; i < count; i++) {
10090 MonoReflectionGenericParam *gp =
10091 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
10092 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
10093 container->type_params [i] = *param;
10096 if (klass->generic_container) {
10097 container->parent = klass->generic_container;
10098 container->context.class_inst = klass->generic_container->context.class_inst;
10100 container->context.method_inst = mono_get_shared_generic_inst (container);
10103 if (rmb->refs) {
10104 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
10105 int i;
10106 void **data;
10108 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
10110 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
10111 data [0] = GUINT_TO_POINTER (rmb->nrefs);
10112 for (i = 0; i < rmb->nrefs; ++i)
10113 data [i + 1] = rmb->refs [i];
10116 method_aux = NULL;
10118 /* Parameter info */
10119 if (rmb->pinfo) {
10120 if (!method_aux)
10121 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10122 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
10123 for (i = 0; i <= m->signature->param_count; ++i) {
10124 MonoReflectionParamBuilder *pb;
10125 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10126 if ((i > 0) && (pb->attrs)) {
10127 /* Make a copy since it might point to a shared type structure */
10128 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
10129 m->signature->params [i - 1]->attrs = pb->attrs;
10132 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
10133 MonoDynamicImage *assembly;
10134 guint32 idx, def_type, len;
10135 char *p;
10136 const char *p2;
10138 if (!method_aux->param_defaults) {
10139 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
10140 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
10142 assembly = (MonoDynamicImage*)klass->image;
10143 idx = encode_constant (assembly, pb->def_value, &def_type);
10144 /* Copy the data from the blob since it might get realloc-ed */
10145 p = assembly->blob.data + idx;
10146 len = mono_metadata_decode_blob_size (p, &p2);
10147 len += p2 - p;
10148 method_aux->param_defaults [i] = image_g_malloc (image, len);
10149 method_aux->param_default_types [i] = def_type;
10150 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
10153 if (pb->name) {
10154 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
10155 g_assert (mono_error_ok (&error));
10157 if (pb->cattrs) {
10158 if (!method_aux->param_cattr)
10159 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
10160 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
10166 /* Parameter marshalling */
10167 specs = NULL;
10168 if (rmb->pinfo)
10169 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
10170 MonoReflectionParamBuilder *pb;
10171 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10172 if (pb->marshal_info) {
10173 if (specs == NULL)
10174 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
10175 specs [pb->position] =
10176 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
10180 if (specs != NULL) {
10181 if (!method_aux)
10182 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10183 method_aux->param_marshall = specs;
10186 if (klass->image->dynamic && method_aux)
10187 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10189 mono_loader_unlock ();
10191 return m;
10194 static MonoMethod*
10195 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
10197 ReflectionMethodBuilder rmb;
10198 MonoMethodSignature *sig;
10200 mono_loader_lock ();
10201 sig = ctor_builder_to_signature (klass->image, mb);
10202 mono_loader_unlock ();
10204 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
10206 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10207 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10209 /* If we are in a generic class, we might be called multiple times from inflate_method */
10210 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10211 /* ilgen is no longer needed */
10212 mb->ilgen = NULL;
10215 return mb->mhandle;
10218 static MonoMethod*
10219 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
10221 ReflectionMethodBuilder rmb;
10222 MonoMethodSignature *sig;
10224 mono_loader_lock ();
10225 sig = method_builder_to_signature (klass->image, mb);
10226 mono_loader_unlock ();
10228 reflection_methodbuilder_from_method_builder (&rmb, mb);
10230 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10231 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10233 /* If we are in a generic class, we might be called multiple times from inflate_method */
10234 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10235 /* ilgen is no longer needed */
10236 mb->ilgen = NULL;
10238 return mb->mhandle;
10241 static MonoClassField*
10242 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
10244 MonoClassField *field;
10245 MonoType *custom;
10247 field = g_new0 (MonoClassField, 1);
10249 field->name = mono_string_to_utf8 (fb->name);
10250 if (fb->attrs || fb->modreq || fb->modopt) {
10251 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10252 field->type->attrs = fb->attrs;
10254 g_assert (klass->image->dynamic);
10255 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
10256 g_free (field->type);
10257 field->type = custom;
10258 } else {
10259 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10261 if (fb->offset != -1)
10262 field->offset = fb->offset;
10263 field->parent = klass;
10264 mono_save_custom_attrs (klass->image, field, fb->cattrs);
10266 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
10268 return field;
10270 #endif
10272 MonoType*
10273 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
10275 MonoClass *klass;
10276 MonoReflectionTypeBuilder *tb = NULL;
10277 gboolean is_dynamic = FALSE;
10278 MonoDomain *domain;
10279 MonoClass *geninst;
10281 mono_loader_lock ();
10283 domain = mono_object_domain (type);
10285 if (is_sre_type_builder (mono_object_class (type))) {
10286 tb = (MonoReflectionTypeBuilder *) type;
10288 is_dynamic = TRUE;
10289 } else if (is_sre_generic_instance (mono_object_class (type))) {
10290 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
10291 MonoReflectionType *gtd = rgi->generic_type;
10293 if (is_sre_type_builder (mono_object_class (gtd))) {
10294 tb = (MonoReflectionTypeBuilder *)gtd;
10295 is_dynamic = TRUE;
10299 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
10300 if (tb && tb->generic_container)
10301 mono_reflection_create_generic_class (tb);
10303 klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10304 if (!klass->generic_container) {
10305 mono_loader_unlock ();
10306 return NULL;
10309 if (klass->wastypebuilder) {
10310 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
10312 is_dynamic = TRUE;
10315 mono_loader_unlock ();
10317 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
10319 return &geninst->byval_arg;
10322 MonoClass*
10323 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
10325 MonoGenericClass *gclass;
10326 MonoGenericInst *inst;
10328 g_assert (klass->generic_container);
10330 inst = mono_metadata_get_generic_inst (type_argc, types);
10331 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
10333 return mono_generic_class_get_class (gclass);
10336 MonoReflectionMethod*
10337 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
10339 MonoClass *klass;
10340 MonoMethod *method, *inflated;
10341 MonoMethodInflated *imethod;
10342 MonoGenericContext tmp_context;
10343 MonoGenericInst *ginst;
10344 MonoType **type_argv;
10345 int count, i;
10347 MONO_ARCH_SAVE_REGS;
10349 /*FIXME but this no longer should happen*/
10350 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
10351 #ifndef DISABLE_REFLECTION_EMIT
10352 MonoReflectionMethodBuilder *mb = NULL;
10353 MonoReflectionTypeBuilder *tb;
10354 MonoClass *klass;
10356 mb = (MonoReflectionMethodBuilder *) rmethod;
10357 tb = (MonoReflectionTypeBuilder *) mb->type;
10358 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10360 method = methodbuilder_to_mono_method (klass, mb);
10361 #else
10362 g_assert_not_reached ();
10363 method = NULL;
10364 #endif
10365 } else {
10366 method = rmethod->method;
10369 klass = method->klass;
10371 if (method->is_inflated)
10372 method = ((MonoMethodInflated *) method)->declaring;
10374 count = mono_method_signature (method)->generic_param_count;
10375 if (count != mono_array_length (types))
10376 return NULL;
10378 type_argv = g_new0 (MonoType *, count);
10379 for (i = 0; i < count; i++) {
10380 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
10381 type_argv [i] = mono_reflection_type_get_handle (garg);
10383 ginst = mono_metadata_get_generic_inst (count, type_argv);
10384 g_free (type_argv);
10386 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
10387 tmp_context.method_inst = ginst;
10389 inflated = mono_class_inflate_generic_method (method, &tmp_context);
10390 imethod = (MonoMethodInflated *) inflated;
10392 /*FIXME but I think this is no longer necessary*/
10393 if (method->klass->image->dynamic) {
10394 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10396 * This table maps metadata structures representing inflated methods/fields
10397 * to the reflection objects representing their generic definitions.
10399 mono_loader_lock ();
10400 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
10401 mono_loader_unlock ();
10404 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
10407 #ifndef DISABLE_REFLECTION_EMIT
10409 static MonoMethod *
10410 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
10412 MonoMethodInflated *imethod;
10413 MonoGenericContext *context;
10414 int i;
10417 * With generic code sharing the klass might not be inflated.
10418 * This can happen because classes inflated with their own
10419 * type arguments are "normalized" to the uninflated class.
10421 if (!klass->generic_class)
10422 return method;
10424 context = mono_class_get_context (klass);
10426 if (klass->method.count) {
10427 /* Find the already created inflated method */
10428 for (i = 0; i < klass->method.count; ++i) {
10429 g_assert (klass->methods [i]->is_inflated);
10430 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
10431 break;
10433 g_assert (i < klass->method.count);
10434 imethod = (MonoMethodInflated*)klass->methods [i];
10435 } else {
10436 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
10439 if (method->is_generic && method->klass->image->dynamic) {
10440 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10442 mono_loader_lock ();
10443 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
10444 mono_loader_unlock ();
10446 return (MonoMethod *) imethod;
10449 static MonoMethod *
10450 inflate_method (MonoReflectionType *type, MonoObject *obj)
10452 MonoMethod *method;
10453 MonoClass *gklass;
10455 MonoClass *type_class = mono_object_class (type);
10457 if (is_sre_generic_instance (type_class)) {
10458 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
10459 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
10460 } else if (is_sre_type_builder (type_class)) {
10461 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10462 } else if (type->type) {
10463 gklass = mono_class_from_mono_type (type->type);
10464 gklass = mono_class_get_generic_type_definition (gklass);
10465 } else {
10466 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
10469 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
10470 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
10471 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
10472 else
10473 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
10474 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
10475 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
10476 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
10477 method = ((MonoReflectionMethod *) obj)->method;
10478 else {
10479 method = NULL; /* prevent compiler warning */
10480 g_error ("can't handle type %s", obj->vtable->klass->name);
10483 return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
10486 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
10487 void
10488 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
10489 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
10490 MonoArray *events)
10492 MonoGenericClass *gclass;
10493 MonoDynamicGenericClass *dgclass;
10494 MonoClass *klass, *gklass;
10495 MonoType *gtype;
10496 int i;
10498 MONO_ARCH_SAVE_REGS;
10500 gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
10501 klass = mono_class_from_mono_type (gtype);
10502 g_assert (gtype->type == MONO_TYPE_GENERICINST);
10503 gclass = gtype->data.generic_class;
10505 if (!gclass->is_dynamic)
10506 return;
10508 dgclass = (MonoDynamicGenericClass *) gclass;
10510 if (dgclass->initialized)
10511 return;
10513 gklass = gclass->container_class;
10514 mono_class_init (gklass);
10516 dgclass->count_methods = methods ? mono_array_length (methods) : 0;
10517 dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
10518 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
10520 dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
10521 dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
10522 dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
10523 dgclass->field_objects = g_new0 (MonoObject*, dgclass->count_fields);
10524 dgclass->field_generic_types = g_new0 (MonoType*, dgclass->count_fields);
10526 for (i = 0; i < dgclass->count_methods; i++) {
10527 MonoObject *obj = mono_array_get (methods, gpointer, i);
10529 dgclass->methods [i] = inflate_method ((MonoReflectionType*)type, obj);
10532 for (i = 0; i < dgclass->count_ctors; i++) {
10533 MonoObject *obj = mono_array_get (ctors, gpointer, i);
10535 dgclass->ctors [i] = inflate_method ((MonoReflectionType*)type, obj);
10538 for (i = 0; i < dgclass->count_fields; i++) {
10539 MonoObject *obj = mono_array_get (fields, gpointer, i);
10540 MonoClassField *field, *inflated_field = NULL;
10542 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
10543 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
10544 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
10545 field = ((MonoReflectionField *) obj)->field;
10546 else {
10547 field = NULL; /* prevent compiler warning */
10548 g_assert_not_reached ();
10551 dgclass->fields [i] = *field;
10552 dgclass->fields [i].parent = klass;
10553 dgclass->fields [i].type = mono_class_inflate_generic_type (
10554 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
10555 dgclass->field_generic_types [i] = field->type;
10556 MOVING_GC_REGISTER (&dgclass->field_objects [i]);
10557 dgclass->field_objects [i] = obj;
10559 if (inflated_field) {
10560 g_free (inflated_field);
10561 } else {
10562 dgclass->fields [i].name = g_strdup (dgclass->fields [i].name);
10566 dgclass->initialized = TRUE;
10569 static void
10570 fix_partial_generic_class (MonoClass *klass)
10572 MonoClass *gklass = klass->generic_class->container_class;
10573 MonoDynamicGenericClass *dgclass;
10574 int i;
10576 if (klass->wastypebuilder)
10577 return;
10579 dgclass = (MonoDynamicGenericClass *) klass->generic_class;
10581 if (!dgclass->initialized)
10582 return;
10584 if (klass->method.count != gklass->method.count) {
10585 klass->method.count = gklass->method.count;
10586 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
10588 for (i = 0; i < klass->method.count; i++) {
10589 klass->methods [i] = mono_class_inflate_generic_method_full (
10590 gklass->methods [i], klass, mono_class_get_context (klass));
10594 if (klass->interface_count && klass->interface_count != gklass->interface_count) {
10595 klass->interface_count = gklass->interface_count;
10596 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
10597 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10599 for (i = 0; i < gklass->interface_count; ++i) {
10600 MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
10601 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
10602 mono_metadata_free_type (iface_type);
10604 ensure_runtime_vtable (klass->interfaces [i]);
10606 klass->interfaces_inited = 1;
10609 if (klass->field.count != gklass->field.count) {
10610 klass->field.count = gklass->field.count;
10611 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
10613 for (i = 0; i < klass->field.count; i++) {
10614 klass->fields [i] = gklass->fields [i];
10615 klass->fields [i].parent = klass;
10616 klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
10620 /*We can only finish with this klass once it's parent has as well*/
10621 if (gklass->wastypebuilder)
10622 klass->wastypebuilder = TRUE;
10623 return;
10626 static void
10627 ensure_generic_class_runtime_vtable (MonoClass *klass)
10629 MonoClass *gklass = klass->generic_class->container_class;
10631 ensure_runtime_vtable (gklass);
10633 fix_partial_generic_class (klass);
10636 static void
10637 ensure_runtime_vtable (MonoClass *klass)
10639 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10640 int i, num, j;
10642 if (!klass->image->dynamic || (!tb && !klass->generic_class) || klass->wastypebuilder)
10643 return;
10644 if (klass->parent)
10645 ensure_runtime_vtable (klass->parent);
10647 if (tb) {
10648 num = tb->ctors? mono_array_length (tb->ctors): 0;
10649 num += tb->num_methods;
10650 klass->method.count = num;
10651 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
10652 num = tb->ctors? mono_array_length (tb->ctors): 0;
10653 for (i = 0; i < num; ++i)
10654 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
10655 num = tb->num_methods;
10656 j = i;
10657 for (i = 0; i < num; ++i)
10658 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
10660 if (tb->interfaces) {
10661 klass->interface_count = mono_array_length (tb->interfaces);
10662 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
10663 for (i = 0; i < klass->interface_count; ++i) {
10664 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
10665 klass->interfaces [i] = mono_class_from_mono_type (iface);
10666 ensure_runtime_vtable (klass->interfaces [i]);
10668 klass->interfaces_inited = 1;
10670 } else if (klass->generic_class){
10671 ensure_generic_class_runtime_vtable (klass);
10674 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
10675 for (i = 0; i < klass->method.count; ++i)
10676 klass->methods [i]->slot = i;
10678 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10679 mono_class_setup_interface_offsets (klass);
10680 mono_class_setup_interface_id (klass);
10684 * The generic vtable is needed even if image->run is not set since some
10685 * runtime code like ves_icall_Type_GetMethodsByName depends on
10686 * method->slot being defined.
10690 * tb->methods could not be freed since it is used for determining
10691 * overrides during dynamic vtable construction.
10695 static MonoMethod*
10696 mono_reflection_method_get_handle (MonoObject *method)
10698 MonoClass *class = mono_object_class (method);
10699 if (is_sr_mono_method (class)) {
10700 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
10701 return sr_method->method;
10703 if (is_sre_method_builder (class)) {
10704 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
10705 return mb->mhandle;
10707 if (is_sre_method_on_tb_inst (class)) {
10708 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
10709 MonoMethod *result;
10710 /*FIXME move this to a proper method and unify with resolve_object*/
10711 if (m->method_args) {
10712 result = mono_reflection_method_on_tb_inst_get_handle (m);
10713 } else {
10714 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
10715 MonoClass *inflated_klass = mono_class_from_mono_type (type);
10716 MonoMethod *mono_method;
10718 if (is_sre_method_builder (mono_object_class (m->mb)))
10719 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
10720 else if (is_sr_mono_method (mono_object_class (m->mb)))
10721 mono_method = ((MonoReflectionMethod *)m->mb)->method;
10722 else
10723 g_error ("resolve_object:: can't handle a MTBI with base_method of type %s", mono_type_get_full_name (mono_object_class (m->mb)));
10725 result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
10727 return result;
10730 g_error ("Can't handle methods of type %s:%s", class->name_space, class->name);
10731 return NULL;
10734 void
10735 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
10737 MonoReflectionTypeBuilder *tb;
10738 int i, onum;
10740 *overrides = NULL;
10741 *num_overrides = 0;
10743 g_assert (klass->image->dynamic);
10745 if (!mono_class_get_ref_info (klass))
10746 return;
10748 g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
10750 tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
10752 onum = 0;
10753 if (tb->methods) {
10754 for (i = 0; i < tb->num_methods; ++i) {
10755 MonoReflectionMethodBuilder *mb =
10756 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10757 if (mb->override_method)
10758 onum ++;
10762 if (onum) {
10763 *overrides = g_new0 (MonoMethod*, onum * 2);
10765 onum = 0;
10766 for (i = 0; i < tb->num_methods; ++i) {
10767 MonoReflectionMethodBuilder *mb =
10768 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10769 if (mb->override_method) {
10770 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject *)mb->override_method);
10771 (*overrides) [onum * 2 + 1] = mb->mhandle;
10773 g_assert (mb->mhandle);
10775 onum ++;
10780 *num_overrides = onum;
10783 static void
10784 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
10786 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10787 MonoReflectionFieldBuilder *fb;
10788 MonoClassField *field;
10789 MonoImage *image = klass->image;
10790 const char *p, *p2;
10791 int i;
10792 guint32 len, idx, real_size = 0;
10794 klass->field.count = tb->num_fields;
10795 klass->field.first = 0;
10797 mono_error_init (error);
10799 if (tb->class_size) {
10800 g_assert ((tb->packing_size & 0xfffffff0) == 0);
10801 klass->packing_size = tb->packing_size;
10802 real_size = klass->instance_size + tb->class_size;
10805 if (!klass->field.count) {
10806 klass->instance_size = MAX (klass->instance_size, real_size);
10807 return;
10810 klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
10811 mono_class_alloc_ext (klass);
10812 klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
10814 This is, guess what, a hack.
10815 The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
10816 On the static path no field class is resolved, only types are built. This is the right thing to do
10817 but we suck.
10818 Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
10820 klass->size_inited = 1;
10822 for (i = 0; i < klass->field.count; ++i) {
10823 fb = mono_array_get (tb->fields, gpointer, i);
10824 field = &klass->fields [i];
10825 field->name = mono_string_to_utf8_image (image, fb->name, error);
10826 if (!mono_error_ok (error))
10827 return;
10828 if (fb->attrs) {
10829 field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10830 field->type->attrs = fb->attrs;
10831 } else {
10832 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10834 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
10835 klass->ext->field_def_values [i].data = mono_array_addr (fb->rva_data, char, 0);
10836 if (fb->offset != -1)
10837 field->offset = fb->offset;
10838 field->parent = klass;
10839 fb->handle = field;
10840 mono_save_custom_attrs (klass->image, field, fb->cattrs);
10842 if (fb->def_value) {
10843 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
10844 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
10845 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
10846 /* Copy the data from the blob since it might get realloc-ed */
10847 p = assembly->blob.data + idx;
10848 len = mono_metadata_decode_blob_size (p, &p2);
10849 len += p2 - p;
10850 klass->ext->field_def_values [i].data = mono_image_alloc (image, len);
10851 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
10855 klass->instance_size = MAX (klass->instance_size, real_size);
10856 mono_class_layout_fields (klass);
10859 static void
10860 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
10862 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10863 MonoReflectionPropertyBuilder *pb;
10864 MonoImage *image = klass->image;
10865 MonoProperty *properties;
10866 int i;
10868 mono_error_init (error);
10870 if (!klass->ext)
10871 klass->ext = image_g_new0 (image, MonoClassExt, 1);
10873 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
10874 klass->ext->property.first = 0;
10876 properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
10877 klass->ext->properties = properties;
10878 for (i = 0; i < klass->ext->property.count; ++i) {
10879 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
10880 properties [i].parent = klass;
10881 properties [i].attrs = pb->attrs;
10882 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
10883 if (!mono_error_ok (error))
10884 return;
10885 if (pb->get_method)
10886 properties [i].get = pb->get_method->mhandle;
10887 if (pb->set_method)
10888 properties [i].set = pb->set_method->mhandle;
10890 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
10894 MonoReflectionEvent *
10895 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
10897 MonoEvent *event = g_new0 (MonoEvent, 1);
10898 MonoClass *klass;
10900 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10902 event->parent = klass;
10903 event->attrs = eb->attrs;
10904 event->name = mono_string_to_utf8 (eb->name);
10905 if (eb->add_method)
10906 event->add = eb->add_method->mhandle;
10907 if (eb->remove_method)
10908 event->remove = eb->remove_method->mhandle;
10909 if (eb->raise_method)
10910 event->raise = eb->raise_method->mhandle;
10912 #ifndef MONO_SMALL_CONFIG
10913 if (eb->other_methods) {
10914 int j;
10915 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
10916 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
10917 MonoReflectionMethodBuilder *mb =
10918 mono_array_get (eb->other_methods,
10919 MonoReflectionMethodBuilder*, j);
10920 event->other [j] = mb->mhandle;
10923 #endif
10925 return mono_event_get_object (mono_object_domain (tb), klass, event);
10928 static void
10929 typebuilder_setup_events (MonoClass *klass, MonoError *error)
10931 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10932 MonoReflectionEventBuilder *eb;
10933 MonoImage *image = klass->image;
10934 MonoEvent *events;
10935 int i;
10937 mono_error_init (error);
10939 if (!klass->ext)
10940 klass->ext = image_g_new0 (image, MonoClassExt, 1);
10942 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
10943 klass->ext->event.first = 0;
10945 events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
10946 klass->ext->events = events;
10947 for (i = 0; i < klass->ext->event.count; ++i) {
10948 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
10949 events [i].parent = klass;
10950 events [i].attrs = eb->attrs;
10951 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
10952 if (!mono_error_ok (error))
10953 return;
10954 if (eb->add_method)
10955 events [i].add = eb->add_method->mhandle;
10956 if (eb->remove_method)
10957 events [i].remove = eb->remove_method->mhandle;
10958 if (eb->raise_method)
10959 events [i].raise = eb->raise_method->mhandle;
10961 #ifndef MONO_SMALL_CONFIG
10962 if (eb->other_methods) {
10963 int j;
10964 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
10965 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
10966 MonoReflectionMethodBuilder *mb =
10967 mono_array_get (eb->other_methods,
10968 MonoReflectionMethodBuilder*, j);
10969 events [i].other [j] = mb->mhandle;
10972 #endif
10973 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
10977 static gboolean
10978 remove_instantiations_of_and_ensure_contents (gpointer key,
10979 gpointer value,
10980 gpointer user_data)
10982 MonoType *type = (MonoType*)key;
10983 MonoClass *klass = (MonoClass*)user_data;
10985 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
10986 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
10987 return TRUE;
10988 } else
10989 return FALSE;
10992 static void
10993 check_array_for_usertypes (MonoArray *arr)
10995 int i;
10997 if (!arr)
10998 return;
11000 for (i = 0; i < mono_array_length (arr); ++i)
11001 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i);
11004 MonoReflectionType*
11005 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11007 MonoError error;
11008 MonoClass *klass;
11009 MonoDomain* domain;
11010 MonoReflectionType* res;
11011 int i, j;
11013 MONO_ARCH_SAVE_REGS;
11015 domain = mono_object_domain (tb);
11016 klass = mono_class_from_mono_type (tb->type.type);
11019 * Check for user defined Type subclasses.
11021 RESOLVE_TYPE (tb->parent);
11022 check_array_for_usertypes (tb->interfaces);
11023 if (tb->fields) {
11024 for (i = 0; i < mono_array_length (tb->fields); ++i) {
11025 MonoReflectionFieldBuilder *fb = mono_array_get (tb->fields, gpointer, i);
11026 if (fb) {
11027 RESOLVE_TYPE (fb->type);
11028 check_array_for_usertypes (fb->modreq);
11029 check_array_for_usertypes (fb->modopt);
11030 if (fb->marshal_info && fb->marshal_info->marshaltyperef)
11031 RESOLVE_TYPE (fb->marshal_info->marshaltyperef);
11035 if (tb->methods) {
11036 for (i = 0; i < mono_array_length (tb->methods); ++i) {
11037 MonoReflectionMethodBuilder *mb = mono_array_get (tb->methods, gpointer, i);
11038 if (mb) {
11039 RESOLVE_TYPE (mb->rtype);
11040 check_array_for_usertypes (mb->return_modreq);
11041 check_array_for_usertypes (mb->return_modopt);
11042 check_array_for_usertypes (mb->parameters);
11043 if (mb->param_modreq)
11044 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11045 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11046 if (mb->param_modopt)
11047 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11048 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11052 if (tb->ctors) {
11053 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
11054 MonoReflectionCtorBuilder *mb = mono_array_get (tb->ctors, gpointer, i);
11055 if (mb) {
11056 check_array_for_usertypes (mb->parameters);
11057 if (mb->param_modreq)
11058 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11059 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11060 if (mb->param_modopt)
11061 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11062 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11067 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
11070 * we need to lock the domain because the lock will be taken inside
11071 * So, we need to keep the locking order correct.
11073 mono_loader_lock ();
11074 mono_domain_lock (domain);
11075 if (klass->wastypebuilder) {
11076 mono_domain_unlock (domain);
11077 mono_loader_unlock ();
11078 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11081 * Fields to set in klass:
11082 * the various flags: delegate/unicode/contextbound etc.
11084 klass->flags = tb->attrs;
11085 klass->has_cctor = 1;
11086 klass->has_finalize = 1;
11088 #if 0
11089 if (!((MonoDynamicImage*)klass->image)->run) {
11090 if (klass->generic_container) {
11091 /* FIXME: The code below can't handle generic classes */
11092 klass->wastypebuilder = TRUE;
11093 mono_loader_unlock ();
11094 mono_domain_unlock (domain);
11095 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11098 #endif
11100 /* enums are done right away */
11101 if (!klass->enumtype)
11102 ensure_runtime_vtable (klass);
11104 if (tb->subtypes) {
11105 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
11106 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
11107 mono_class_alloc_ext (klass);
11108 klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)subtb)));
11112 klass->nested_classes_inited = TRUE;
11114 /* fields and object layout */
11115 if (klass->parent) {
11116 if (!klass->parent->size_inited)
11117 mono_class_init (klass->parent);
11118 klass->instance_size = klass->parent->instance_size;
11119 klass->sizes.class_size = 0;
11120 klass->min_align = klass->parent->min_align;
11121 /* if the type has no fields we won't call the field_setup
11122 * routine which sets up klass->has_references.
11124 klass->has_references |= klass->parent->has_references;
11125 } else {
11126 klass->instance_size = sizeof (MonoObject);
11127 klass->min_align = 1;
11130 /* FIXME: handle packing_size and instance_size */
11131 typebuilder_setup_fields (klass, &error);
11132 if (!mono_error_ok (&error))
11133 goto failure;
11134 typebuilder_setup_properties (klass, &error);
11135 if (!mono_error_ok (&error))
11136 goto failure;
11138 typebuilder_setup_events (klass, &error);
11139 if (!mono_error_ok (&error))
11140 goto failure;
11142 klass->wastypebuilder = TRUE;
11145 * If we are a generic TypeBuilder, there might be instantiations in the type cache
11146 * which have type System.Reflection.MonoGenericClass, but after the type is created,
11147 * we want to return normal System.MonoType objects, so clear these out from the cache.
11149 * Together with this we must ensure the contents of all instances to match the created type.
11151 if (domain->type_hash && klass->generic_container)
11152 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
11154 mono_domain_unlock (domain);
11155 mono_loader_unlock ();
11157 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
11158 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11159 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
11162 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11163 g_assert (res != (MonoReflectionType*)tb);
11165 return res;
11167 failure:
11168 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11169 klass->wastypebuilder = TRUE;
11170 mono_domain_unlock (domain);
11171 mono_loader_unlock ();
11172 mono_error_raise_exception (&error);
11173 return NULL;
11176 void
11177 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
11179 MonoGenericParamFull *param;
11180 MonoImage *image;
11181 MonoClass *pklass;
11183 MONO_ARCH_SAVE_REGS;
11185 param = g_new0 (MonoGenericParamFull, 1);
11187 if (gparam->mbuilder) {
11188 if (!gparam->mbuilder->generic_container) {
11189 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
11190 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11191 gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11192 gparam->mbuilder->generic_container->is_method = TRUE;
11194 * Cannot set owner.method, since the MonoMethod is not created yet.
11195 * Set the image field instead, so type_in_image () works.
11197 gparam->mbuilder->generic_container->image = klass->image;
11199 param->param.owner = gparam->mbuilder->generic_container;
11200 } else if (gparam->tbuilder) {
11201 if (!gparam->tbuilder->generic_container) {
11202 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
11203 gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11204 gparam->tbuilder->generic_container->owner.klass = klass;
11206 param->param.owner = gparam->tbuilder->generic_container;
11209 param->info.name = mono_string_to_utf8 (gparam->name);
11210 param->param.num = gparam->index;
11212 image = &gparam->tbuilder->module->dynamic_image->image;
11213 pklass = mono_class_from_generic_parameter ((MonoGenericParam *) param, image, gparam->mbuilder != NULL);
11215 gparam->type.type = &pklass->byval_arg;
11217 mono_class_set_ref_info (pklass, gparam);
11218 mono_image_lock (image);
11219 image->reflection_info_unregister_classes = g_slist_prepend (image->reflection_info_unregister_classes, pklass);
11220 mono_image_unlock (image);
11223 MonoArray *
11224 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
11226 MonoReflectionModuleBuilder *module = sig->module;
11227 MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
11228 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11229 guint32 buflen, i;
11230 MonoArray *result;
11231 SigBuffer buf;
11233 check_array_for_usertypes (sig->arguments);
11235 sigbuffer_init (&buf, 32);
11237 sigbuffer_add_value (&buf, 0x07);
11238 sigbuffer_add_value (&buf, na);
11239 if (assembly != NULL){
11240 for (i = 0; i < na; ++i) {
11241 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11242 encode_reflection_type (assembly, type, &buf);
11246 buflen = buf.p - buf.buf;
11247 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11248 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11249 sigbuffer_free (&buf);
11251 return result;
11254 MonoArray *
11255 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
11257 MonoDynamicImage *assembly = sig->module->dynamic_image;
11258 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11259 guint32 buflen, i;
11260 MonoArray *result;
11261 SigBuffer buf;
11263 check_array_for_usertypes (sig->arguments);
11265 sigbuffer_init (&buf, 32);
11267 sigbuffer_add_value (&buf, 0x06);
11268 for (i = 0; i < na; ++i) {
11269 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11270 encode_reflection_type (assembly, type, &buf);
11273 buflen = buf.p - buf.buf;
11274 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11275 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11276 sigbuffer_free (&buf);
11278 return result;
11281 void
11282 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
11284 ReflectionMethodBuilder rmb;
11285 MonoMethodSignature *sig;
11286 MonoClass *klass;
11287 GSList *l;
11288 int i;
11290 sig = dynamic_method_to_signature (mb);
11292 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
11295 * Resolve references.
11298 * Every second entry in the refs array is reserved for storing handle_class,
11299 * which is needed by the ldtoken implementation in the JIT.
11301 rmb.nrefs = mb->nrefs;
11302 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
11303 for (i = 0; i < mb->nrefs; i += 2) {
11304 MonoClass *handle_class;
11305 gpointer ref;
11306 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
11308 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11309 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11311 * The referenced DynamicMethod should already be created by the managed
11312 * code, except in the case of circular references. In that case, we store
11313 * method in the refs array, and fix it up later when the referenced
11314 * DynamicMethod is created.
11316 if (method->mhandle) {
11317 ref = method->mhandle;
11318 } else {
11319 /* FIXME: GC object stored in unmanaged memory */
11320 ref = method;
11322 /* FIXME: GC object stored in unmanaged memory */
11323 method->referenced_by = g_slist_append (method->referenced_by, mb);
11325 handle_class = mono_defaults.methodhandle_class;
11326 } else {
11327 MonoException *ex = NULL;
11328 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
11329 if (!ref)
11330 ex = mono_get_exception_type_load (NULL, NULL);
11331 else if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
11332 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
11334 if (ex) {
11335 g_free (rmb.refs);
11336 mono_raise_exception (ex);
11337 return;
11341 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
11342 rmb.refs [i + 1] = handle_class;
11345 klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
11347 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11349 /* Fix up refs entries pointing at us */
11350 for (l = mb->referenced_by; l; l = l->next) {
11351 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
11352 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
11353 gpointer *data;
11355 g_assert (method->mhandle);
11357 data = (gpointer*)wrapper->method_data;
11358 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
11359 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
11360 data [i + 1] = mb->mhandle;
11363 g_slist_free (mb->referenced_by);
11365 g_free (rmb.refs);
11367 /* ilgen is no longer needed */
11368 mb->ilgen = NULL;
11371 #endif /* DISABLE_REFLECTION_EMIT */
11373 void
11374 mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod *mb)
11376 g_assert (mb);
11378 if (mb->mhandle)
11379 mono_runtime_free_method (
11380 mono_object_get_domain ((MonoObject*)mb), mb->mhandle);
11385 * mono_reflection_is_valid_dynamic_token:
11387 * Returns TRUE if token is valid.
11390 gboolean
11391 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
11393 return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
11396 #ifndef DISABLE_REFLECTION_EMIT
11399 * mono_reflection_lookup_dynamic_token:
11401 * Finish the Builder object pointed to by TOKEN and return the corresponding
11402 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
11403 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
11404 * mapping table.
11406 * LOCKING: Take the loader lock
11408 gpointer
11409 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
11411 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
11412 MonoObject *obj;
11413 MonoClass *klass;
11415 mono_loader_lock ();
11416 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
11417 mono_loader_unlock ();
11418 if (!obj) {
11419 if (valid_token)
11420 g_error ("Could not find required dynamic token 0x%08x", token);
11421 else
11422 return NULL;
11425 if (!handle_class)
11426 handle_class = &klass;
11427 return resolve_object (image, obj, handle_class, context);
11431 * ensure_complete_type:
11433 * Ensure that KLASS is completed if it is a dynamic type, or references
11434 * dynamic types.
11436 static void
11437 ensure_complete_type (MonoClass *klass)
11439 if (klass->image->dynamic && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
11440 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11442 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11444 // Asserting here could break a lot of code
11445 //g_assert (klass->wastypebuilder);
11448 if (klass->generic_class) {
11449 MonoGenericInst *inst = klass->generic_class->context.class_inst;
11450 int i;
11452 for (i = 0; i < inst->type_argc; ++i) {
11453 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
11458 static gpointer
11459 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
11461 gpointer result = NULL;
11463 if (strcmp (obj->vtable->klass->name, "String") == 0) {
11464 result = mono_string_intern ((MonoString*)obj);
11465 *handle_class = mono_defaults.string_class;
11466 g_assert (result);
11467 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
11468 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11469 if (context) {
11470 MonoType *inflated = mono_class_inflate_generic_type (type, context);
11471 result = mono_class_from_mono_type (inflated);
11472 mono_metadata_free_type (inflated);
11473 } else {
11474 result = mono_class_from_mono_type (type);
11476 *handle_class = mono_defaults.typehandle_class;
11477 g_assert (result);
11478 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
11479 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
11480 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
11481 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
11482 result = ((MonoReflectionMethod*)obj)->method;
11483 if (context)
11484 result = mono_class_inflate_generic_method (result, context);
11485 *handle_class = mono_defaults.methodhandle_class;
11486 g_assert (result);
11487 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
11488 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
11489 result = mb->mhandle;
11490 if (!result) {
11491 /* Type is not yet created */
11492 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
11494 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11497 * Hopefully this has been filled in by calling CreateType() on the
11498 * TypeBuilder.
11501 * TODO: This won't work if the application finishes another
11502 * TypeBuilder instance instead of this one.
11504 result = mb->mhandle;
11506 if (context)
11507 result = mono_class_inflate_generic_method (result, context);
11508 *handle_class = mono_defaults.methodhandle_class;
11509 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
11510 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
11512 result = cb->mhandle;
11513 if (!result) {
11514 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
11516 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11517 result = cb->mhandle;
11519 if (context)
11520 result = mono_class_inflate_generic_method (result, context);
11521 *handle_class = mono_defaults.methodhandle_class;
11522 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
11523 MonoClassField *field = ((MonoReflectionField*)obj)->field;
11525 ensure_complete_type (field->parent);
11526 if (context) {
11527 MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
11528 MonoClass *class = mono_class_from_mono_type (inflated);
11529 MonoClassField *inflated_field;
11530 gpointer iter = NULL;
11531 mono_metadata_free_type (inflated);
11532 while ((inflated_field = mono_class_get_fields (class, &iter))) {
11533 if (!strcmp (field->name, inflated_field->name))
11534 break;
11536 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
11537 result = inflated_field;
11538 } else {
11539 result = field;
11541 *handle_class = mono_defaults.fieldhandle_class;
11542 g_assert (result);
11543 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
11544 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
11545 result = fb->handle;
11547 if (!result) {
11548 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
11550 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11551 result = fb->handle;
11554 if (fb->handle && fb->handle->parent->generic_container) {
11555 MonoClass *klass = fb->handle->parent;
11556 MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
11557 MonoClass *inflated = mono_class_from_mono_type (type);
11559 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
11560 g_assert (result);
11561 mono_metadata_free_type (type);
11563 *handle_class = mono_defaults.fieldhandle_class;
11564 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
11565 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
11566 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
11567 MonoClass *klass;
11569 klass = type->data.klass;
11570 if (klass->wastypebuilder) {
11571 /* Already created */
11572 result = klass;
11574 else {
11575 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11576 result = type->data.klass;
11577 g_assert (result);
11579 *handle_class = mono_defaults.typehandle_class;
11580 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
11581 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
11582 MonoMethodSignature *sig;
11583 int nargs, i;
11585 if (helper->arguments)
11586 nargs = mono_array_length (helper->arguments);
11587 else
11588 nargs = 0;
11590 sig = mono_metadata_signature_alloc (image, nargs);
11591 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
11592 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
11594 if (helper->unmanaged_call_conv) { /* unmanaged */
11595 sig->call_convention = helper->unmanaged_call_conv - 1;
11596 sig->pinvoke = TRUE;
11597 } else if (helper->call_conv & 0x02) {
11598 sig->call_convention = MONO_CALL_VARARG;
11599 } else {
11600 sig->call_convention = MONO_CALL_DEFAULT;
11603 sig->param_count = nargs;
11604 /* TODO: Copy type ? */
11605 sig->ret = helper->return_type->type;
11606 for (i = 0; i < nargs; ++i)
11607 sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
11609 result = sig;
11610 *handle_class = NULL;
11611 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11612 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11613 /* Already created by the managed code */
11614 g_assert (method->mhandle);
11615 result = method->mhandle;
11616 *handle_class = mono_defaults.methodhandle_class;
11617 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
11618 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11619 type = mono_class_inflate_generic_type (type, context);
11620 result = mono_class_from_mono_type (type);
11621 *handle_class = mono_defaults.typehandle_class;
11622 g_assert (result);
11623 mono_metadata_free_type (type);
11624 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
11625 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11626 type = mono_class_inflate_generic_type (type, context);
11627 result = mono_class_from_mono_type (type);
11628 *handle_class = mono_defaults.typehandle_class;
11629 g_assert (result);
11630 mono_metadata_free_type (type);
11631 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
11632 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
11633 MonoClass *inflated;
11634 MonoType *type;
11635 MonoClassField *field;
11637 if (is_sre_field_builder (mono_object_class (f->fb)))
11638 field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
11639 else if (is_sr_mono_field (mono_object_class (f->fb)))
11640 field = ((MonoReflectionField*)f->fb)->field;
11641 else
11642 g_error ("resolve_object:: can't handle a FTBI with base_method of type %s", mono_type_get_full_name (mono_object_class (f->fb)));
11644 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
11645 inflated = mono_class_from_mono_type (type);
11647 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
11648 ensure_complete_type (field->parent);
11649 g_assert (result);
11650 mono_metadata_free_type (type);
11651 *handle_class = mono_defaults.fieldhandle_class;
11652 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
11653 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
11654 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
11655 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11656 MonoMethod *method;
11658 if (is_sre_ctor_builder (mono_object_class (c->cb)))
11659 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
11660 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
11661 method = ((MonoReflectionMethod *)c->cb)->method;
11662 else
11663 g_error ("resolve_object:: can't handle a CTBI with base_method of type %s", mono_type_get_full_name (mono_object_class (c->cb)));
11665 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
11666 *handle_class = mono_defaults.methodhandle_class;
11667 mono_metadata_free_type (type);
11668 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
11669 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
11670 if (m->method_args) {
11671 result = mono_reflection_method_on_tb_inst_get_handle (m);
11672 } else {
11673 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
11674 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11675 MonoMethod *method;
11677 if (is_sre_method_builder (mono_object_class (m->mb)))
11678 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
11679 else if (is_sr_mono_method (mono_object_class (m->mb)))
11680 method = ((MonoReflectionMethod *)m->mb)->method;
11681 else
11682 g_error ("resolve_object:: can't handle a MTBI with base_method of type %s", mono_type_get_full_name (mono_object_class (m->mb)));
11684 result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
11685 mono_metadata_free_type (type);
11687 *handle_class = mono_defaults.methodhandle_class;
11688 } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
11689 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
11690 MonoType *mtype;
11691 MonoClass *klass;
11692 MonoMethod *method;
11693 gpointer iter;
11694 char *name;
11696 mtype = mono_reflection_type_get_handle (m->parent);
11697 klass = mono_class_from_mono_type (mtype);
11699 /* Find the method */
11701 name = mono_string_to_utf8 (m->name);
11702 iter = NULL;
11703 while ((method = mono_class_get_methods (klass, &iter))) {
11704 if (!strcmp (method->name, name))
11705 break;
11707 g_free (name);
11709 // FIXME:
11710 g_assert (method);
11711 // FIXME: Check parameters/return value etc. match
11713 result = method;
11714 *handle_class = mono_defaults.methodhandle_class;
11715 } else if (is_sre_array (mono_object_get_class(obj)) ||
11716 is_sre_byref (mono_object_get_class(obj)) ||
11717 is_sre_pointer (mono_object_get_class(obj))) {
11718 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
11719 MonoType *type = mono_reflection_type_get_handle (ref_type);
11720 result = mono_class_from_mono_type (type);
11721 *handle_class = mono_defaults.typehandle_class;
11722 } else {
11723 g_print ("%s\n", obj->vtable->klass->name);
11724 g_assert_not_reached ();
11726 return result;
11729 #else /* DISABLE_REFLECTION_EMIT */
11731 MonoArray*
11732 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
11734 g_assert_not_reached ();
11735 return NULL;
11738 void
11739 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
11741 g_assert_not_reached ();
11744 void
11745 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11747 g_assert_not_reached ();
11750 void
11751 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
11753 g_assert_not_reached ();
11756 void
11757 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11759 g_assert_not_reached ();
11762 void
11763 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
11765 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
11768 void
11769 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
11771 g_assert_not_reached ();
11774 void
11775 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
11777 g_assert_not_reached ();
11780 MonoReflectionModule *
11781 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
11783 g_assert_not_reached ();
11784 return NULL;
11787 guint32
11788 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
11790 g_assert_not_reached ();
11791 return 0;
11794 guint32
11795 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
11797 g_assert_not_reached ();
11798 return 0;
11801 guint32
11802 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
11803 gboolean create_methodspec, gboolean register_token)
11805 g_assert_not_reached ();
11806 return 0;
11809 void
11810 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
11814 void
11815 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
11816 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
11817 MonoArray *events)
11819 g_assert_not_reached ();
11822 void
11823 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
11825 *overrides = NULL;
11826 *num_overrides = 0;
11829 MonoReflectionEvent *
11830 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11832 g_assert_not_reached ();
11833 return NULL;
11836 MonoReflectionType*
11837 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11839 g_assert_not_reached ();
11840 return NULL;
11843 void
11844 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
11846 g_assert_not_reached ();
11849 MonoArray *
11850 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
11852 g_assert_not_reached ();
11853 return NULL;
11856 MonoArray *
11857 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
11859 g_assert_not_reached ();
11860 return NULL;
11863 void
11864 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
11868 gpointer
11869 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
11871 return NULL;
11874 MonoType*
11875 mono_reflection_type_get_handle (MonoReflectionType* ref)
11877 if (!ref)
11878 return NULL;
11879 return ref->type;
11882 #endif /* DISABLE_REFLECTION_EMIT */
11884 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
11885 const static guint32 declsec_flags_map[] = {
11886 0x00000000, /* empty */
11887 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
11888 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
11889 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
11890 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
11891 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
11892 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
11893 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
11894 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
11895 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
11896 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
11897 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
11898 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
11899 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
11900 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
11901 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
11902 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
11903 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
11904 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
11908 * Returns flags that includes all available security action associated to the handle.
11909 * @token: metadata token (either for a class or a method)
11910 * @image: image where resides the metadata.
11912 static guint32
11913 mono_declsec_get_flags (MonoImage *image, guint32 token)
11915 int index = mono_metadata_declsec_from_index (image, token);
11916 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
11917 guint32 result = 0;
11918 guint32 action;
11919 int i;
11921 /* HasSecurity can be present for other, not specially encoded, attributes,
11922 e.g. SuppressUnmanagedCodeSecurityAttribute */
11923 if (index < 0)
11924 return 0;
11926 for (i = index; i < t->rows; i++) {
11927 guint32 cols [MONO_DECL_SECURITY_SIZE];
11929 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
11930 if (cols [MONO_DECL_SECURITY_PARENT] != token)
11931 break;
11933 action = cols [MONO_DECL_SECURITY_ACTION];
11934 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
11935 result |= declsec_flags_map [action];
11936 } else {
11937 g_assert_not_reached ();
11940 return result;
11944 * Get the security actions (in the form of flags) associated with the specified method.
11946 * @method: The method for which we want the declarative security flags.
11947 * Return the declarative security flags for the method (only).
11949 * Note: To keep MonoMethod size down we do not cache the declarative security flags
11950 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
11952 guint32
11953 mono_declsec_flags_from_method (MonoMethod *method)
11955 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11956 /* FIXME: No cache (for the moment) */
11957 guint32 idx = mono_method_get_index (method);
11958 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11959 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
11960 return mono_declsec_get_flags (method->klass->image, idx);
11962 return 0;
11966 * Get the security actions (in the form of flags) associated with the specified class.
11968 * @klass: The class for which we want the declarative security flags.
11969 * Return the declarative security flags for the class.
11971 * Note: We cache the flags inside the MonoClass structure as this will get
11972 * called very often (at least for each method).
11974 guint32
11975 mono_declsec_flags_from_class (MonoClass *klass)
11977 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
11978 if (!klass->ext || !klass->ext->declsec_flags) {
11979 guint32 idx;
11981 idx = mono_metadata_token_index (klass->type_token);
11982 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11983 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
11984 mono_loader_lock ();
11985 mono_class_alloc_ext (klass);
11986 mono_loader_unlock ();
11987 /* we cache the flags on classes */
11988 klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
11990 return klass->ext->declsec_flags;
11992 return 0;
11996 * Get the security actions (in the form of flags) associated with the specified assembly.
11998 * @assembly: The assembly for which we want the declarative security flags.
11999 * Return the declarative security flags for the assembly.
12001 guint32
12002 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
12004 guint32 idx = 1; /* there is only one assembly */
12005 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12006 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12007 return mono_declsec_get_flags (assembly->image, idx);
12012 * Fill actions for the specific index (which may either be an encoded class token or
12013 * an encoded method token) from the metadata image.
12014 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
12016 static MonoBoolean
12017 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
12018 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12020 MonoBoolean result = FALSE;
12021 MonoTableInfo *t;
12022 guint32 cols [MONO_DECL_SECURITY_SIZE];
12023 int index = mono_metadata_declsec_from_index (image, token);
12024 int i;
12026 t = &image->tables [MONO_TABLE_DECLSECURITY];
12027 for (i = index; i < t->rows; i++) {
12028 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12030 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12031 return result;
12033 /* if present only replace (class) permissions with method permissions */
12034 /* if empty accept either class or method permissions */
12035 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
12036 if (!actions->demand.blob) {
12037 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12038 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12039 actions->demand.blob = (char*) (blob + 2);
12040 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
12041 result = TRUE;
12043 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
12044 if (!actions->noncasdemand.blob) {
12045 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12046 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12047 actions->noncasdemand.blob = (char*) (blob + 2);
12048 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
12049 result = TRUE;
12051 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
12052 if (!actions->demandchoice.blob) {
12053 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12054 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12055 actions->demandchoice.blob = (char*) (blob + 2);
12056 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
12057 result = TRUE;
12062 return result;
12065 static MonoBoolean
12066 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
12067 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12069 guint32 idx = mono_metadata_token_index (klass->type_token);
12070 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12071 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12072 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
12075 static MonoBoolean
12076 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
12077 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12079 guint32 idx = mono_method_get_index (method);
12080 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12081 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12082 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
12086 * Collect all actions (that requires to generate code in mini) assigned for
12087 * the specified method.
12088 * Note: Don't use the content of actions if the function return FALSE.
12090 MonoBoolean
12091 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
12093 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
12094 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
12095 MonoBoolean result = FALSE;
12096 guint32 flags;
12098 /* quick exit if no declarative security is present in the metadata */
12099 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12100 return FALSE;
12102 /* we want the original as the wrapper is "free" of the security informations */
12103 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12104 method = mono_marshal_method_from_wrapper (method);
12105 if (!method)
12106 return FALSE;
12109 /* First we look for method-level attributes */
12110 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12111 mono_class_init (method->klass);
12112 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12114 result = mono_declsec_get_method_demands_params (method, demands,
12115 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12118 /* Here we use (or create) the class declarative cache to look for demands */
12119 flags = mono_declsec_flags_from_class (method->klass);
12120 if (flags & mask) {
12121 if (!result) {
12122 mono_class_init (method->klass);
12123 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12125 result |= mono_declsec_get_class_demands_params (method->klass, demands,
12126 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12129 /* The boolean return value is used as a shortcut in case nothing needs to
12130 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
12131 return result;
12136 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
12138 * Note: Don't use the content of actions if the function return FALSE.
12140 MonoBoolean
12141 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
12143 MonoBoolean result = FALSE;
12144 guint32 flags;
12146 /* quick exit if no declarative security is present in the metadata */
12147 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12148 return FALSE;
12150 /* we want the original as the wrapper is "free" of the security informations */
12151 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12152 method = mono_marshal_method_from_wrapper (method);
12153 if (!method)
12154 return FALSE;
12157 /* results are independant - zeroize both */
12158 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
12159 memset (klass, 0, sizeof (MonoDeclSecurityActions));
12161 /* First we look for method-level attributes */
12162 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12163 mono_class_init (method->klass);
12165 result = mono_declsec_get_method_demands_params (method, cmethod,
12166 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12169 /* Here we use (or create) the class declarative cache to look for demands */
12170 flags = mono_declsec_flags_from_class (method->klass);
12171 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
12172 mono_class_init (method->klass);
12174 result |= mono_declsec_get_class_demands_params (method->klass, klass,
12175 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12178 return result;
12182 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12184 * @klass The inherited class - this is the class that provides the security check (attributes)
12185 * @demans
12186 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
12188 * Note: Don't use the content of actions if the function return FALSE.
12190 MonoBoolean
12191 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
12193 MonoBoolean result = FALSE;
12194 guint32 flags;
12196 /* quick exit if no declarative security is present in the metadata */
12197 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12198 return FALSE;
12200 /* Here we use (or create) the class declarative cache to look for demands */
12201 flags = mono_declsec_flags_from_class (klass);
12202 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
12203 mono_class_init (klass);
12204 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12206 result |= mono_declsec_get_class_demands_params (klass, demands,
12207 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12210 return result;
12214 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12216 * Note: Don't use the content of actions if the function return FALSE.
12218 MonoBoolean
12219 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
12221 /* quick exit if no declarative security is present in the metadata */
12222 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12223 return FALSE;
12225 /* we want the original as the wrapper is "free" of the security informations */
12226 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12227 method = mono_marshal_method_from_wrapper (method);
12228 if (!method)
12229 return FALSE;
12232 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12233 mono_class_init (method->klass);
12234 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12236 return mono_declsec_get_method_demands_params (method, demands,
12237 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12239 return FALSE;
12243 static MonoBoolean
12244 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
12246 guint32 cols [MONO_DECL_SECURITY_SIZE];
12247 MonoTableInfo *t;
12248 int i;
12250 int index = mono_metadata_declsec_from_index (image, token);
12251 if (index == -1)
12252 return FALSE;
12254 t = &image->tables [MONO_TABLE_DECLSECURITY];
12255 for (i = index; i < t->rows; i++) {
12256 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12258 /* shortcut - index are ordered */
12259 if (token != cols [MONO_DECL_SECURITY_PARENT])
12260 return FALSE;
12262 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
12263 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12264 entry->blob = (char*) (metadata + 2);
12265 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
12266 return TRUE;
12270 return FALSE;
12273 MonoBoolean
12274 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
12276 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12277 guint32 idx = mono_method_get_index (method);
12278 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12279 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12280 return get_declsec_action (method->klass->image, idx, action, entry);
12282 return FALSE;
12285 MonoBoolean
12286 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
12288 /* use cache */
12289 guint32 flags = mono_declsec_flags_from_class (klass);
12290 if (declsec_flags_map [action] & flags) {
12291 guint32 idx = mono_metadata_token_index (klass->type_token);
12292 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12293 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12294 return get_declsec_action (klass->image, idx, action, entry);
12296 return FALSE;
12299 MonoBoolean
12300 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
12302 guint32 idx = 1; /* there is only one assembly */
12303 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12304 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12306 return get_declsec_action (assembly->image, idx, action, entry);
12309 gboolean
12310 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
12312 MonoObject *res, *exc;
12313 void *params [1];
12314 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
12315 static MonoMethod *method = NULL;
12317 if (!System_Reflection_Emit_TypeBuilder) {
12318 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
12319 g_assert (System_Reflection_Emit_TypeBuilder);
12321 if (method == NULL) {
12322 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
12323 g_assert (method);
12327 * The result of mono_type_get_object () might be a System.MonoType but we
12328 * need a TypeBuilder so use mono_class_get_ref_info (klass).
12330 g_assert (mono_class_get_ref_info (klass));
12331 g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
12333 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
12335 res = mono_runtime_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc);
12336 if (exc)
12337 return FALSE;
12338 else
12339 return *(MonoBoolean*)mono_object_unbox (res);