2007-01-02 Jb Evain <jbevain@gmail.com>
[mono.git] / mono / metadata / reflection.c
blobd480a7884d6781655e4ad122706ad62908e5888f
1 /*
2 * reflection.c: Routines for creating an image at runtime.
3 *
4 * Author:
5 * Paolo Molaro (lupus@ximian.com)
7 * (C) 2001, 2002 Ximian, Inc. http://www.ximian.com
9 */
10 #include <config.h>
11 #include "mono/utils/mono-digest.h"
12 #include "mono/metadata/reflection.h"
13 #include "mono/metadata/tabledefs.h"
14 #include "mono/metadata/metadata-internals.h"
15 #include "mono/metadata/class-internals.h"
16 #include "mono/metadata/gc-internal.h"
17 #include "mono/metadata/tokentype.h"
18 #include "mono/metadata/domain-internals.h"
19 #include "mono/metadata/opcodes.h"
20 #include "mono/metadata/assembly.h"
21 #include "mono/metadata/object-internals.h"
22 #include <mono/metadata/exception.h>
23 #include <mono/metadata/marshal.h>
24 #include <mono/metadata/security-manager.h>
25 #include <stdio.h>
26 #include <glib.h>
27 #include <errno.h>
28 #include <time.h>
29 #include <string.h>
30 #include <ctype.h>
31 #include "image.h"
32 #include "cil-coff.h"
33 #include "rawbuffer.h"
34 #include "mono-endian.h"
35 #include <mono/os/gc_wrapper.h>
37 #define TEXT_OFFSET 512
38 #define CLI_H_SIZE 136
39 #define FILE_ALIGN 512
40 #define VIRT_ALIGN 8192
41 #define START_TEXT_RVA 0x00002000
43 typedef struct {
44 MonoReflectionILGen *ilgen;
45 MonoReflectionType *rtype;
46 MonoArray *parameters;
47 MonoArray *generic_params;
48 MonoGenericContainer *generic_container;
49 MonoArray *pinfo;
50 MonoArray *opt_types;
51 guint32 attrs;
52 guint32 iattrs;
53 guint32 call_conv;
54 guint32 *table_idx; /* note: it's a pointer */
55 MonoArray *code;
56 MonoObject *type;
57 MonoString *name;
58 MonoBoolean init_locals;
59 MonoBoolean skip_visibility;
60 MonoArray *return_modreq;
61 MonoArray *return_modopt;
62 MonoArray *param_modreq;
63 MonoArray *param_modopt;
64 MonoArray *permissions;
65 MonoMethod *mhandle;
66 guint32 nrefs;
67 gpointer *refs;
68 /* for PInvoke */
69 int charset, extra_flags, native_cc;
70 MonoString *dll, *dllentry;
71 } ReflectionMethodBuilder;
73 typedef struct {
74 guint32 owner;
75 MonoReflectionGenericParam *gparam;
76 } GenericParamTableEntry;
78 const unsigned char table_sizes [MONO_TABLE_NUM] = {
79 MONO_MODULE_SIZE,
80 MONO_TYPEREF_SIZE,
81 MONO_TYPEDEF_SIZE,
83 MONO_FIELD_SIZE,
85 MONO_METHOD_SIZE,
87 MONO_PARAM_SIZE,
88 MONO_INTERFACEIMPL_SIZE,
89 MONO_MEMBERREF_SIZE, /* 0x0A */
90 MONO_CONSTANT_SIZE,
91 MONO_CUSTOM_ATTR_SIZE,
92 MONO_FIELD_MARSHAL_SIZE,
93 MONO_DECL_SECURITY_SIZE,
94 MONO_CLASS_LAYOUT_SIZE,
95 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
96 MONO_STAND_ALONE_SIGNATURE_SIZE,
97 MONO_EVENT_MAP_SIZE,
99 MONO_EVENT_SIZE,
100 MONO_PROPERTY_MAP_SIZE,
102 MONO_PROPERTY_SIZE,
103 MONO_METHOD_SEMA_SIZE,
104 MONO_METHODIMPL_SIZE,
105 MONO_MODULEREF_SIZE, /* 0x1A */
106 MONO_TYPESPEC_SIZE,
107 MONO_IMPLMAP_SIZE,
108 MONO_FIELD_RVA_SIZE,
111 MONO_ASSEMBLY_SIZE, /* 0x20 */
112 MONO_ASSEMBLY_PROCESSOR_SIZE,
113 MONO_ASSEMBLYOS_SIZE,
114 MONO_ASSEMBLYREF_SIZE,
115 MONO_ASSEMBLYREFPROC_SIZE,
116 MONO_ASSEMBLYREFOS_SIZE,
117 MONO_FILE_SIZE,
118 MONO_EXP_TYPE_SIZE,
119 MONO_MANIFEST_SIZE,
120 MONO_NESTED_CLASS_SIZE,
122 MONO_GENERICPARAM_SIZE, /* 0x2A */
123 MONO_METHODSPEC_SIZE,
124 MONO_GENPARCONSTRAINT_SIZE
128 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
129 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
130 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
131 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method);
132 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb);
133 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
134 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
135 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
136 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
137 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
138 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
139 static void ensure_runtime_vtable (MonoClass *klass);
140 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class);
141 static void encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf);
142 static guint32 type_get_signature_size (MonoType *type);
143 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
144 static MonoObject *mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob);
145 static inline MonoType *dup_type (const MonoType *original);
148 * mp_g_alloc:
150 * Allocate memory from the mempool MP if it is non-NULL. Otherwise, allocate memory
151 * from the C heap.
153 static gpointer
154 mp_g_malloc (MonoMemPool *mp, guint size)
156 if (mp)
157 return mono_mempool_alloc (mp, size);
158 else
159 return g_malloc (size);
163 * mp_g_alloc0:
165 * Allocate memory from the mempool MP if it is non-NULL. Otherwise, allocate memory
166 * from the C heap.
168 static gpointer
169 mp_g_malloc0 (MonoMemPool *mp, guint size)
171 if (mp)
172 return mono_mempool_alloc0 (mp, size);
173 else
174 return g_malloc0 (size);
177 #define mp_g_new(mp,struct_type, n_structs) \
178 ((struct_type *) mp_g_malloc (mp, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
180 #define mp_g_new0(mp,struct_type, n_structs) \
181 ((struct_type *) mp_g_malloc0 (mp, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
183 static void
184 alloc_table (MonoDynamicTable *table, guint nrows)
186 table->rows = nrows;
187 g_assert (table->columns);
188 if (nrows + 1 >= table->alloc_rows) {
189 while (nrows + 1 >= table->alloc_rows) {
190 if (table->alloc_rows == 0)
191 table->alloc_rows = 16;
192 else
193 table->alloc_rows *= 2;
196 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
200 static void
201 make_room_in_stream (MonoDynamicStream *stream, int size)
203 if (size <= stream->alloc_size)
204 return;
206 while (stream->alloc_size <= size) {
207 if (stream->alloc_size < 4096)
208 stream->alloc_size = 4096;
209 else
210 stream->alloc_size *= 2;
213 stream->data = g_realloc (stream->data, stream->alloc_size);
216 static guint32
217 string_heap_insert (MonoDynamicStream *sh, const char *str)
219 guint32 idx;
220 guint32 len;
221 gpointer oldkey, oldval;
223 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
224 return GPOINTER_TO_UINT (oldval);
226 len = strlen (str) + 1;
227 idx = sh->index;
229 make_room_in_stream (sh, idx + len);
232 * We strdup the string even if we already copy them in sh->data
233 * so that the string pointers in the hash remain valid even if
234 * we need to realloc sh->data. We may want to avoid that later.
236 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
237 memcpy (sh->data + idx, str, len);
238 sh->index += len;
239 return idx;
242 static guint32
243 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
245 char *name = mono_string_to_utf8 (str);
246 guint32 idx;
247 idx = string_heap_insert (sh, name);
248 g_free (name);
249 return idx;
252 static void
253 string_heap_init (MonoDynamicStream *sh)
255 sh->index = 0;
256 sh->alloc_size = 4096;
257 sh->data = g_malloc (4096);
258 sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
259 string_heap_insert (sh, "");
262 static guint32
263 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
265 guint32 idx;
267 make_room_in_stream (stream, stream->index + len);
268 memcpy (stream->data + stream->index, data, len);
269 idx = stream->index;
270 stream->index += len;
272 * align index? Not without adding an additional param that controls it since
273 * we may store a blob value in pieces.
275 return idx;
278 static guint32
279 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
281 guint32 idx;
283 make_room_in_stream (stream, stream->index + len);
284 memset (stream->data + stream->index, 0, len);
285 idx = stream->index;
286 stream->index += len;
287 return idx;
290 static void
291 stream_data_align (MonoDynamicStream *stream)
293 char buf [4] = {0};
294 guint32 count = stream->index % 4;
296 /* we assume the stream data will be aligned */
297 if (count)
298 mono_image_add_stream_data (stream, buf, 4 - count);
301 static int
302 mono_blob_entry_hash (const char* str)
304 guint len, h;
305 const char *end;
306 len = mono_metadata_decode_blob_size (str, &str);
307 if (len > 0) {
308 end = str + len;
309 h = *str;
310 for (str += 1; str < end; str++)
311 h = (h << 5) - h + *str;
312 return h;
313 } else {
314 return 0;
318 static gboolean
319 mono_blob_entry_equal (const char *str1, const char *str2) {
320 int len, len2;
321 const char *end1;
322 const char *end2;
323 len = mono_metadata_decode_blob_size (str1, &end1);
324 len2 = mono_metadata_decode_blob_size (str2, &end2);
325 if (len != len2)
326 return 0;
327 return memcmp (end1, end2, len) == 0;
330 static guint32
331 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
333 guint32 idx;
334 char *copy;
335 gpointer oldkey, oldval;
337 copy = g_malloc (s1+s2);
338 memcpy (copy, b1, s1);
339 memcpy (copy + s1, b2, s2);
340 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
341 g_free (copy);
342 idx = GPOINTER_TO_UINT (oldval);
343 } else {
344 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
345 mono_image_add_stream_data (&assembly->blob, b2, s2);
346 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
348 return idx;
352 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
353 * dest may be misaligned.
355 static void
356 swap_with_size (char *dest, const char* val, int len, int nelem) {
357 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
358 int elem;
360 for (elem = 0; elem < nelem; ++elem) {
361 switch (len) {
362 case 1:
363 *dest = *val;
364 break;
365 case 2:
366 dest [0] = val [1];
367 dest [1] = val [0];
368 break;
369 case 4:
370 dest [0] = val [3];
371 dest [1] = val [2];
372 dest [2] = val [1];
373 dest [3] = val [0];
374 break;
375 case 8:
376 dest [0] = val [7];
377 dest [1] = val [6];
378 dest [2] = val [5];
379 dest [3] = val [4];
380 dest [4] = val [3];
381 dest [5] = val [2];
382 dest [6] = val [1];
383 dest [7] = val [0];
384 break;
385 default:
386 g_assert_not_reached ();
388 dest += len;
389 val += len;
391 #else
392 memcpy (dest, val, len * nelem);
393 #endif
396 static guint32
397 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
399 char blob_size [64];
400 char *b = blob_size;
401 guint32 idx = 0, len;
403 len = str->length * 2;
404 mono_metadata_encode_value (len, b, &b);
405 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
407 char *swapped = g_malloc (2 * mono_string_length (str));
408 const char *p = (const char*)mono_string_chars (str);
410 swap_with_size (swapped, p, 2, mono_string_length (str));
411 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
412 g_free (swapped);
414 #else
415 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
416 #endif
417 return idx;
420 /* modified version needed to handle building corlib */
421 static MonoClass*
422 my_mono_class_from_mono_type (MonoType *type) {
423 switch (type->type) {
424 case MONO_TYPE_ARRAY:
425 case MONO_TYPE_PTR:
426 case MONO_TYPE_SZARRAY:
427 case MONO_TYPE_GENERICINST:
428 return mono_class_from_mono_type (type);
429 case MONO_TYPE_VAR:
430 case MONO_TYPE_MVAR:
431 g_assert (type->data.generic_param->pklass);
432 return type->data.generic_param->pklass;
433 default:
434 /* should be always valid when we reach this case... */
435 return type->data.klass;
439 static MonoClass *
440 default_class_from_mono_type (MonoType *type)
442 switch (type->type) {
443 case MONO_TYPE_OBJECT:
444 return mono_defaults.object_class;
445 case MONO_TYPE_VOID:
446 return mono_defaults.void_class;
447 case MONO_TYPE_BOOLEAN:
448 return mono_defaults.boolean_class;
449 case MONO_TYPE_CHAR:
450 return mono_defaults.char_class;
451 case MONO_TYPE_I1:
452 return mono_defaults.sbyte_class;
453 case MONO_TYPE_U1:
454 return mono_defaults.byte_class;
455 case MONO_TYPE_I2:
456 return mono_defaults.int16_class;
457 case MONO_TYPE_U2:
458 return mono_defaults.uint16_class;
459 case MONO_TYPE_I4:
460 return mono_defaults.int32_class;
461 case MONO_TYPE_U4:
462 return mono_defaults.uint32_class;
463 case MONO_TYPE_I:
464 return mono_defaults.int_class;
465 case MONO_TYPE_U:
466 return mono_defaults.uint_class;
467 case MONO_TYPE_I8:
468 return mono_defaults.int64_class;
469 case MONO_TYPE_U8:
470 return mono_defaults.uint64_class;
471 case MONO_TYPE_R4:
472 return mono_defaults.single_class;
473 case MONO_TYPE_R8:
474 return mono_defaults.double_class;
475 case MONO_TYPE_STRING:
476 return mono_defaults.string_class;
477 default:
478 g_warning ("implement me 0x%02x\n", type->type);
479 g_assert_not_reached ();
482 return NULL;
485 static void
486 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, char *p, char **endbuf)
488 int i;
490 if (!gclass) {
491 g_assert_not_reached ();
492 return;
495 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
496 encode_type (assembly, &gclass->container_class->byval_arg, p, &p);
497 mono_metadata_encode_value (gclass->inst->type_argc, p, &p);
498 for (i = 0; i < gclass->inst->type_argc; ++i)
499 encode_type (assembly, gclass->inst->type_argv [i], p, &p);
501 *endbuf = p;
504 static void
505 encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf)
507 if (!type) {
508 g_assert_not_reached ();
509 return;
512 if (type->byref)
513 mono_metadata_encode_value (MONO_TYPE_BYREF, p, &p);
515 switch (type->type){
516 case MONO_TYPE_VOID:
517 case MONO_TYPE_BOOLEAN:
518 case MONO_TYPE_CHAR:
519 case MONO_TYPE_I1:
520 case MONO_TYPE_U1:
521 case MONO_TYPE_I2:
522 case MONO_TYPE_U2:
523 case MONO_TYPE_I4:
524 case MONO_TYPE_U4:
525 case MONO_TYPE_I8:
526 case MONO_TYPE_U8:
527 case MONO_TYPE_R4:
528 case MONO_TYPE_R8:
529 case MONO_TYPE_I:
530 case MONO_TYPE_U:
531 case MONO_TYPE_STRING:
532 case MONO_TYPE_OBJECT:
533 case MONO_TYPE_TYPEDBYREF:
534 mono_metadata_encode_value (type->type, p, &p);
535 break;
536 case MONO_TYPE_PTR:
537 mono_metadata_encode_value (type->type, p, &p);
538 encode_type (assembly, type->data.type, p, &p);
539 break;
540 case MONO_TYPE_SZARRAY:
541 mono_metadata_encode_value (type->type, p, &p);
542 encode_type (assembly, &type->data.klass->byval_arg, p, &p);
543 break;
544 case MONO_TYPE_VALUETYPE:
545 case MONO_TYPE_CLASS: {
546 MonoClass *k = mono_class_from_mono_type (type);
548 * Make sure we use the correct type.
550 mono_metadata_encode_value (k->byval_arg.type, p, &p);
552 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
553 * otherwise two typerefs could point to the same type, leading to
554 * verification errors.
556 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, &k->byval_arg), p, &p);
557 break;
559 case MONO_TYPE_ARRAY:
560 mono_metadata_encode_value (type->type, p, &p);
561 encode_type (assembly, &type->data.array->eklass->byval_arg, p, &p);
562 mono_metadata_encode_value (type->data.array->rank, p, &p);
563 mono_metadata_encode_value (0, p, &p); /* FIXME: set to 0 for now */
564 mono_metadata_encode_value (0, p, &p);
565 break;
566 case MONO_TYPE_GENERICINST:
567 encode_generic_class (assembly, type->data.generic_class, p, &p);
568 break;
569 case MONO_TYPE_VAR:
570 case MONO_TYPE_MVAR:
571 mono_metadata_encode_value (type->type, p, &p);
572 mono_metadata_encode_value (type->data.generic_param->num, p, &p);
573 break;
574 default:
575 g_error ("need to encode type %x", type->type);
577 *endbuf = p;
580 static void
581 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, char *p, char **endbuf)
583 if (!type) {
584 mono_metadata_encode_value (MONO_TYPE_VOID, p, endbuf);
585 return;
587 if (type->type) {
588 encode_type (assembly, type->type, p, endbuf);
589 return;
592 g_assert_not_reached ();
596 static void
597 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, char *p, char **endbuf)
599 int i;
601 if (modreq) {
602 for (i = 0; i < mono_array_length (modreq); ++i) {
603 MonoReflectionType *mod = mono_array_get (modreq, MonoReflectionType*, i);
604 *p = MONO_TYPE_CMOD_REQD;
605 p++;
606 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
609 if (modopt) {
610 for (i = 0; i < mono_array_length (modopt); ++i) {
611 MonoReflectionType *mod = mono_array_get (modopt, MonoReflectionType*, i);
612 *p = MONO_TYPE_CMOD_OPT;
613 p++;
614 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
617 *endbuf = p;
620 static guint32
621 generic_class_get_signature_size (MonoGenericClass *gclass)
623 guint32 size = 0;
624 int i;
626 if (!gclass) {
627 g_assert_not_reached ();
630 size += 1 + type_get_signature_size (&gclass->container_class->byval_arg);
631 size += 4;
632 for (i = 0; i < gclass->inst->type_argc; ++i)
633 size += type_get_signature_size (gclass->inst->type_argv [i]);
635 return size;
638 static guint32
639 type_get_signature_size (MonoType *type)
641 guint32 size = 0;
643 if (!type) {
644 g_assert_not_reached ();
647 if (type->byref)
648 size++;
650 switch (type->type){
651 case MONO_TYPE_VOID:
652 case MONO_TYPE_BOOLEAN:
653 case MONO_TYPE_CHAR:
654 case MONO_TYPE_I1:
655 case MONO_TYPE_U1:
656 case MONO_TYPE_I2:
657 case MONO_TYPE_U2:
658 case MONO_TYPE_I4:
659 case MONO_TYPE_U4:
660 case MONO_TYPE_I8:
661 case MONO_TYPE_U8:
662 case MONO_TYPE_R4:
663 case MONO_TYPE_R8:
664 case MONO_TYPE_I:
665 case MONO_TYPE_U:
666 case MONO_TYPE_STRING:
667 case MONO_TYPE_OBJECT:
668 case MONO_TYPE_TYPEDBYREF:
669 return size + 1;
670 case MONO_TYPE_PTR:
671 return size + 1 + type_get_signature_size (type->data.type);
672 case MONO_TYPE_SZARRAY:
673 return size + 1 + type_get_signature_size (&type->data.klass->byval_arg);
674 case MONO_TYPE_VALUETYPE:
675 case MONO_TYPE_CLASS:
676 return size + 5;
677 case MONO_TYPE_ARRAY:
678 return size + 7 + type_get_signature_size (&type->data.array->eklass->byval_arg);
679 case MONO_TYPE_GENERICINST:
680 return size + generic_class_get_signature_size (type->data.generic_class);
681 case MONO_TYPE_VAR:
682 case MONO_TYPE_MVAR:
683 return size + 5;
684 default:
685 g_error ("need to encode type %x", type->type);
686 return size;
690 static guint32
691 method_get_signature_size (MonoMethodSignature *sig)
693 guint32 size;
694 int i;
696 size = type_get_signature_size (sig->ret);
697 for (i = 0; i < sig->param_count; i++)
698 size += type_get_signature_size (sig->params [i]);
700 if (sig->generic_param_count)
701 size += 4;
702 if (sig->sentinelpos >= 0)
703 size++;
705 return size;
708 static guint32
709 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
711 char *buf;
712 char *p;
713 int i;
714 guint32 nparams = sig->param_count;
715 guint32 size = 11 + method_get_signature_size (sig);
716 guint32 idx;
717 char blob_size [6];
718 char *b = blob_size;
720 if (!assembly->save)
721 return 0;
723 p = buf = g_malloc (size);
725 * FIXME: vararg, explicit_this, differenc call_conv values...
727 *p = sig->call_convention;
728 if (sig->hasthis)
729 *p |= 0x20; /* hasthis */
730 if (sig->generic_param_count)
731 *p |= 0x10; /* generic */
732 p++;
733 if (sig->generic_param_count)
734 mono_metadata_encode_value (sig->generic_param_count, p, &p);
735 mono_metadata_encode_value (nparams, p, &p);
736 encode_type (assembly, sig->ret, p, &p);
737 for (i = 0; i < nparams; ++i) {
738 if (i == sig->sentinelpos)
739 *p++ = MONO_TYPE_SENTINEL;
740 encode_type (assembly, sig->params [i], p, &p);
742 /* store length */
743 g_assert (p - buf < size);
744 mono_metadata_encode_value (p-buf, b, &b);
745 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
746 g_free (buf);
747 return idx;
750 static guint32
751 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
754 * FIXME: reuse code from method_encode_signature().
756 char *buf;
757 char *p;
758 int i;
759 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
760 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
761 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
762 guint32 size = 41 + nparams * 40 + notypes * 40;
763 guint32 idx;
764 char blob_size [6];
765 char *b = blob_size;
767 p = buf = g_malloc (size);
768 /* LAMESPEC: all the call conv spec is foobared */
769 *p = mb->call_conv & 0x60; /* has-this, explicit-this */
770 if (mb->call_conv & 2)
771 *p |= 0x5; /* vararg */
772 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
773 *p |= 0x20; /* hasthis */
774 if (ngparams)
775 *p |= 0x10; /* generic */
776 p++;
777 if (ngparams)
778 mono_metadata_encode_value (ngparams, p, &p);
779 mono_metadata_encode_value (nparams + notypes, p, &p);
780 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, p, &p);
781 encode_reflection_type (assembly, mb->rtype, p, &p);
782 for (i = 0; i < nparams; ++i) {
783 MonoArray *modreq = NULL;
784 MonoArray *modopt = NULL;
785 MonoReflectionType *pt;
787 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
788 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
789 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
790 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
791 encode_custom_modifiers (assembly, modreq, modopt, p, &p);
792 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
793 encode_reflection_type (assembly, pt, p, &p);
795 if (notypes)
796 *p++ = MONO_TYPE_SENTINEL;
797 for (i = 0; i < notypes; ++i) {
798 MonoReflectionType *pt;
800 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
801 encode_reflection_type (assembly, pt, p, &p);
804 /* store length */
805 g_assert (p - buf < size);
806 mono_metadata_encode_value (p-buf, b, &b);
807 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
808 g_free (buf);
809 return idx;
812 static guint32
813 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
815 MonoDynamicTable *table;
816 guint32 *values;
817 char *p;
818 guint32 idx, sig_idx, size;
819 guint nl = mono_array_length (ilgen->locals);
820 char *buf;
821 char blob_size [6];
822 char *b = blob_size;
823 int i;
825 size = 50 + nl * 30;
826 p = buf = g_malloc (size);
827 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
828 idx = table->next_idx ++;
829 table->rows ++;
830 alloc_table (table, table->rows);
831 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
833 mono_metadata_encode_value (0x07, p, &p);
834 mono_metadata_encode_value (nl, p, &p);
835 for (i = 0; i < nl; ++i) {
836 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
838 if (lb->is_pinned)
839 mono_metadata_encode_value (MONO_TYPE_PINNED, p, &p);
841 encode_reflection_type (assembly, lb->type, p, &p);
843 g_assert (p - buf < size);
844 mono_metadata_encode_value (p-buf, b, &b);
845 sig_idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
846 g_free (buf);
848 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
850 return idx;
853 static guint32
854 method_count_clauses (MonoReflectionILGen *ilgen)
856 guint32 num_clauses = 0;
857 int i;
859 MonoILExceptionInfo *ex_info;
860 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
861 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
862 if (ex_info->handlers)
863 num_clauses += mono_array_length (ex_info->handlers);
864 else
865 num_clauses++;
868 return num_clauses;
871 static MonoExceptionClause*
872 method_encode_clauses (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
874 MonoExceptionClause *clauses;
875 MonoExceptionClause *clause;
876 MonoILExceptionInfo *ex_info;
877 MonoILExceptionBlock *ex_block;
878 guint32 finally_start;
879 int i, j, clause_index;;
881 clauses = g_new0 (MonoExceptionClause, num_clauses);
883 clause_index = 0;
884 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
885 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
886 finally_start = ex_info->start + ex_info->len;
887 if (!ex_info->handlers)
888 continue;
889 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
890 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
891 clause = &(clauses [clause_index]);
893 clause->flags = ex_block->type;
894 clause->try_offset = ex_info->start;
896 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
897 clause->try_len = finally_start - ex_info->start;
898 else
899 clause->try_len = ex_info->len;
900 clause->handler_offset = ex_block->start;
901 clause->handler_len = ex_block->len;
902 if (ex_block->extype) {
903 clause->data.catch_class = mono_class_from_mono_type (ex_block->extype->type);
904 } else {
905 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
906 clause->data.filter_offset = ex_block->filter_offset;
907 else
908 clause->data.filter_offset = 0;
910 finally_start = ex_block->start + ex_block->len;
912 clause_index ++;
916 return clauses;
919 static guint32
920 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
922 char flags = 0;
923 guint32 idx;
924 guint32 code_size;
925 gint32 max_stack, i;
926 gint32 num_locals = 0;
927 gint32 num_exception = 0;
928 gint maybe_small;
929 guint32 fat_flags;
930 char fat_header [12];
931 guint32 int_value;
932 guint16 short_value;
933 guint32 local_sig = 0;
934 guint32 header_size = 12;
935 MonoArray *code;
937 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
938 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
939 return 0;
941 /*if (mb->name)
942 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
943 if (mb->ilgen) {
944 code = mb->ilgen->code;
945 code_size = mb->ilgen->code_len;
946 max_stack = mb->ilgen->max_stack;
947 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
948 if (mb->ilgen->ex_handlers)
949 num_exception = method_count_clauses (mb->ilgen);
950 } else {
951 code = mb->code;
952 if (code == NULL){
953 char *name = mono_string_to_utf8 (mb->name);
954 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
955 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
956 g_free (str);
957 g_free (name);
958 mono_raise_exception (exception);
961 code_size = mono_array_length (code);
962 max_stack = 8; /* we probably need to run a verifier on the code... */
965 stream_data_align (&assembly->code);
967 /* check for exceptions, maxstack, locals */
968 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
969 if (maybe_small) {
970 if (code_size < 64 && !(code_size & 1)) {
971 flags = (code_size << 2) | 0x2;
972 } else if (code_size < 32 && (code_size & 1)) {
973 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
974 } else {
975 goto fat_header;
977 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
978 /* add to the fixup todo list */
979 if (mb->ilgen && mb->ilgen->num_token_fixups)
980 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
981 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
982 return assembly->text_rva + idx;
984 fat_header:
985 if (num_locals)
986 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
988 * FIXME: need to set also the header size in fat_flags.
989 * (and more sects and init locals flags)
991 fat_flags = 0x03;
992 if (num_exception)
993 fat_flags |= METHOD_HEADER_MORE_SECTS;
994 if (mb->init_locals)
995 fat_flags |= METHOD_HEADER_INIT_LOCALS;
996 fat_header [0] = fat_flags;
997 fat_header [1] = (header_size / 4 ) << 4;
998 short_value = GUINT16_TO_LE (max_stack);
999 memcpy (fat_header + 2, &short_value, 2);
1000 int_value = GUINT32_TO_LE (code_size);
1001 memcpy (fat_header + 4, &int_value, 4);
1002 int_value = GUINT32_TO_LE (local_sig);
1003 memcpy (fat_header + 8, &int_value, 4);
1004 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1005 /* add to the fixup todo list */
1006 if (mb->ilgen && mb->ilgen->num_token_fixups)
1007 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1009 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1010 if (num_exception) {
1011 unsigned char sheader [4];
1012 MonoILExceptionInfo * ex_info;
1013 MonoILExceptionBlock * ex_block;
1014 int j;
1016 stream_data_align (&assembly->code);
1017 /* always use fat format for now */
1018 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1019 num_exception *= 6 * sizeof (guint32);
1020 num_exception += 4; /* include the size of the header */
1021 sheader [1] = num_exception & 0xff;
1022 sheader [2] = (num_exception >> 8) & 0xff;
1023 sheader [3] = (num_exception >> 16) & 0xff;
1024 mono_image_add_stream_data (&assembly->code, sheader, 4);
1025 /* fat header, so we are already aligned */
1026 /* reverse order */
1027 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1028 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1029 if (ex_info->handlers) {
1030 int finally_start = ex_info->start + ex_info->len;
1031 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1032 guint32 val;
1033 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1034 /* the flags */
1035 val = GUINT32_TO_LE (ex_block->type);
1036 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1037 /* try offset */
1038 val = GUINT32_TO_LE (ex_info->start);
1039 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1040 /* need fault, too, probably */
1041 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1042 val = GUINT32_TO_LE (finally_start - ex_info->start);
1043 else
1044 val = GUINT32_TO_LE (ex_info->len);
1045 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1046 /* handler offset */
1047 val = GUINT32_TO_LE (ex_block->start);
1048 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1049 /* handler len */
1050 val = GUINT32_TO_LE (ex_block->len);
1051 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1052 finally_start = ex_block->start + ex_block->len;
1053 if (ex_block->extype) {
1054 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, ex_block->extype->type));
1055 } else {
1056 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1057 val = ex_block->filter_offset;
1058 else
1059 val = 0;
1061 val = GUINT32_TO_LE (val);
1062 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1063 /*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",
1064 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);*/
1066 } else {
1067 g_error ("No clauses for ex info block %d", i);
1071 return assembly->text_rva + idx;
1074 static guint32
1075 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1077 int i;
1078 MonoDynamicTable *table;
1079 guint32 *values;
1081 table = &assembly->tables [table_idx];
1083 g_assert (col < table->columns);
1085 values = table->values + table->columns;
1086 for (i = 1; i <= table->rows; ++i) {
1087 if (values [col] == token)
1088 return i;
1089 values += table->columns;
1091 return 0;
1094 static GHashTable *dynamic_custom_attrs = NULL;
1096 static gboolean
1097 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1099 /* FIXME: Need to do more checks */
1100 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1101 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1103 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1104 return FALSE;
1107 return TRUE;
1110 static MonoCustomAttrInfo*
1111 mono_custom_attrs_from_builders (MonoImage *image, MonoArray *cattrs)
1113 int i, index, count, not_visible;
1114 MonoCustomAttrInfo *ainfo;
1115 MonoReflectionCustomAttr *cattr;
1117 if (!cattrs)
1118 return NULL;
1119 /* FIXME: check in assembly the Run flag is set */
1121 count = mono_array_length (cattrs);
1123 /* Skip nonpublic attributes since MS.NET seems to do the same */
1124 /* FIXME: This needs to be done more globally */
1125 not_visible = 0;
1126 for (i = 0; i < count; ++i) {
1127 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1128 if (!custom_attr_visible (image, cattr))
1129 not_visible ++;
1131 count -= not_visible;
1133 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
1135 ainfo->image = image;
1136 ainfo->num_attrs = count;
1137 index = 0;
1138 for (i = 0; i < count; ++i) {
1139 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1140 if (custom_attr_visible (image, cattr)) {
1141 ainfo->attrs [index].ctor = cattr->ctor->method;
1142 /* FIXME: might want to memdup the data here */
1143 ainfo->attrs [index].data = mono_array_addr (cattr->data, char, 0);
1144 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1145 index ++;
1149 return ainfo;
1152 static void
1153 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1155 MonoCustomAttrInfo *ainfo = mono_custom_attrs_from_builders (image, cattrs);
1157 if (!ainfo)
1158 return;
1160 if (!dynamic_custom_attrs)
1161 dynamic_custom_attrs = g_hash_table_new (NULL, NULL);
1163 g_hash_table_insert (dynamic_custom_attrs, obj, ainfo);
1164 ainfo->cached = TRUE;
1167 void
1168 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1170 if (!ainfo->cached)
1171 g_free (ainfo);
1175 * idx is the table index of the object
1176 * type is one of MONO_CUSTOM_ATTR_*
1178 static void
1179 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1181 MonoDynamicTable *table;
1182 MonoReflectionCustomAttr *cattr;
1183 guint32 *values;
1184 guint32 count, i, token;
1185 char blob_size [6];
1186 char *p = blob_size;
1188 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1189 if (!cattrs)
1190 return;
1191 count = mono_array_length (cattrs);
1192 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1193 table->rows += count;
1194 alloc_table (table, table->rows);
1195 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1196 idx <<= MONO_CUSTOM_ATTR_BITS;
1197 idx |= type;
1198 for (i = 0; i < count; ++i) {
1199 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1200 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1201 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE);
1202 type = mono_metadata_token_index (token);
1203 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1204 switch (mono_metadata_token_table (token)) {
1205 case MONO_TABLE_METHOD:
1206 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1207 break;
1208 case MONO_TABLE_MEMBERREF:
1209 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1210 break;
1211 default:
1212 g_warning ("got wrong token in custom attr");
1213 continue;
1215 values [MONO_CUSTOM_ATTR_TYPE] = type;
1216 p = blob_size;
1217 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1218 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1219 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1220 values += MONO_CUSTOM_ATTR_SIZE;
1221 ++table->next_idx;
1225 static void
1226 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1228 MonoDynamicTable *table;
1229 guint32 *values;
1230 guint32 count, i, idx;
1231 MonoReflectionPermissionSet *perm;
1233 if (!permissions)
1234 return;
1236 count = mono_array_length (permissions);
1237 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1238 table->rows += count;
1239 alloc_table (table, table->rows);
1241 for (i = 0; i < mono_array_length (permissions); ++i) {
1242 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1244 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1246 idx = mono_metadata_token_index (parent_token);
1247 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1248 switch (mono_metadata_token_table (parent_token)) {
1249 case MONO_TABLE_TYPEDEF:
1250 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1251 break;
1252 case MONO_TABLE_METHOD:
1253 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1254 break;
1255 case MONO_TABLE_ASSEMBLY:
1256 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1257 break;
1258 default:
1259 g_assert_not_reached ();
1262 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1263 values [MONO_DECL_SECURITY_PARENT] = idx;
1264 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1266 ++table->next_idx;
1271 * Fill in the MethodDef and ParamDef tables for a method.
1272 * This is used for both normal methods and constructors.
1274 static void
1275 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1277 MonoDynamicTable *table;
1278 guint32 *values;
1279 guint i, count;
1281 /* room in this table is already allocated */
1282 table = &assembly->tables [MONO_TABLE_METHOD];
1283 *mb->table_idx = table->next_idx ++;
1284 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1285 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1286 values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1287 values [MONO_METHOD_FLAGS] = mb->attrs;
1288 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1289 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1290 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1292 table = &assembly->tables [MONO_TABLE_PARAM];
1293 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1295 mono_image_add_decl_security (assembly,
1296 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1298 if (mb->pinfo) {
1299 MonoDynamicTable *mtable;
1300 guint32 *mvalues;
1302 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1303 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1305 count = 0;
1306 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1307 if (mono_array_get (mb->pinfo, gpointer, i))
1308 count++;
1310 table->rows += count;
1311 alloc_table (table, table->rows);
1312 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1313 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1314 MonoReflectionParamBuilder *pb;
1315 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1316 values [MONO_PARAM_FLAGS] = pb->attrs;
1317 values [MONO_PARAM_SEQUENCE] = i;
1318 if (pb->name != NULL) {
1319 values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1320 } else {
1321 values [MONO_PARAM_NAME] = 0;
1323 values += MONO_PARAM_SIZE;
1324 if (pb->marshal_info) {
1325 mtable->rows++;
1326 alloc_table (mtable, mtable->rows);
1327 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1328 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1329 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1331 pb->table_idx = table->next_idx++;
1332 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1333 guint32 field_type = 0;
1334 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1335 mtable->rows ++;
1336 alloc_table (mtable, mtable->rows);
1337 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1338 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1339 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1340 mvalues [MONO_CONSTANT_TYPE] = field_type;
1341 mvalues [MONO_CONSTANT_PADDING] = 0;
1348 static void
1349 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1351 rmb->ilgen = mb->ilgen;
1352 rmb->rtype = mb->rtype;
1353 rmb->parameters = mb->parameters;
1354 rmb->generic_params = mb->generic_params;
1355 rmb->generic_container = mb->generic_container;
1356 rmb->opt_types = NULL;
1357 rmb->pinfo = mb->pinfo;
1358 rmb->attrs = mb->attrs;
1359 rmb->iattrs = mb->iattrs;
1360 rmb->call_conv = mb->call_conv;
1361 rmb->code = mb->code;
1362 rmb->type = mb->type;
1363 rmb->name = mb->name;
1364 rmb->table_idx = &mb->table_idx;
1365 rmb->init_locals = mb->init_locals;
1366 rmb->return_modreq = mb->return_modreq;
1367 rmb->return_modopt = mb->return_modopt;
1368 rmb->param_modreq = mb->param_modreq;
1369 rmb->param_modopt = mb->param_modopt;
1370 rmb->permissions = mb->permissions;
1371 rmb->mhandle = mb->mhandle;
1372 rmb->nrefs = 0;
1373 rmb->refs = NULL;
1375 if (mb->dll) {
1376 rmb->charset = mb->charset;
1377 rmb->extra_flags = mb->extra_flags;
1378 rmb->native_cc = mb->native_cc;
1379 rmb->dllentry = mb->dllentry;
1380 rmb->dll = mb->dll;
1384 static void
1385 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1387 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1389 rmb->ilgen = mb->ilgen;
1390 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1391 rmb->parameters = mb->parameters;
1392 rmb->generic_params = NULL;
1393 rmb->generic_container = NULL;
1394 rmb->opt_types = NULL;
1395 rmb->pinfo = mb->pinfo;
1396 rmb->attrs = mb->attrs;
1397 rmb->iattrs = mb->iattrs;
1398 rmb->call_conv = mb->call_conv;
1399 rmb->code = NULL;
1400 rmb->type = mb->type;
1401 rmb->name = mono_string_new (mono_domain_get (), name);
1402 rmb->table_idx = &mb->table_idx;
1403 rmb->init_locals = mb->init_locals;
1404 rmb->return_modreq = NULL;
1405 rmb->return_modopt = NULL;
1406 rmb->param_modreq = mb->param_modreq;
1407 rmb->param_modopt = mb->param_modopt;
1408 rmb->permissions = mb->permissions;
1409 rmb->mhandle = mb->mhandle;
1410 rmb->nrefs = 0;
1411 rmb->refs = NULL;
1414 static void
1415 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1417 rmb->ilgen = mb->ilgen;
1418 rmb->rtype = mb->rtype;
1419 rmb->parameters = mb->parameters;
1420 rmb->generic_params = NULL;
1421 rmb->generic_container = NULL;
1422 rmb->opt_types = NULL;
1423 rmb->pinfo = NULL;
1424 rmb->attrs = mb->attrs;
1425 rmb->iattrs = 0;
1426 rmb->call_conv = mb->call_conv;
1427 rmb->code = NULL;
1428 rmb->type = NULL;
1429 rmb->name = mb->name;
1430 rmb->table_idx = NULL;
1431 rmb->init_locals = mb->init_locals;
1432 rmb->skip_visibility = mb->skip_visibility;
1433 rmb->return_modreq = NULL;
1434 rmb->return_modopt = NULL;
1435 rmb->param_modreq = NULL;
1436 rmb->param_modopt = NULL;
1437 rmb->permissions = NULL;
1438 rmb->mhandle = mb->mhandle;
1439 rmb->nrefs = 0;
1440 rmb->refs = NULL;
1443 static void
1444 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1446 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1447 MonoDynamicTable *table;
1448 guint32 *values;
1449 guint32 tok;
1451 if (!mb->override_method)
1452 return;
1454 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1455 table->rows ++;
1456 alloc_table (table, table->rows);
1457 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1458 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1459 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1461 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE);
1462 switch (mono_metadata_token_table (tok)) {
1463 case MONO_TABLE_MEMBERREF:
1464 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1465 break;
1466 case MONO_TABLE_METHOD:
1467 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1468 break;
1469 default:
1470 g_assert_not_reached ();
1472 values [MONO_METHODIMPL_DECLARATION] = tok;
1475 static void
1476 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1478 MonoDynamicTable *table;
1479 guint32 *values;
1480 ReflectionMethodBuilder rmb;
1481 int i;
1483 reflection_methodbuilder_from_method_builder (&rmb, mb);
1485 mono_image_basic_method (&rmb, assembly);
1486 mb->table_idx = *rmb.table_idx;
1488 if (mb->dll) { /* It's a P/Invoke method */
1489 guint32 moduleref;
1490 /* map CharSet values to on-disk values */
1491 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1492 int extra_flags = mb->extra_flags;
1493 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1494 table->rows ++;
1495 alloc_table (table, table->rows);
1496 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1498 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1499 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1500 if (mb->dllentry)
1501 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1502 else
1503 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1504 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1505 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1506 table = &assembly->tables [MONO_TABLE_MODULEREF];
1507 table->rows ++;
1508 alloc_table (table, table->rows);
1509 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1510 values [MONO_IMPLMAP_SCOPE] = table->rows;
1514 if (mb->generic_params) {
1515 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1516 table->rows += mono_array_length (mb->generic_params);
1517 alloc_table (table, table->rows);
1518 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1519 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1521 mono_image_get_generic_param_info (
1522 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1528 static void
1529 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1531 ReflectionMethodBuilder rmb;
1533 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1535 mono_image_basic_method (&rmb, assembly);
1536 mb->table_idx = *rmb.table_idx;
1539 static char*
1540 type_get_fully_qualified_name (MonoType *type)
1542 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1545 static char*
1546 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1547 MonoClass *klass;
1548 MonoAssembly *ta;
1550 klass = my_mono_class_from_mono_type (type);
1551 if (!klass)
1552 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1553 ta = klass->image->assembly;
1554 if (ta->dynamic || (ta == ass))
1555 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1557 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1560 static guint32
1561 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
1563 char blob_size [64];
1564 char *b = blob_size;
1565 char *p;
1566 char* buf;
1567 guint32 idx;
1569 if (!assembly->save)
1570 return 0;
1572 p = buf = g_malloc (256);
1574 mono_metadata_encode_value (0x06, p, &p);
1575 /* encode custom attributes before the type */
1576 encode_type (assembly, type, p, &p);
1577 g_assert (p-buf < 256);
1578 mono_metadata_encode_value (p-buf, b, &b);
1579 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1580 g_free (buf);
1581 return idx;
1584 static guint32
1585 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1587 char blob_size [64];
1588 char *b = blob_size;
1589 char *p;
1590 char* buf;
1591 guint32 idx;
1593 p = buf = g_malloc (256);
1595 mono_metadata_encode_value (0x06, p, &p);
1596 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, p, &p);
1597 /* encode custom attributes before the type */
1598 encode_reflection_type (assembly, fb->type, p, &p);
1599 g_assert (p-buf < 256);
1600 mono_metadata_encode_value (p-buf, b, &b);
1601 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1602 g_free (buf);
1603 return idx;
1606 static guint32
1607 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1608 char blob_size [64];
1609 char *b = blob_size;
1610 char *p, *box_val;
1611 char* buf;
1612 guint32 idx = 0, len = 0, dummy = 0;
1613 #ifdef ARM_FPU_FPA
1614 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1615 guint32 fpa_double [2];
1616 guint32 *fpa_p;
1617 #endif
1618 #endif
1620 p = buf = g_malloc (64);
1621 if (!val) {
1622 *ret_type = MONO_TYPE_CLASS;
1623 len = 4;
1624 box_val = (char*)&dummy;
1625 } else {
1626 box_val = ((char*)val) + sizeof (MonoObject);
1627 *ret_type = val->vtable->klass->byval_arg.type;
1629 handle_enum:
1630 switch (*ret_type) {
1631 case MONO_TYPE_BOOLEAN:
1632 case MONO_TYPE_U1:
1633 case MONO_TYPE_I1:
1634 len = 1;
1635 break;
1636 case MONO_TYPE_CHAR:
1637 case MONO_TYPE_U2:
1638 case MONO_TYPE_I2:
1639 len = 2;
1640 break;
1641 case MONO_TYPE_U4:
1642 case MONO_TYPE_I4:
1643 case MONO_TYPE_R4:
1644 len = 4;
1645 break;
1646 case MONO_TYPE_U8:
1647 case MONO_TYPE_I8:
1648 len = 8;
1649 break;
1650 case MONO_TYPE_R8:
1651 len = 8;
1652 #ifdef ARM_FPU_FPA
1653 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1654 fpa_p = (guint32*)box_val;
1655 fpa_double [0] = fpa_p [1];
1656 fpa_double [1] = fpa_p [0];
1657 box_val = (char*)fpa_double;
1658 #endif
1659 #endif
1660 break;
1661 case MONO_TYPE_VALUETYPE:
1662 if (val->vtable->klass->enumtype) {
1663 *ret_type = val->vtable->klass->enum_basetype->type;
1664 goto handle_enum;
1665 } else
1666 g_error ("we can't encode valuetypes");
1667 case MONO_TYPE_CLASS:
1668 break;
1669 case MONO_TYPE_STRING: {
1670 MonoString *str = (MonoString*)val;
1671 /* there is no signature */
1672 len = str->length * 2;
1673 mono_metadata_encode_value (len, b, &b);
1674 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1676 char *swapped = g_malloc (2 * mono_string_length (str));
1677 const char *p = (const char*)mono_string_chars (str);
1679 swap_with_size (swapped, p, 2, mono_string_length (str));
1680 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1681 g_free (swapped);
1683 #else
1684 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1685 #endif
1687 g_free (buf);
1688 return idx;
1690 default:
1691 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1694 /* there is no signature */
1695 mono_metadata_encode_value (len, b, &b);
1696 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1697 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1698 swap_with_size (blob_size, box_val, len, 1);
1699 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1700 #else
1701 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1702 #endif
1704 g_free (buf);
1705 return idx;
1708 static guint32
1709 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1710 char blob_size [64];
1711 char *b = blob_size;
1712 char *p, *buf, *str;
1713 guint32 idx, len, bufsize = 256;
1715 p = buf = g_malloc (bufsize);
1717 mono_metadata_encode_value (minfo->type, p, &p);
1719 switch (minfo->type) {
1720 case MONO_NATIVE_BYVALTSTR:
1721 case MONO_NATIVE_BYVALARRAY:
1722 mono_metadata_encode_value (minfo->count, p, &p);
1723 break;
1724 case MONO_NATIVE_LPARRAY:
1725 if (minfo->eltype || minfo->has_size) {
1726 mono_metadata_encode_value (minfo->eltype, p, &p);
1727 if (minfo->has_size) {
1728 if (minfo->param_num != -1)
1729 mono_metadata_encode_value (minfo->param_num, p, &p);
1730 else
1731 mono_metadata_encode_value (0, p, &p);
1732 if (minfo->count != -1)
1733 mono_metadata_encode_value (minfo->count, p, &p);
1734 else
1735 mono_metadata_encode_value (0, p, &p);
1737 /* LAMESPEC: ElemMult is undocumented */
1738 if (minfo->param_num != -1)
1739 mono_metadata_encode_value (1, p, &p);
1740 else
1741 mono_metadata_encode_value (0, p, &p);
1744 break;
1745 case MONO_NATIVE_CUSTOM:
1746 if (minfo->guid) {
1747 str = mono_string_to_utf8 (minfo->guid);
1748 len = strlen (str);
1749 mono_metadata_encode_value (len, p, &p);
1750 memcpy (p, str, len);
1751 p += len;
1752 g_free (str);
1753 } else {
1754 mono_metadata_encode_value (0, p, &p);
1756 /* native type name */
1757 mono_metadata_encode_value (0, p, &p);
1758 /* custom marshaler type name */
1759 if (minfo->marshaltype || minfo->marshaltyperef) {
1760 if (minfo->marshaltyperef)
1761 str = type_get_fully_qualified_name (minfo->marshaltyperef->type);
1762 else
1763 str = mono_string_to_utf8 (minfo->marshaltype);
1764 len = strlen (str);
1765 mono_metadata_encode_value (len, p, &p);
1766 if (p + len >= buf + bufsize) {
1767 idx = p - buf;
1768 bufsize *= 2;
1769 buf = g_realloc (buf, bufsize);
1770 p = buf + idx;
1772 memcpy (p, str, len);
1773 p += len;
1774 g_free (str);
1775 } else {
1776 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
1777 mono_metadata_encode_value (0, p, &p);
1779 if (minfo->mcookie) {
1780 str = mono_string_to_utf8 (minfo->mcookie);
1781 len = strlen (str);
1782 mono_metadata_encode_value (len, p, &p);
1783 if (p + len >= buf + bufsize) {
1784 idx = p - buf;
1785 bufsize *= 2;
1786 buf = g_realloc (buf, bufsize);
1787 p = buf + idx;
1789 memcpy (p, str, len);
1790 p += len;
1791 g_free (str);
1792 } else {
1793 mono_metadata_encode_value (0, p, &p);
1795 break;
1796 default:
1797 break;
1799 len = p-buf;
1800 mono_metadata_encode_value (len, b, &b);
1801 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, len);
1802 g_free (buf);
1803 return idx;
1806 static void
1807 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1809 MonoDynamicTable *table;
1810 guint32 *values;
1812 /* maybe this fixup should be done in the C# code */
1813 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1814 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1815 table = &assembly->tables [MONO_TABLE_FIELD];
1816 fb->table_idx = table->next_idx ++;
1817 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1818 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1819 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
1820 values [MONO_FIELD_FLAGS] = fb->attrs;
1821 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1823 if (fb->offset != -1) {
1824 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1825 table->rows ++;
1826 alloc_table (table, table->rows);
1827 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1828 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1829 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1831 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1832 guint32 field_type = 0;
1833 table = &assembly->tables [MONO_TABLE_CONSTANT];
1834 table->rows ++;
1835 alloc_table (table, table->rows);
1836 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1837 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1838 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1839 values [MONO_CONSTANT_TYPE] = field_type;
1840 values [MONO_CONSTANT_PADDING] = 0;
1842 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1843 guint32 rva_idx;
1844 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1845 table->rows ++;
1846 alloc_table (table, table->rows);
1847 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1848 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1850 * We store it in the code section because it's simpler for now.
1852 if (fb->rva_data)
1853 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1854 else
1855 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1856 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1858 if (fb->marshal_info) {
1859 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1860 table->rows ++;
1861 alloc_table (table, table->rows);
1862 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1863 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1864 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1868 static guint32
1869 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1871 char *buf, *p;
1872 char blob_size [6];
1873 char *b = blob_size;
1874 guint32 nparams = 0;
1875 MonoReflectionMethodBuilder *mb = fb->get_method;
1876 MonoReflectionMethodBuilder *smb = fb->set_method;
1877 guint32 idx, i, size;
1879 if (mb && mb->parameters)
1880 nparams = mono_array_length (mb->parameters);
1881 if (!mb && smb && smb->parameters)
1882 nparams = mono_array_length (smb->parameters) - 1;
1883 size = 24 + nparams * 10;
1884 buf = p = g_malloc (size);
1885 *p = 0x08;
1886 p++;
1887 mono_metadata_encode_value (nparams, p, &p);
1888 if (mb) {
1889 encode_reflection_type (assembly, mb->rtype, p, &p);
1890 for (i = 0; i < nparams; ++i) {
1891 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1892 encode_reflection_type (assembly, pt, p, &p);
1894 } else if (smb && smb->parameters) {
1895 /* the property type is the last param */
1896 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), p, &p);
1897 for (i = 0; i < nparams; ++i) {
1898 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1899 encode_reflection_type (assembly, pt, p, &p);
1902 else {
1903 encode_reflection_type (assembly, fb->type, p, &p);
1906 /* store length */
1907 g_assert (p - buf < size);
1908 mono_metadata_encode_value (p-buf, b, &b);
1909 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1910 g_free (buf);
1911 return idx;
1914 static void
1915 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1917 MonoDynamicTable *table;
1918 guint32 *values;
1919 guint num_methods = 0;
1920 guint32 semaidx;
1923 * we need to set things in the following tables:
1924 * PROPERTYMAP (info already filled in _get_type_info ())
1925 * PROPERTY (rows already preallocated in _get_type_info ())
1926 * METHOD (method info already done with the generic method code)
1927 * METHODSEMANTICS
1929 table = &assembly->tables [MONO_TABLE_PROPERTY];
1930 pb->table_idx = table->next_idx ++;
1931 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1932 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1933 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1934 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1936 /* FIXME: we still don't handle 'other' methods */
1937 if (pb->get_method) num_methods ++;
1938 if (pb->set_method) num_methods ++;
1940 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1941 table->rows += num_methods;
1942 alloc_table (table, table->rows);
1944 if (pb->get_method) {
1945 semaidx = table->next_idx ++;
1946 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1947 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1948 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1949 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1951 if (pb->set_method) {
1952 semaidx = table->next_idx ++;
1953 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1954 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1955 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1956 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1960 static void
1961 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1963 MonoDynamicTable *table;
1964 guint32 *values;
1965 guint num_methods = 0;
1966 guint32 semaidx;
1969 * we need to set things in the following tables:
1970 * EVENTMAP (info already filled in _get_type_info ())
1971 * EVENT (rows already preallocated in _get_type_info ())
1972 * METHOD (method info already done with the generic method code)
1973 * METHODSEMANTICS
1975 table = &assembly->tables [MONO_TABLE_EVENT];
1976 eb->table_idx = table->next_idx ++;
1977 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1978 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
1979 values [MONO_EVENT_FLAGS] = eb->attrs;
1980 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1983 * FIXME: we still don't handle 'other' methods
1985 if (eb->add_method) num_methods ++;
1986 if (eb->remove_method) num_methods ++;
1987 if (eb->raise_method) num_methods ++;
1989 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1990 table->rows += num_methods;
1991 alloc_table (table, table->rows);
1993 if (eb->add_method) {
1994 semaidx = table->next_idx ++;
1995 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1996 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
1997 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
1998 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2000 if (eb->remove_method) {
2001 semaidx = table->next_idx ++;
2002 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2003 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2004 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2005 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2007 if (eb->raise_method) {
2008 semaidx = table->next_idx ++;
2009 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2010 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2011 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2012 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2016 static void
2017 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2019 MonoDynamicTable *table;
2020 guint32 num_constraints, i;
2021 guint32 *values;
2022 guint32 table_idx;
2024 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2025 num_constraints = gparam->iface_constraints ?
2026 mono_array_length (gparam->iface_constraints) : 0;
2027 table->rows += num_constraints;
2028 if (gparam->base_type)
2029 table->rows++;
2030 alloc_table (table, table->rows);
2032 if (gparam->base_type) {
2033 table_idx = table->next_idx ++;
2034 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2036 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2037 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2038 assembly, gparam->base_type->type);
2041 for (i = 0; i < num_constraints; i++) {
2042 MonoReflectionType *constraint = mono_array_get (
2043 gparam->iface_constraints, gpointer, i);
2045 table_idx = table->next_idx ++;
2046 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2048 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2049 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2050 assembly, constraint->type);
2054 static void
2055 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2057 GenericParamTableEntry *entry;
2060 * The GenericParam table must be sorted according to the `owner' field.
2061 * We need to do this sorting prior to writing the GenericParamConstraint
2062 * table, since we have to use the final GenericParam table indices there
2063 * and they must also be sorted.
2066 entry = g_new0 (GenericParamTableEntry, 1);
2067 entry->owner = owner;
2068 #ifdef HAVE_SGEN_GC
2069 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2070 MONO_GC_REGISTER_ROOT (entry->gparam);
2071 #endif
2072 entry->gparam = gparam; /* FIXME: GC object stored in unmanaged mem */
2074 g_ptr_array_add (assembly->gen_params, entry);
2077 static void
2078 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2080 MonoDynamicTable *table;
2081 MonoGenericParam *param;
2082 guint32 *values;
2083 guint32 table_idx;
2085 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2086 table_idx = table->next_idx ++;
2087 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2089 param = entry->gparam->type.type->data.generic_param;
2091 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2092 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2093 values [MONO_GENERICPARAM_NUMBER] = param->num;
2094 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
2096 mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2098 encode_constraints (entry->gparam, table_idx, assembly);
2101 static guint32
2102 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2104 MonoDynamicTable *table;
2105 guint32 token;
2106 guint32 *values;
2107 guint32 cols [MONO_ASSEMBLY_SIZE];
2108 const char *pubkey;
2109 guint32 publen;
2111 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2112 return token;
2114 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2115 table = &assembly->tables [MONO_TABLE_MODULEREF];
2116 token = table->next_idx ++;
2117 table->rows ++;
2118 alloc_table (table, table->rows);
2119 values = table->values + token * MONO_MODULEREF_SIZE;
2120 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2122 token <<= MONO_RESOLTION_SCOPE_BITS;
2123 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2124 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2126 return token;
2129 if (image->assembly->dynamic)
2130 /* FIXME: */
2131 memset (cols, 0, sizeof (cols));
2132 else {
2133 /* image->assembly->image is the manifest module */
2134 image = image->assembly->image;
2135 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2138 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2139 token = table->next_idx ++;
2140 table->rows ++;
2141 alloc_table (table, table->rows);
2142 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2143 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2144 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2145 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2146 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2147 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2148 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2149 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2150 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2152 if (strcmp ("", image->assembly->aname.culture)) {
2153 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2154 image->assembly->aname.culture);
2157 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2158 guchar pubtoken [9];
2159 pubtoken [0] = 8;
2160 mono_digest_get_public_token (pubtoken + 1, pubkey, publen);
2161 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, pubtoken, 9);
2162 } else {
2163 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2165 token <<= MONO_RESOLTION_SCOPE_BITS;
2166 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2167 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2168 return token;
2171 static guint32
2172 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2174 MonoDynamicTable *table;
2175 guint32 *values;
2176 guint32 token;
2177 char sig [128];
2178 char *p = sig;
2179 char blob_size [6];
2180 char *b = blob_size;
2182 switch (type->type) {
2183 case MONO_TYPE_FNPTR:
2184 case MONO_TYPE_PTR:
2185 case MONO_TYPE_SZARRAY:
2186 case MONO_TYPE_ARRAY:
2187 case MONO_TYPE_VAR:
2188 case MONO_TYPE_MVAR:
2189 case MONO_TYPE_GENERICINST:
2190 encode_type (assembly, type, p, &p);
2191 break;
2192 case MONO_TYPE_CLASS:
2193 case MONO_TYPE_VALUETYPE: {
2194 MonoClass *k = mono_class_from_mono_type (type);
2195 if (!k || !k->generic_class)
2196 return 0;
2197 encode_generic_class (assembly, k->generic_class, p, &p);
2198 break;
2200 default:
2201 return 0;
2204 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2205 if (assembly->save) {
2206 g_assert (p-sig < 128);
2207 mono_metadata_encode_value (p-sig, b, &b);
2208 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2209 alloc_table (table, table->rows + 1);
2210 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2211 values [MONO_TYPESPEC_SIGNATURE] = token;
2214 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2215 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2216 table->next_idx ++;
2217 return token;
2221 * Despite the name, we handle also TypeSpec (with the above helper).
2223 static guint32
2224 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2226 MonoDynamicTable *table;
2227 guint32 *values;
2228 guint32 token, scope, enclosing;
2229 MonoClass *klass;
2231 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2232 if (token)
2233 return token;
2234 token = create_typespec (assembly, type);
2235 if (token)
2236 return token;
2237 klass = my_mono_class_from_mono_type (type);
2238 if (!klass)
2239 klass = mono_class_from_mono_type (type);
2242 * If it's in the same module and not a generic type parameter:
2244 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2245 (type->type != MONO_TYPE_MVAR)) {
2246 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2247 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2248 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2249 return token;
2252 if (klass->nested_in) {
2253 enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
2254 /* get the typeref idx of the enclosing type */
2255 enclosing >>= MONO_TYPEDEFORREF_BITS;
2256 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2257 } else {
2258 scope = resolution_scope_from_image (assembly, klass->image);
2260 table = &assembly->tables [MONO_TABLE_TYPEREF];
2261 if (assembly->save) {
2262 alloc_table (table, table->rows + 1);
2263 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2264 values [MONO_TYPEREF_SCOPE] = scope;
2265 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2266 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2268 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2269 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2270 table->next_idx ++;
2271 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2272 return token;
2276 * Insert a memberef row into the metadata: the token that point to the memberref
2277 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2278 * mono_image_get_fieldref_token()).
2279 * The sig param is an index to an already built signature.
2281 static guint32
2282 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2284 MonoDynamicTable *table;
2285 guint32 *values;
2286 guint32 token, pclass;
2287 guint32 parent;
2289 parent = mono_image_typedef_or_ref (assembly, type);
2290 switch (parent & MONO_TYPEDEFORREF_MASK) {
2291 case MONO_TYPEDEFORREF_TYPEREF:
2292 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2293 break;
2294 case MONO_TYPEDEFORREF_TYPESPEC:
2295 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2296 break;
2297 case MONO_TYPEDEFORREF_TYPEDEF:
2298 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2299 break;
2300 default:
2301 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2302 return 0;
2304 /* extract the index */
2305 parent >>= MONO_TYPEDEFORREF_BITS;
2307 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2309 if (assembly->save) {
2310 alloc_table (table, table->rows + 1);
2311 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2312 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2313 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2314 values [MONO_MEMBERREF_SIGNATURE] = sig;
2317 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2318 table->next_idx ++;
2320 return token;
2323 static guint32
2324 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method)
2326 guint32 token;
2327 MonoMethodSignature *sig;
2329 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2330 if (token)
2331 return token;
2334 * A methodref signature can't contain an unmanaged calling convention.
2336 sig = mono_metadata_signature_dup (mono_method_signature (method));
2337 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2338 sig->call_convention = MONO_CALL_DEFAULT;
2339 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2340 method->name, method_encode_signature (assembly, sig));
2341 g_free (sig);
2342 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2343 return token;
2346 static guint32
2347 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2348 const gchar *name, guint32 sig)
2350 MonoDynamicTable *table;
2351 guint32 token;
2352 guint32 *values;
2354 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2356 if (assembly->save) {
2357 alloc_table (table, table->rows + 1);
2358 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2359 values [MONO_MEMBERREF_CLASS] = original;
2360 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2361 values [MONO_MEMBERREF_SIGNATURE] = sig;
2364 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2365 table->next_idx ++;
2367 return token;
2370 static guint32
2371 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2373 guint32 token;
2374 ReflectionMethodBuilder rmb;
2376 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2377 if (token)
2378 return token;
2380 reflection_methodbuilder_from_method_builder (&rmb, mb);
2382 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2383 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2384 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2385 return token;
2388 static guint32
2389 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2391 guint32 token;
2392 ReflectionMethodBuilder rmb;
2394 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2395 if (token)
2396 return token;
2398 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2400 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2401 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2402 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2403 return token;
2406 static guint32
2407 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2409 MonoType *type;
2410 guint32 token;
2412 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2413 if (token)
2414 return token;
2415 g_assert (f->field->parent);
2416 type = f->field->generic_info ? f->field->generic_info->generic_type : f->field->type;
2417 token = mono_image_get_memberref_token (assembly, &f->field->parent->byval_arg,
2418 f->field->name, fieldref_encode_signature (assembly, type));
2419 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2420 return token;
2423 static guint32
2424 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericMethod *gmethod)
2426 char *buf;
2427 char *p;
2428 int i;
2429 guint32 nparams = gmethod->inst->type_argc;
2430 guint32 size = 10 + nparams * 30;
2431 guint32 idx;
2432 char blob_size [6];
2433 char *b = blob_size;
2435 if (!assembly->save)
2436 return 0;
2438 p = buf = g_malloc (size);
2440 * FIXME: vararg, explicit_this, differenc call_conv values...
2442 mono_metadata_encode_value (0xa, p, &p); /* FIXME FIXME FIXME */
2443 mono_metadata_encode_value (nparams, p, &p);
2445 for (i = 0; i < nparams; i++)
2446 encode_type (assembly, gmethod->inst->type_argv [i], p, &p);
2448 /* store length */
2449 g_assert (p - buf < size);
2450 mono_metadata_encode_value (p-buf, b, &b);
2451 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2452 g_free (buf);
2453 return idx;
2456 static guint32
2457 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2459 MonoDynamicTable *table;
2460 guint32 *values;
2461 guint32 token, mtoken = 0, sig;
2462 MonoMethodInflated *imethod;
2463 MonoMethod *declaring;
2465 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2467 g_assert (method->is_inflated);
2468 method = mono_get_inflated_method (method);
2469 imethod = (MonoMethodInflated *) method;
2470 declaring = imethod->declaring;
2472 sig = method_encode_signature (assembly, mono_method_signature (declaring));
2473 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2475 if (!mono_method_signature (declaring)->generic_param_count)
2476 return mtoken;
2478 switch (mono_metadata_token_table (mtoken)) {
2479 case MONO_TABLE_MEMBERREF:
2480 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2481 break;
2482 case MONO_TABLE_METHOD:
2483 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2484 break;
2485 default:
2486 g_assert_not_reached ();
2489 sig = encode_generic_method_sig (assembly, imethod->context->gmethod);
2491 if (assembly->save) {
2492 alloc_table (table, table->rows + 1);
2493 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2494 values [MONO_METHODSPEC_METHOD] = mtoken;
2495 values [MONO_METHODSPEC_SIGNATURE] = sig;
2498 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2499 table->next_idx ++;
2501 return token;
2504 static guint32
2505 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
2507 MonoMethodInflated *imethod;
2508 MonoMethod *inflated;
2509 guint32 token;
2511 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2512 if (token)
2513 return token;
2515 g_assert (method->is_inflated);
2516 inflated = mono_get_inflated_method (method);
2517 imethod = (MonoMethodInflated *) inflated;
2519 if (mono_method_signature (imethod->declaring)->generic_param_count) {
2520 token = method_encode_methodspec (assembly, inflated);
2521 } else {
2522 guint32 sig = method_encode_signature (
2523 assembly, mono_method_signature (imethod->declaring));
2524 token = mono_image_get_memberref_token (
2525 assembly, &inflated->klass->byval_arg, inflated->name, sig);
2528 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2529 return token;
2532 static guint32
2533 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
2535 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
2536 guint32 sig, token;
2538 m = mono_get_inflated_method (m);
2540 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
2541 token = mono_image_get_memberref_token (
2542 assembly, &m->klass->byval_arg, m->name, sig);
2544 return token;
2547 static guint32
2548 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2550 MonoDynamicTable *table;
2551 MonoClass *klass;
2552 guint32 *values;
2553 guint32 token;
2554 char sig [128];
2555 char *p = sig;
2556 char blob_size [6];
2557 char *b = blob_size;
2558 int count, i;
2561 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2562 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2563 * Because of this, we must not insert it into the `typeref' hash table.
2566 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2567 if (token)
2568 return token;
2570 g_assert (tb->generic_params);
2571 klass = mono_class_from_mono_type (tb->type.type);
2573 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
2574 encode_type (assembly, &klass->byval_arg, p, &p);
2576 count = mono_array_length (tb->generic_params);
2577 mono_metadata_encode_value (count, p, &p);
2578 for (i = 0; i < count; i++) {
2579 MonoReflectionGenericParam *gparam;
2581 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2583 encode_type (assembly, gparam->type.type, p, &p);
2586 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2587 g_assert (p-sig < 128);
2589 if (assembly->save) {
2590 mono_metadata_encode_value (p-sig, b, &b);
2591 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2592 alloc_table (table, table->rows + 1);
2593 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2594 values [MONO_TYPESPEC_SIGNATURE] = token;
2597 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2598 g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2599 table->next_idx ++;
2600 return token;
2603 static guint32
2604 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2606 MonoDynamicTable *table;
2607 MonoClass *klass;
2608 guint32 *values;
2609 guint32 token, pclass, parent, sig;
2610 gchar *name;
2612 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2613 if (token)
2614 return token;
2616 klass = mono_class_from_mono_type (fb->typeb->type);
2617 name = mono_string_to_utf8 (fb->name);
2619 sig = fieldref_encode_signature (assembly, fb->type->type);
2621 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2622 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
2624 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2625 parent >>= MONO_TYPEDEFORREF_BITS;
2627 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2629 if (assembly->save) {
2630 alloc_table (table, table->rows + 1);
2631 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2632 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2633 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2634 values [MONO_MEMBERREF_SIGNATURE] = sig;
2637 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2638 table->next_idx ++;
2639 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2640 return token;
2643 static guint32
2644 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2646 char *buf;
2647 char *p;
2648 guint32 nargs;
2649 guint32 size;
2650 guint32 i, idx;
2651 char blob_size [6];
2652 char *b = blob_size;
2654 if (!assembly->save)
2655 return 0;
2657 /* FIXME: */
2658 g_assert (helper->type == 2);
2660 if (helper->arguments)
2661 nargs = mono_array_length (helper->arguments);
2662 else
2663 nargs = 0;
2665 size = 10 + (nargs * 10);
2667 p = buf = g_malloc (size);
2669 /* Encode calling convention */
2670 /* Change Any to Standard */
2671 if ((helper->call_conv & 0x03) == 0x03)
2672 helper->call_conv = 0x01;
2673 /* explicit_this implies has_this */
2674 if (helper->call_conv & 0x40)
2675 helper->call_conv &= 0x20;
2677 if (helper->call_conv == 0) { /* Unmanaged */
2678 *p = helper->unmanaged_call_conv - 1;
2679 } else {
2680 /* Managed */
2681 *p = helper->call_conv & 0x60; /* has_this + explicit_this */
2682 if (helper->call_conv & 0x02) /* varargs */
2683 *p += 0x05;
2686 p++;
2687 mono_metadata_encode_value (nargs, p, &p);
2688 encode_reflection_type (assembly, helper->return_type, p, &p);
2689 for (i = 0; i < nargs; ++i) {
2690 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2691 encode_reflection_type (assembly, pt, p, &p);
2693 /* store length */
2694 g_assert (p - buf < size);
2695 mono_metadata_encode_value (p-buf, b, &b);
2696 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2697 g_free (buf);
2699 return idx;
2702 static guint32
2703 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2705 guint32 idx;
2706 MonoDynamicTable *table;
2707 guint32 *values;
2709 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2710 idx = table->next_idx ++;
2711 table->rows ++;
2712 alloc_table (table, table->rows);
2713 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
2715 values [MONO_STAND_ALONE_SIGNATURE] =
2716 mono_reflection_encode_sighelper (assembly, helper);
2718 return idx;
2721 static int
2722 reflection_cc_to_file (int call_conv) {
2723 switch (call_conv & 0x3) {
2724 case 0:
2725 case 1: return MONO_CALL_DEFAULT;
2726 case 2: return MONO_CALL_VARARG;
2727 default:
2728 g_assert_not_reached ();
2730 return 0;
2733 typedef struct {
2734 MonoType *parent;
2735 MonoMethodSignature *sig;
2736 char *name;
2737 guint32 token;
2738 } ArrayMethod;
2740 static guint32
2741 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
2743 guint32 nparams, i;
2744 GList *tmp;
2745 char *name;
2746 MonoMethodSignature *sig;
2747 ArrayMethod *am;
2749 name = mono_string_to_utf8 (m->name);
2750 nparams = mono_array_length (m->parameters);
2751 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
2752 sig->hasthis = 1;
2753 sig->sentinelpos = -1;
2754 sig->call_convention = reflection_cc_to_file (m->call_conv);
2755 sig->param_count = nparams;
2756 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
2757 for (i = 0; i < nparams; ++i) {
2758 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
2759 sig->params [i] = t->type;
2762 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
2763 am = tmp->data;
2764 if (strcmp (name, am->name) == 0 &&
2765 mono_metadata_type_equal (am->parent, m->parent->type) &&
2766 mono_metadata_signature_equal (am->sig, sig)) {
2767 g_free (name);
2768 g_free (sig);
2769 m->table_idx = am->token & 0xffffff;
2770 return am->token;
2773 am = g_new0 (ArrayMethod, 1);
2774 am->name = name;
2775 am->sig = sig;
2776 am->parent = m->parent->type;
2777 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
2778 method_encode_signature (assembly, sig));
2779 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
2780 m->table_idx = am->token & 0xffffff;
2781 return am->token;
2785 * Insert into the metadata tables all the info about the TypeBuilder tb.
2786 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2788 static void
2789 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
2791 MonoDynamicTable *table;
2792 guint *values;
2793 int i, is_object = 0, is_system = 0;
2794 char *n;
2796 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2797 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2798 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2799 n = mono_string_to_utf8 (tb->name);
2800 if (strcmp (n, "Object") == 0)
2801 is_object++;
2802 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2803 g_free (n);
2804 n = mono_string_to_utf8 (tb->nspace);
2805 if (strcmp (n, "System") == 0)
2806 is_system++;
2807 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2808 g_free (n);
2809 if (tb->parent && !(is_system && is_object) &&
2810 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
2811 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
2812 } else {
2813 values [MONO_TYPEDEF_EXTENDS] = 0;
2815 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
2816 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
2819 * if we have explicitlayout or sequentiallayouts, output data in the
2820 * ClassLayout table.
2822 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
2823 ((tb->class_size > 0) || (tb->packing_size > 0))) {
2824 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2825 table->rows++;
2826 alloc_table (table, table->rows);
2827 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2828 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2829 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2830 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2833 /* handle interfaces */
2834 if (tb->interfaces) {
2835 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2836 i = table->rows;
2837 table->rows += mono_array_length (tb->interfaces);
2838 alloc_table (table, table->rows);
2839 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2840 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2841 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2842 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2843 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
2844 values += MONO_INTERFACEIMPL_SIZE;
2848 /* handle fields */
2849 if (tb->fields) {
2850 table = &assembly->tables [MONO_TABLE_FIELD];
2851 table->rows += tb->num_fields;
2852 alloc_table (table, table->rows);
2853 for (i = 0; i < tb->num_fields; ++i)
2854 mono_image_get_field_info (
2855 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
2858 /* handle constructors */
2859 if (tb->ctors) {
2860 table = &assembly->tables [MONO_TABLE_METHOD];
2861 table->rows += mono_array_length (tb->ctors);
2862 alloc_table (table, table->rows);
2863 for (i = 0; i < mono_array_length (tb->ctors); ++i)
2864 mono_image_get_ctor_info (domain,
2865 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
2868 /* handle methods */
2869 if (tb->methods) {
2870 table = &assembly->tables [MONO_TABLE_METHOD];
2871 table->rows += tb->num_methods;
2872 alloc_table (table, table->rows);
2873 for (i = 0; i < tb->num_methods; ++i)
2874 mono_image_get_method_info (
2875 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
2878 /* Do the same with properties etc.. */
2879 if (tb->events && mono_array_length (tb->events)) {
2880 table = &assembly->tables [MONO_TABLE_EVENT];
2881 table->rows += mono_array_length (tb->events);
2882 alloc_table (table, table->rows);
2883 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2884 table->rows ++;
2885 alloc_table (table, table->rows);
2886 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2887 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2888 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2889 for (i = 0; i < mono_array_length (tb->events); ++i)
2890 mono_image_get_event_info (
2891 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
2893 if (tb->properties && mono_array_length (tb->properties)) {
2894 table = &assembly->tables [MONO_TABLE_PROPERTY];
2895 table->rows += mono_array_length (tb->properties);
2896 alloc_table (table, table->rows);
2897 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2898 table->rows ++;
2899 alloc_table (table, table->rows);
2900 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2901 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2902 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2903 for (i = 0; i < mono_array_length (tb->properties); ++i)
2904 mono_image_get_property_info (
2905 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
2908 /* handle generic parameters */
2909 if (tb->generic_params) {
2910 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2911 table->rows += mono_array_length (tb->generic_params);
2912 alloc_table (table, table->rows);
2913 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
2914 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
2916 mono_image_get_generic_param_info (
2917 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
2921 mono_image_add_decl_security (assembly,
2922 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
2924 if (tb->subtypes) {
2925 MonoDynamicTable *ntable;
2927 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2928 ntable->rows += mono_array_length (tb->subtypes);
2929 alloc_table (ntable, ntable->rows);
2930 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2932 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2933 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2935 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2936 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2937 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2938 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2939 mono_string_to_utf8 (tb->name), tb->table_idx,
2940 ntable->next_idx, ntable->rows);*/
2941 values += MONO_NESTED_CLASS_SIZE;
2942 ntable->next_idx++;
2947 static void
2948 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
2950 int i;
2952 g_ptr_array_add (types, type); /* FIXME: GC object added to unmanaged memory */
2954 if (!type->subtypes)
2955 return;
2957 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
2958 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
2959 collect_types (types, subtype);
2963 static gint
2964 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
2966 if ((*type1)->table_idx < (*type2)->table_idx)
2967 return -1;
2968 else
2969 if ((*type1)->table_idx > (*type2)->table_idx)
2970 return 1;
2971 else
2972 return 0;
2975 static void
2976 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
2977 int i;
2979 if (!pinfo)
2980 return;
2981 for (i = 0; i < mono_array_length (pinfo); ++i) {
2982 MonoReflectionParamBuilder *pb;
2983 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
2984 if (!pb)
2985 continue;
2986 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
2990 static void
2991 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
2992 int i;
2994 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
2995 if (tb->fields) {
2996 for (i = 0; i < tb->num_fields; ++i) {
2997 MonoReflectionFieldBuilder* fb;
2998 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
2999 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3002 if (tb->events) {
3003 for (i = 0; i < mono_array_length (tb->events); ++i) {
3004 MonoReflectionEventBuilder* eb;
3005 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3006 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3009 if (tb->properties) {
3010 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3011 MonoReflectionPropertyBuilder* pb;
3012 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3013 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3016 if (tb->ctors) {
3017 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3018 MonoReflectionCtorBuilder* cb;
3019 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3020 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3021 params_add_cattrs (assembly, cb->pinfo);
3025 if (tb->methods) {
3026 for (i = 0; i < tb->num_methods; ++i) {
3027 MonoReflectionMethodBuilder* mb;
3028 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3029 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3030 params_add_cattrs (assembly, mb->pinfo);
3034 if (tb->subtypes) {
3035 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3036 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3040 static void
3041 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3043 int i;
3045 mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3047 if (moduleb->global_methods) {
3048 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3049 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3050 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3051 params_add_cattrs (assembly, mb->pinfo);
3055 if (moduleb->global_fields) {
3056 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3057 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3058 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3062 if (moduleb->types) {
3063 for (i = 0; i < moduleb->num_types; ++i)
3064 type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3068 static void
3069 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3071 MonoDynamicTable *table;
3072 guint32 *values;
3073 char blob_size [6];
3074 guchar hash [20];
3075 char *b = blob_size;
3076 char *dir, *path;
3078 table = &assembly->tables [MONO_TABLE_FILE];
3079 table->rows++;
3080 alloc_table (table, table->rows);
3081 values = table->values + table->next_idx * MONO_FILE_SIZE;
3082 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3083 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3084 if (module->image->dynamic) {
3085 /* This depends on the fact that the main module is emitted last */
3086 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3087 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3088 } else {
3089 dir = NULL;
3090 path = g_strdup (module->image->name);
3092 mono_sha1_get_digest_from_file (path, hash);
3093 g_free (dir);
3094 g_free (path);
3095 mono_metadata_encode_value (20, b, &b);
3096 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3097 mono_image_add_stream_data (&assembly->blob, hash, 20);
3098 table->next_idx ++;
3101 static void
3102 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3104 MonoDynamicTable *table;
3105 int i;
3107 table = &assembly->tables [MONO_TABLE_MODULE];
3108 mb->table_idx = table->next_idx ++;
3109 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3110 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3111 i /= 16;
3112 ++i;
3113 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3114 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3115 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3116 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3119 static guint32
3120 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3121 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3123 MonoDynamicTable *table;
3124 guint32 *values;
3125 guint32 visib, res;
3127 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3128 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3129 return 0;
3131 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3132 table->rows++;
3133 alloc_table (table, table->rows);
3134 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3136 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3137 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3138 if (klass->nested_in)
3139 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3140 else
3141 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3142 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3143 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3145 res = table->next_idx;
3147 table->next_idx ++;
3149 /* Emit nested types */
3150 if (klass->nested_classes) {
3151 GList *tmp;
3153 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
3154 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3157 return res;
3160 static void
3161 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3162 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3164 MonoClass *klass;
3165 guint32 idx, i;
3167 klass = mono_class_from_mono_type (tb->type.type);
3169 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3171 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3172 parent_index, assembly);
3175 * Emit nested types
3176 * We need to do this ourselves since klass->nested_classes is not set up.
3178 if (tb->subtypes) {
3179 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3180 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3184 static void
3185 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3186 guint32 module_index, MonoDynamicImage *assembly)
3188 MonoImage *image = module->image;
3189 MonoTableInfo *t;
3190 guint32 i;
3192 t = &image->tables [MONO_TABLE_TYPEDEF];
3194 for (i = 0; i < t->rows; ++i) {
3195 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3197 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3198 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3202 static void
3203 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3205 MonoDynamicTable *table;
3206 MonoClass *klass;
3207 guint32 *values;
3208 guint32 scope, idx;
3209 int i;
3211 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3213 if (assemblyb->type_forwarders) {
3214 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3215 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType*, i);
3216 if (!t)
3217 continue;
3219 g_assert (t->type);
3221 klass = mono_class_from_mono_type (t->type);
3223 scope = resolution_scope_from_image (assembly, klass->image);
3224 g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3225 idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3227 table->rows++;
3228 alloc_table (table, table->rows);
3229 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3231 values [MONO_EXP_TYPE_FLAGS] = TYPE_ATTRIBUTE_FORWARDER;
3232 values [MONO_EXP_TYPE_TYPEDEF] = 0;
3233 values [MONO_EXP_TYPE_IMPLEMENTATION] = (idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3234 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3235 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3240 #define align_pointer(base,p)\
3241 do {\
3242 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3243 if (__diff & 3)\
3244 (p) += 4 - (__diff & 3);\
3245 } while (0)
3247 static int
3248 compare_constants (const void *a, const void *b)
3250 const guint32 *a_values = a;
3251 const guint32 *b_values = b;
3252 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3255 static int
3256 compare_semantics (const void *a, const void *b)
3258 const guint32 *a_values = a;
3259 const guint32 *b_values = b;
3260 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3261 if (assoc)
3262 return assoc;
3263 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3266 static int
3267 compare_custom_attrs (const void *a, const void *b)
3269 const guint32 *a_values = a;
3270 const guint32 *b_values = b;
3272 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3275 static int
3276 compare_field_marshal (const void *a, const void *b)
3278 const guint32 *a_values = a;
3279 const guint32 *b_values = b;
3281 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3284 static int
3285 compare_nested (const void *a, const void *b)
3287 const guint32 *a_values = a;
3288 const guint32 *b_values = b;
3290 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3293 static int
3294 compare_genericparam (const void *a, const void *b)
3296 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3297 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3299 if ((*b_entry)->owner == (*a_entry)->owner)
3300 return
3301 (*a_entry)->gparam->type.type->data.generic_param->num -
3302 (*b_entry)->gparam->type.type->data.generic_param->num;
3303 else
3304 return (*a_entry)->owner - (*b_entry)->owner;
3307 static int
3308 compare_declsecurity_attrs (const void *a, const void *b)
3310 const guint32 *a_values = a;
3311 const guint32 *b_values = b;
3313 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3316 static void
3317 pad_heap (MonoDynamicStream *sh)
3319 if (sh->index & 3) {
3320 int sz = 4 - (sh->index & 3);
3321 memset (sh->data + sh->index, 0, sz);
3322 sh->index += sz;
3326 struct StreamDesc {
3327 const char *name;
3328 MonoDynamicStream *stream;
3332 * build_compressed_metadata() fills in the blob of data that represents the
3333 * raw metadata as it will be saved in the PE file. The five streams are output
3334 * and the metadata tables are comnpressed from the guint32 array representation,
3335 * to the compressed on-disk format.
3337 static void
3338 build_compressed_metadata (MonoDynamicImage *assembly)
3340 MonoDynamicTable *table;
3341 int i;
3342 guint64 valid_mask = 0;
3343 guint64 sorted_mask;
3344 guint32 heapt_size = 0;
3345 guint32 meta_size = 256; /* allow for header and other stuff */
3346 guint32 table_offset;
3347 guint32 ntables = 0;
3348 guint64 *int64val;
3349 guint32 *int32val;
3350 guint16 *int16val;
3351 MonoImage *meta;
3352 unsigned char *p;
3353 struct StreamDesc stream_desc [5];
3355 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3356 for (i = 0; i < assembly->gen_params->len; i++){
3357 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3358 write_generic_param_entry (assembly, entry);
3361 stream_desc [0].name = "#~";
3362 stream_desc [0].stream = &assembly->tstream;
3363 stream_desc [1].name = "#Strings";
3364 stream_desc [1].stream = &assembly->sheap;
3365 stream_desc [2].name = "#US";
3366 stream_desc [2].stream = &assembly->us;
3367 stream_desc [3].name = "#Blob";
3368 stream_desc [3].stream = &assembly->blob;
3369 stream_desc [4].name = "#GUID";
3370 stream_desc [4].stream = &assembly->guid;
3372 /* tables that are sorted */
3373 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3374 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3375 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3376 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3377 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3378 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM);
3380 /* Compute table sizes */
3381 /* the MonoImage has already been created in mono_image_basic_init() */
3382 meta = &assembly->image;
3384 /* sizes should be multiple of 4 */
3385 pad_heap (&assembly->blob);
3386 pad_heap (&assembly->guid);
3387 pad_heap (&assembly->sheap);
3388 pad_heap (&assembly->us);
3390 /* Setup the info used by compute_sizes () */
3391 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3392 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3393 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3395 meta_size += assembly->blob.index;
3396 meta_size += assembly->guid.index;
3397 meta_size += assembly->sheap.index;
3398 meta_size += assembly->us.index;
3400 for (i=0; i < MONO_TABLE_NUM; ++i)
3401 meta->tables [i].rows = assembly->tables [i].rows;
3403 for (i = 0; i < MONO_TABLE_NUM; i++){
3404 if (meta->tables [i].rows == 0)
3405 continue;
3406 valid_mask |= (guint64)1 << i;
3407 ntables ++;
3408 meta->tables [i].row_size = mono_metadata_compute_size (
3409 meta, i, &meta->tables [i].size_bitfield);
3410 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3412 heapt_size += 24; /* #~ header size */
3413 heapt_size += ntables * 4;
3414 /* make multiple of 4 */
3415 heapt_size += 3;
3416 heapt_size &= ~3;
3417 meta_size += heapt_size;
3418 meta->raw_metadata = g_malloc0 (meta_size);
3419 p = meta->raw_metadata;
3420 /* the metadata signature */
3421 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3422 /* version numbers and 4 bytes reserved */
3423 int16val = (guint16*)p;
3424 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
3425 *int16val = GUINT16_TO_LE (meta->md_version_minor);
3426 p += 8;
3427 /* version string */
3428 int32val = (guint32*)p;
3429 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3430 p += 4;
3431 memcpy (p, meta->version, strlen (meta->version));
3432 p += GUINT32_FROM_LE (*int32val);
3433 align_pointer (meta->raw_metadata, p);
3434 int16val = (guint16*)p;
3435 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3436 *int16val = GUINT16_TO_LE (5); /* number of streams */
3437 p += 4;
3440 * write the stream info.
3442 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3443 table_offset += 3; table_offset &= ~3;
3445 assembly->tstream.index = heapt_size;
3446 for (i = 0; i < 5; ++i) {
3447 int32val = (guint32*)p;
3448 stream_desc [i].stream->offset = table_offset;
3449 *int32val++ = GUINT32_TO_LE (table_offset);
3450 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3451 table_offset += GUINT32_FROM_LE (*int32val);
3452 table_offset += 3; table_offset &= ~3;
3453 p += 8;
3454 strcpy (p, stream_desc [i].name);
3455 p += strlen (stream_desc [i].name) + 1;
3456 align_pointer (meta->raw_metadata, p);
3459 * now copy the data, the table stream header and contents goes first.
3461 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3462 p = meta->raw_metadata + assembly->tstream.offset;
3463 int32val = (guint32*)p;
3464 *int32val = GUINT32_TO_LE (0); /* reserved */
3465 p += 4;
3467 if ((assembly->tables [MONO_TABLE_GENERICPARAM].rows > 0) ||
3468 (assembly->tables [MONO_TABLE_METHODSPEC].rows > 0) ||
3469 (assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT].rows > 0)) {
3470 *p++ = 2; /* version */
3471 *p++ = 0;
3472 } else {
3473 *p++ = 1; /* version */
3474 *p++ = 0;
3477 if (meta->idx_string_wide)
3478 *p |= 0x01;
3479 if (meta->idx_guid_wide)
3480 *p |= 0x02;
3481 if (meta->idx_blob_wide)
3482 *p |= 0x04;
3483 ++p;
3484 *p++ = 1; /* reserved */
3485 int64val = (guint64*)p;
3486 *int64val++ = GUINT64_TO_LE (valid_mask);
3487 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3488 p += 16;
3489 int32val = (guint32*)p;
3490 for (i = 0; i < MONO_TABLE_NUM; i++){
3491 if (meta->tables [i].rows == 0)
3492 continue;
3493 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3495 p = (unsigned char*)int32val;
3497 /* sort the tables that still need sorting */
3498 table = &assembly->tables [MONO_TABLE_CONSTANT];
3499 if (table->rows)
3500 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
3501 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3502 if (table->rows)
3503 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3504 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3505 if (table->rows)
3506 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3507 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3508 if (table->rows)
3509 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3510 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3511 if (table->rows)
3512 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3513 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3514 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
3515 if (table->rows)
3516 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
3518 /* compress the tables */
3519 for (i = 0; i < MONO_TABLE_NUM; i++){
3520 int row, col;
3521 guint32 *values;
3522 guint32 bitfield = meta->tables [i].size_bitfield;
3523 if (!meta->tables [i].rows)
3524 continue;
3525 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3526 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3527 meta->tables [i].base = p;
3528 for (row = 1; row <= meta->tables [i].rows; ++row) {
3529 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3530 for (col = 0; col < assembly->tables [i].columns; ++col) {
3531 switch (mono_metadata_table_size (bitfield, col)) {
3532 case 1:
3533 *p++ = values [col];
3534 break;
3535 case 2:
3536 *p++ = values [col] & 0xff;
3537 *p++ = (values [col] >> 8) & 0xff;
3538 break;
3539 case 4:
3540 *p++ = values [col] & 0xff;
3541 *p++ = (values [col] >> 8) & 0xff;
3542 *p++ = (values [col] >> 16) & 0xff;
3543 *p++ = (values [col] >> 24) & 0xff;
3544 break;
3545 default:
3546 g_assert_not_reached ();
3550 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3553 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3554 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3555 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3556 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3557 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3559 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3563 * Some tables in metadata need to be sorted according to some criteria, but
3564 * when methods and fields are first created with reflection, they may be assigned a token
3565 * that doesn't correspond to the final token they will get assigned after the sorting.
3566 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3567 * with the reflection objects that represent them. Once all the tables are set up, the
3568 * reflection objects will contains the correct table index. fixup_method() will fixup the
3569 * tokens for the method with ILGenerator @ilgen.
3571 static void
3572 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly) {
3573 guint32 code_idx = GPOINTER_TO_UINT (value);
3574 MonoReflectionILTokenInfo *iltoken;
3575 MonoReflectionFieldBuilder *field;
3576 MonoReflectionCtorBuilder *ctor;
3577 MonoReflectionMethodBuilder *method;
3578 MonoReflectionTypeBuilder *tb;
3579 MonoReflectionArrayMethod *am;
3580 guint32 i, idx = 0;
3581 unsigned char *target;
3583 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3584 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3585 target = assembly->code.data + code_idx + iltoken->code_pos;
3586 switch (target [3]) {
3587 case MONO_TABLE_FIELD:
3588 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3589 field = (MonoReflectionFieldBuilder *)iltoken->member;
3590 idx = field->table_idx;
3591 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3592 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3593 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
3594 } else {
3595 g_assert_not_reached ();
3597 break;
3598 case MONO_TABLE_METHOD:
3599 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3600 method = (MonoReflectionMethodBuilder *)iltoken->member;
3601 idx = method->table_idx;
3602 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3603 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3604 idx = ctor->table_idx;
3605 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3606 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3607 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3608 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3609 } else {
3610 g_assert_not_reached ();
3612 break;
3613 case MONO_TABLE_TYPEDEF:
3614 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3615 g_assert_not_reached ();
3616 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3617 idx = tb->table_idx;
3618 break;
3619 case MONO_TABLE_MEMBERREF:
3620 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3621 am = (MonoReflectionArrayMethod*)iltoken->member;
3622 idx = am->table_idx;
3623 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3624 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
3625 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
3626 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
3627 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3628 g_assert (m->klass->generic_class || m->klass->generic_container);
3629 continue;
3630 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3631 continue;
3632 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3633 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3634 g_assert (f->generic_info);
3635 continue;
3636 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3637 continue;
3638 } else {
3639 g_assert_not_reached ();
3641 break;
3642 case MONO_TABLE_METHODSPEC:
3643 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
3644 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3645 g_assert (mono_method_signature (m)->generic_param_count);
3646 continue;
3647 } else {
3648 g_assert_not_reached ();
3650 break;
3651 default:
3652 g_error ("got unexpected table 0x%02x in fixup", target [3]);
3654 target [0] = idx & 0xff;
3655 target [1] = (idx >> 8) & 0xff;
3656 target [2] = (idx >> 16) & 0xff;
3661 * fixup_cattrs:
3663 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3664 * value is not known when the table is emitted.
3666 static void
3667 fixup_cattrs (MonoDynamicImage *assembly)
3669 MonoDynamicTable *table;
3670 guint32 *values;
3671 guint32 type, i, idx, token;
3672 MonoObject *ctor;
3674 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3676 for (i = 0; i < table->rows; ++i) {
3677 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3679 type = values [MONO_CUSTOM_ATTR_TYPE];
3680 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
3681 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
3682 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3683 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3684 g_assert (ctor);
3686 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3687 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3688 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3689 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
3695 static void
3696 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3698 MonoDynamicTable *table;
3699 guint32 *values;
3701 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3702 table->rows++;
3703 alloc_table (table, table->rows);
3704 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3705 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3706 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3707 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
3708 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3709 table->next_idx++;
3712 static void
3713 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3715 MonoDynamicTable *table;
3716 guint32 *values;
3717 char blob_size [6];
3718 guchar hash [20];
3719 char *b = blob_size;
3720 char *name, *sname;
3721 guint32 idx, offset;
3723 if (rsrc->filename) {
3724 name = mono_string_to_utf8 (rsrc->filename);
3725 sname = g_path_get_basename (name);
3727 table = &assembly->tables [MONO_TABLE_FILE];
3728 table->rows++;
3729 alloc_table (table, table->rows);
3730 values = table->values + table->next_idx * MONO_FILE_SIZE;
3731 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3732 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3733 g_free (sname);
3735 mono_sha1_get_digest_from_file (name, hash);
3736 mono_metadata_encode_value (20, b, &b);
3737 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3738 mono_image_add_stream_data (&assembly->blob, hash, 20);
3739 g_free (name);
3740 idx = table->next_idx++;
3741 rsrc->offset = 0;
3742 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
3743 } else {
3744 char sizebuf [4];
3745 char *data;
3746 guint len;
3747 if (rsrc->data) {
3748 data = mono_array_addr (rsrc->data, char, 0);
3749 len = mono_array_length (rsrc->data);
3750 } else {
3751 data = NULL;
3752 len = 0;
3754 offset = len;
3755 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3756 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3757 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3758 mono_image_add_stream_data (&assembly->resources, data, len);
3760 if (!mb->is_main)
3762 * The entry should be emitted into the MANIFESTRESOURCE table of
3763 * the main module, but that needs to reference the FILE table
3764 * which isn't emitted yet.
3766 return;
3767 else
3768 idx = 0;
3771 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3774 static void
3775 set_version_from_string (MonoString *version, guint32 *values)
3777 gchar *ver, *p, *str;
3778 guint32 i;
3780 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3781 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3782 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3783 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3784 if (!version)
3785 return;
3786 ver = str = mono_string_to_utf8 (version);
3787 for (i = 0; i < 4; ++i) {
3788 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3789 switch (*p) {
3790 case '.':
3791 p++;
3792 break;
3793 case '*':
3794 /* handle Revision and Build */
3795 p++;
3796 break;
3798 ver = p;
3800 g_free (str);
3803 static guint32
3804 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3805 gsize len;
3806 guint32 token = 0;
3807 char blob_size [6];
3808 char *b = blob_size;
3810 if (!pkey)
3811 return token;
3813 len = mono_array_length (pkey);
3814 mono_metadata_encode_value (len, b, &b);
3815 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3816 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, guint8, 0), len);
3818 /* Special case: check for ECMA key (16 bytes) */
3819 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, guint8, 0), len)) {
3820 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
3821 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
3822 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
3823 /* minimum key size (in 2.0) is 384 bits */
3824 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
3825 } else {
3826 /* FIXME - verifier */
3827 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
3828 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
3830 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3832 return token;
3835 static void
3836 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
3838 MonoDynamicTable *table;
3839 MonoDynamicImage *assembly;
3840 MonoReflectionAssemblyBuilder *assemblyb;
3841 MonoDomain *domain;
3842 guint32 *values;
3843 int i;
3844 guint32 module_index;
3846 assemblyb = moduleb->assemblyb;
3847 assembly = moduleb->dynamic_image;
3848 domain = mono_object_domain (assemblyb);
3850 /* Emit ASSEMBLY table */
3851 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3852 alloc_table (table, 1);
3853 values = table->values + MONO_ASSEMBLY_SIZE;
3854 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3855 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
3856 if (assemblyb->culture) {
3857 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
3858 } else {
3859 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3861 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3862 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3863 set_version_from_string (assemblyb->version, values);
3865 /* Emit FILE + EXPORTED_TYPE table */
3866 module_index = 0;
3867 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3868 int j;
3869 MonoReflectionModuleBuilder *file_module =
3870 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3871 if (file_module != moduleb) {
3872 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
3873 module_index ++;
3874 if (file_module->types) {
3875 for (j = 0; j < file_module->num_types; ++j) {
3876 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3877 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
3882 if (assemblyb->loaded_modules) {
3883 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
3884 MonoReflectionModule *file_module =
3885 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
3886 mono_image_fill_file_table (domain, file_module, assembly);
3887 module_index ++;
3888 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
3891 if (assemblyb->type_forwarders)
3892 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
3894 /* Emit MANIFESTRESOURCE table */
3895 module_index = 0;
3896 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3897 int j;
3898 MonoReflectionModuleBuilder *file_module =
3899 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3900 /* The table for the main module is emitted later */
3901 if (file_module != moduleb) {
3902 module_index ++;
3903 if (file_module->resources) {
3904 int len = mono_array_length (file_module->resources);
3905 for (j = 0; j < len; ++j) {
3906 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
3907 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
3915 * mono_image_build_metadata() will fill the info in all the needed metadata tables
3916 * for the modulebuilder @moduleb.
3917 * At the end of the process, method and field tokens are fixed up and the
3918 * on-disk compressed metadata representation is created.
3920 void
3921 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
3923 MonoDynamicTable *table;
3924 MonoDynamicImage *assembly;
3925 MonoReflectionAssemblyBuilder *assemblyb;
3926 MonoDomain *domain;
3927 GPtrArray *types;
3928 guint32 *values;
3929 int i, j;
3931 assemblyb = moduleb->assemblyb;
3932 assembly = moduleb->dynamic_image;
3933 domain = mono_object_domain (assemblyb);
3935 if (assembly->text_rva)
3936 return;
3938 assembly->text_rva = START_TEXT_RVA;
3940 if (moduleb->is_main) {
3941 mono_image_emit_manifest (moduleb);
3944 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3945 table->rows = 1; /* .<Module> */
3946 table->next_idx++;
3947 alloc_table (table, table->rows);
3949 * Set the first entry.
3951 values = table->values + table->columns;
3952 values [MONO_TYPEDEF_FLAGS] = 0;
3953 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
3954 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
3955 values [MONO_TYPEDEF_EXTENDS] = 0;
3956 values [MONO_TYPEDEF_FIELD_LIST] = 1;
3957 values [MONO_TYPEDEF_METHOD_LIST] = 1;
3960 * handle global methods
3961 * FIXME: test what to do when global methods are defined in multiple modules.
3963 if (moduleb->global_methods) {
3964 table = &assembly->tables [MONO_TABLE_METHOD];
3965 table->rows += mono_array_length (moduleb->global_methods);
3966 alloc_table (table, table->rows);
3967 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
3968 mono_image_get_method_info (
3969 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
3971 if (moduleb->global_fields) {
3972 table = &assembly->tables [MONO_TABLE_FIELD];
3973 table->rows += mono_array_length (moduleb->global_fields);
3974 alloc_table (table, table->rows);
3975 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
3976 mono_image_get_field_info (
3977 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
3980 table = &assembly->tables [MONO_TABLE_MODULE];
3981 alloc_table (table, 1);
3982 mono_image_fill_module_table (domain, moduleb, assembly);
3984 /* Collect all types into a list sorted by their table_idx */
3985 types = g_ptr_array_new ();
3987 if (moduleb->types)
3988 for (i = 0; i < moduleb->num_types; ++i) {
3989 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
3990 collect_types (types, type);
3993 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
3994 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3995 table->rows += types->len;
3996 alloc_table (table, table->rows);
3999 * Emit type names + namespaces at one place inside the string heap,
4000 * so load_class_names () needs to touch fewer pages.
4002 for (i = 0; i < types->len; ++i) {
4003 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4004 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4006 for (i = 0; i < types->len; ++i) {
4007 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4008 string_heap_insert_mstring (&assembly->sheap, tb->name);
4011 for (i = 0; i < types->len; ++i) {
4012 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4013 mono_image_get_type_info (domain, type, assembly);
4017 * table->rows is already set above and in mono_image_fill_module_table.
4019 /* add all the custom attributes at the end, once all the indexes are stable */
4020 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4022 /* CAS assembly permissions */
4023 if (assemblyb->permissions_minimum)
4024 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4025 if (assemblyb->permissions_optional)
4026 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4027 if (assemblyb->permissions_refused)
4028 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4030 module_add_cattrs (assembly, moduleb);
4032 /* fixup tokens */
4033 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4035 /* Create the MethodImpl table. We do this after emitting all methods so we already know
4036 * the final tokens and don't need another fixup pass. */
4038 if (moduleb->global_methods) {
4039 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4040 MonoReflectionMethodBuilder *mb = mono_array_get (
4041 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4042 mono_image_add_methodimpl (assembly, mb);
4046 for (i = 0; i < types->len; ++i) {
4047 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4048 if (type->methods) {
4049 for (j = 0; j < type->num_methods; ++j) {
4050 MonoReflectionMethodBuilder *mb = mono_array_get (
4051 type->methods, MonoReflectionMethodBuilder*, j);
4053 mono_image_add_methodimpl (assembly, mb);
4058 g_ptr_array_free (types, TRUE);
4060 fixup_cattrs (assembly);
4064 * mono_image_insert_string:
4065 * @module: module builder object
4066 * @str: a string
4068 * Insert @str into the user string stream of @module.
4070 guint32
4071 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4073 MonoDynamicImage *assembly;
4074 guint32 idx;
4075 char buf [16];
4076 char *b = buf;
4078 MONO_ARCH_SAVE_REGS;
4080 if (!module->dynamic_image)
4081 mono_image_module_basic_init (module);
4083 assembly = module->dynamic_image;
4085 if (assembly->save) {
4086 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4087 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4088 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4090 char *swapped = g_malloc (2 * mono_string_length (str));
4091 const char *p = (const char*)mono_string_chars (str);
4093 swap_with_size (swapped, p, 2, mono_string_length (str));
4094 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4095 g_free (swapped);
4097 #else
4098 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4099 #endif
4100 mono_image_add_stream_data (&assembly->us, "", 1);
4101 } else {
4102 idx = assembly->us.index ++;
4105 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4107 return MONO_TOKEN_STRING | idx;
4110 guint32
4111 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4113 MonoClass *klass;
4114 guint32 token = 0;
4116 klass = obj->vtable->klass;
4117 if (strcmp (klass->name, "MonoMethod") == 0) {
4118 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4119 MonoMethodSignature *sig, *old;
4120 guint32 sig_token, parent;
4121 int nargs, i;
4123 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4125 nargs = mono_array_length (opt_param_types);
4126 old = mono_method_signature (method);
4127 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4129 sig->hasthis = old->hasthis;
4130 sig->explicit_this = old->explicit_this;
4131 sig->call_convention = old->call_convention;
4132 sig->generic_param_count = old->generic_param_count;
4133 sig->param_count = old->param_count + nargs;
4134 sig->sentinelpos = old->param_count;
4135 sig->ret = old->ret;
4137 for (i = 0; i < old->param_count; i++)
4138 sig->params [i] = old->params [i];
4140 for (i = 0; i < nargs; i++) {
4141 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4142 sig->params [old->param_count + i] = rt->type;
4145 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4146 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4147 parent >>= MONO_TYPEDEFORREF_BITS;
4149 parent <<= MONO_MEMBERREF_PARENT_BITS;
4150 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4152 sig_token = method_encode_signature (assembly, sig);
4153 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4154 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4155 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4156 ReflectionMethodBuilder rmb;
4157 guint32 parent, sig;
4159 reflection_methodbuilder_from_method_builder (&rmb, mb);
4160 rmb.opt_types = opt_param_types;
4162 sig = method_builder_encode_signature (assembly, &rmb);
4164 parent = mono_image_create_token (assembly, obj, TRUE);
4165 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4167 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4168 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4170 token = mono_image_get_varargs_method_token (
4171 assembly, parent, mono_string_to_utf8 (rmb.name), sig);
4172 } else {
4173 g_error ("requested method token for %s\n", klass->name);
4176 return token;
4180 * mono_image_create_token:
4181 * @assembly: a dynamic assembly
4182 * @obj:
4184 * Get a token to insert in the IL code stream for the given MemberInfo.
4185 * @obj can be one of:
4186 * ConstructorBuilder
4187 * MethodBuilder
4188 * FieldBuilder
4189 * MonoCMethod
4190 * MonoMethod
4191 * MonoField
4192 * MonoType
4193 * TypeBuilder
4195 guint32
4196 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, gboolean create_methodspec)
4198 MonoClass *klass;
4199 guint32 token = 0;
4201 klass = obj->vtable->klass;
4202 if (strcmp (klass->name, "MethodBuilder") == 0) {
4203 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4205 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4206 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4207 else
4208 token = mono_image_get_methodbuilder_token (assembly, mb);
4209 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4210 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4211 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4213 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4214 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4215 else
4216 token = mono_image_get_ctorbuilder_token (assembly, mb);
4217 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4218 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4219 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4220 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4221 if (tb->generic_params) {
4222 token = mono_image_get_generic_field_token (assembly, fb);
4223 } else {
4224 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4226 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4227 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4228 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4229 } else if (strcmp (klass->name, "MonoType") == 0 ||
4230 strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4231 MonoReflectionType *tb = (MonoReflectionType *)obj;
4232 token = mono_metadata_token_from_dor (
4233 mono_image_typedef_or_ref (assembly, tb->type));
4234 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4235 MonoReflectionType *tb = (MonoReflectionType *)obj;
4236 token = mono_metadata_token_from_dor (
4237 mono_image_typedef_or_ref (assembly, tb->type));
4238 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4239 strcmp (klass->name, "MonoMethod") == 0 ||
4240 strcmp (klass->name, "MonoGenericMethod") == 0 ||
4241 strcmp (klass->name, "MonoGenericCMethod") == 0) {
4242 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4243 if (m->method->is_inflated) {
4244 if (create_methodspec)
4245 token = mono_image_get_methodspec_token (assembly, m->method);
4246 else
4247 token = mono_image_get_inflated_method_token (assembly, m->method);
4248 } else if ((m->method->klass->image == &assembly->image) &&
4249 !m->method->klass->generic_class) {
4250 static guint32 method_table_idx = 0xffffff;
4251 if (m->method->klass->wastypebuilder) {
4252 /* we use the same token as the one that was assigned
4253 * to the Methodbuilder.
4254 * FIXME: do the equivalent for Fields.
4256 token = m->method->token;
4257 } else {
4259 * Each token should have a unique index, but the indexes are
4260 * assigned by managed code, so we don't know about them. An
4261 * easy solution is to count backwards...
4263 method_table_idx --;
4264 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4266 } else {
4267 token = mono_image_get_methodref_token (assembly, m->method);
4269 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4270 } else if (strcmp (klass->name, "MonoField") == 0) {
4271 MonoReflectionField *f = (MonoReflectionField *)obj;
4272 if ((f->field->parent->image == &assembly->image) && !f->field->generic_info) {
4273 static guint32 field_table_idx = 0xffffff;
4274 field_table_idx --;
4275 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4276 } else {
4277 token = mono_image_get_fieldref_token (assembly, f);
4279 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4280 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4281 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4282 token = mono_image_get_array_token (assembly, m);
4283 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4284 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4285 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4286 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
4287 MonoReflectionType *tb = (MonoReflectionType *)obj;
4288 token = mono_metadata_token_from_dor (
4289 mono_image_typedef_or_ref (assembly, tb->type));
4290 } else {
4291 g_error ("requested token for %s\n", klass->name);
4294 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4296 return token;
4299 typedef struct {
4300 guint32 import_lookup_table;
4301 guint32 timestamp;
4302 guint32 forwarder;
4303 guint32 name_rva;
4304 guint32 import_address_table_rva;
4305 } MonoIDT;
4307 typedef struct {
4308 guint32 name_rva;
4309 guint32 flags;
4310 } MonoILT;
4312 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4314 static MonoDynamicImage*
4315 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4317 static const guchar entrycode [16] = {0xff, 0x25, 0};
4318 MonoDynamicImage *image;
4319 int i;
4321 const char *version = mono_get_runtime_info ()->runtime_version;
4323 #if HAVE_BOEHM_GC
4324 image = GC_MALLOC (sizeof (MonoDynamicImage));
4325 #else
4326 image = g_new0 (MonoDynamicImage, 1);
4327 #endif
4329 /*g_print ("created image %p\n", image);*/
4330 /* keep in sync with image.c */
4331 image->image.name = assembly_name;
4332 image->image.assembly_name = image->image.name; /* they may be different */
4333 image->image.module_name = module_name;
4334 image->image.version = g_strdup (version);
4335 image->image.md_version_major = 1;
4336 image->image.md_version_minor = 1;
4337 image->image.dynamic = TRUE;
4339 image->image.references = g_new0 (MonoAssembly*, 1);
4340 image->image.references [0] = NULL;
4342 mono_image_init (&image->image);
4344 image->token_fixups = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_KEY_GC);
4345 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
4346 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
4347 image->method_aux_hash = g_hash_table_new (NULL, NULL);
4348 image->handleref = g_hash_table_new (NULL, NULL);
4349 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4350 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4351 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4352 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4353 image->gen_params = g_ptr_array_new ();
4355 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
4356 string_heap_init (&image->sheap);
4357 mono_image_add_stream_data (&image->us, "", 1);
4358 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4359 /* import tables... */
4360 mono_image_add_stream_data (&image->code, entrycode, sizeof (entrycode));
4361 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4362 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4363 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4364 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4365 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4366 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4367 stream_data_align (&image->code);
4369 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4371 for (i=0; i < MONO_TABLE_NUM; ++i) {
4372 image->tables [i].next_idx = 1;
4373 image->tables [i].columns = table_sizes [i];
4376 image->image.assembly = (MonoAssembly*)assembly;
4377 image->run = assembly->run;
4378 image->save = assembly->save;
4379 image->pe_kind = 0x1; /* ILOnly */
4380 image->machine = 0x14c; /* I386 */
4382 return image;
4386 * mono_image_basic_init:
4387 * @assembly: an assembly builder object
4389 * Create the MonoImage that represents the assembly builder and setup some
4390 * of the helper hash table and the basic metadata streams.
4392 void
4393 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4395 MonoDynamicAssembly *assembly;
4396 MonoDynamicImage *image;
4397 MonoDomain *domain = mono_object_domain (assemblyb);
4399 MONO_ARCH_SAVE_REGS;
4401 if (assemblyb->dynamic_assembly)
4402 return;
4404 #if HAVE_BOEHM_GC
4405 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4406 #else
4407 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
4408 #endif
4410 assembly->assembly.ref_count = 1;
4411 assembly->assembly.dynamic = TRUE;
4412 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
4413 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4414 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4415 if (assemblyb->culture)
4416 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4417 else
4418 assembly->assembly.aname.culture = g_strdup ("");
4420 if (assemblyb->version) {
4421 char *vstr = mono_string_to_utf8 (assemblyb->version);
4422 char **version = g_strsplit (vstr, ".", 4);
4423 char **parts = version;
4424 assembly->assembly.aname.major = atoi (*parts++);
4425 assembly->assembly.aname.minor = atoi (*parts++);
4426 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
4427 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
4429 g_strfreev (version);
4430 g_free (vstr);
4431 } else {
4432 assembly->assembly.aname.major = 0;
4433 assembly->assembly.aname.minor = 0;
4434 assembly->assembly.aname.build = 0;
4435 assembly->assembly.aname.revision = 0;
4438 assembly->run = assemblyb->access != 2;
4439 assembly->save = assemblyb->access != 1;
4441 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4442 image->initial_image = TRUE;
4443 assembly->assembly.aname.name = image->image.name;
4444 assembly->assembly.image = &image->image;
4446 mono_domain_assemblies_lock (domain);
4447 domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
4448 mono_domain_assemblies_unlock (domain);
4450 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4451 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4454 static int
4455 calc_section_size (MonoDynamicImage *assembly)
4457 int nsections = 0;
4459 /* alignment constraints */
4460 assembly->code.index += 3;
4461 assembly->code.index &= ~3;
4462 assembly->meta_size += 3;
4463 assembly->meta_size &= ~3;
4464 assembly->resources.index += 3;
4465 assembly->resources.index &= ~3;
4467 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4468 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4469 nsections++;
4471 if (assembly->win32_res) {
4472 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4474 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4475 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4476 nsections++;
4479 assembly->sections [MONO_SECTION_RELOC].size = 12;
4480 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4481 nsections++;
4483 return nsections;
4486 typedef struct {
4487 guint32 id;
4488 guint32 offset;
4489 GSList *children;
4490 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4491 } ResTreeNode;
4493 static int
4494 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4496 ResTreeNode *t1 = (ResTreeNode*)a;
4497 ResTreeNode *t2 = (ResTreeNode*)b;
4499 return t1->id - t2->id;
4503 * resource_tree_create:
4505 * Organize the resources into a resource tree.
4507 static ResTreeNode *
4508 resource_tree_create (MonoArray *win32_resources)
4510 ResTreeNode *tree, *res_node, *type_node, *lang_node;
4511 GSList *l;
4512 int i;
4514 tree = g_new0 (ResTreeNode, 1);
4516 for (i = 0; i < mono_array_length (win32_resources); ++i) {
4517 MonoReflectionWin32Resource *win32_res =
4518 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4520 /* Create node */
4522 /* FIXME: BUG: this stores managed references in unmanaged memory */
4523 lang_node = g_new0 (ResTreeNode, 1);
4524 lang_node->id = win32_res->lang_id;
4525 lang_node->win32_res = win32_res;
4527 /* Create type node if neccesary */
4528 type_node = NULL;
4529 for (l = tree->children; l; l = l->next)
4530 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4531 type_node = (ResTreeNode*)l->data;
4532 break;
4535 if (!type_node) {
4536 type_node = g_new0 (ResTreeNode, 1);
4537 type_node->id = win32_res->res_type;
4540 * The resource types have to be sorted otherwise
4541 * Windows Explorer can't display the version information.
4543 tree->children = g_slist_insert_sorted (tree->children,
4544 type_node, resource_tree_compare_by_id);
4547 /* Create res node if neccesary */
4548 res_node = NULL;
4549 for (l = type_node->children; l; l = l->next)
4550 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4551 res_node = (ResTreeNode*)l->data;
4552 break;
4555 if (!res_node) {
4556 res_node = g_new0 (ResTreeNode, 1);
4557 res_node->id = win32_res->res_id;
4558 type_node->children = g_slist_append (type_node->children, res_node);
4561 res_node->children = g_slist_append (res_node->children, lang_node);
4564 return tree;
4568 * resource_tree_encode:
4570 * Encode the resource tree into the format used in the PE file.
4572 static void
4573 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4575 char *entries;
4576 MonoPEResourceDir dir;
4577 MonoPEResourceDirEntry dir_entry;
4578 MonoPEResourceDataEntry data_entry;
4579 GSList *l;
4582 * For the format of the resource directory, see the article
4583 * "An In-Depth Look into the Win32 Portable Executable File Format" by
4584 * Matt Pietrek
4587 memset (&dir, 0, sizeof (dir));
4588 memset (&dir_entry, 0, sizeof (dir_entry));
4589 memset (&data_entry, 0, sizeof (data_entry));
4591 g_assert (sizeof (dir) == 16);
4592 g_assert (sizeof (dir_entry) == 8);
4593 g_assert (sizeof (data_entry) == 16);
4595 node->offset = p - begin;
4597 /* IMAGE_RESOURCE_DIRECTORY */
4598 dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4600 memcpy (p, &dir, sizeof (dir));
4601 p += sizeof (dir);
4603 /* Reserve space for entries */
4604 entries = p;
4605 p += sizeof (dir_entry) * dir.res_id_entries;
4607 /* Write children */
4608 for (l = node->children; l; l = l->next) {
4609 ResTreeNode *child = (ResTreeNode*)l->data;
4611 if (child->win32_res) {
4613 child->offset = p - begin;
4615 /* IMAGE_RESOURCE_DATA_ENTRY */
4616 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4617 data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4619 memcpy (p, &data_entry, sizeof (data_entry));
4620 p += sizeof (data_entry);
4622 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4623 p += data_entry.rde_size;
4624 } else {
4625 resource_tree_encode (child, begin, p, &p);
4629 /* IMAGE_RESOURCE_ENTRY */
4630 for (l = node->children; l; l = l->next) {
4631 ResTreeNode *child = (ResTreeNode*)l->data;
4632 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4634 dir_entry.is_dir = child->win32_res ? 0 : 1;
4635 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4637 memcpy (entries, &dir_entry, sizeof (dir_entry));
4638 entries += sizeof (dir_entry);
4641 *endbuf = p;
4644 static void
4645 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4647 char *buf;
4648 char *p;
4649 guint32 size, i;
4650 MonoReflectionWin32Resource *win32_res;
4651 ResTreeNode *tree;
4653 if (!assemblyb->win32_resources)
4654 return;
4657 * Resources are stored in a three level tree inside the PE file.
4658 * - level one contains a node for each type of resource
4659 * - level two contains a node for each resource
4660 * - level three contains a node for each instance of a resource for a
4661 * specific language.
4664 tree = resource_tree_create (assemblyb->win32_resources);
4666 /* Estimate the size of the encoded tree */
4667 size = 0;
4668 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4669 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4670 size += mono_array_length (win32_res->res_data);
4672 /* Directory structure */
4673 size += mono_array_length (assemblyb->win32_resources) * 256;
4674 p = buf = g_malloc (size);
4676 resource_tree_encode (tree, p, p, &p);
4678 g_assert (p - buf < size);
4680 assembly->win32_res = g_malloc (p - buf);
4681 assembly->win32_res_size = p - buf;
4682 memcpy (assembly->win32_res, buf, p - buf);
4684 g_free (buf);
4687 static void
4688 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4690 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4691 int i;
4693 p += sizeof (MonoPEResourceDir);
4694 for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4695 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4696 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4697 if (dir_entry->is_dir) {
4698 fixup_resource_directory (res_section, child, rva);
4699 } else {
4700 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4701 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4704 p += sizeof (MonoPEResourceDirEntry);
4708 static void
4709 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
4711 guint32 dummy;
4712 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
4713 g_error ("WriteFile returned %d\n", GetLastError ());
4717 * mono_image_create_pefile:
4718 * @mb: a module builder object
4720 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
4721 * assembly->pefile where it can be easily retrieved later in chunks.
4723 void
4724 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file) {
4725 MonoMSDOSHeader *msdos;
4726 MonoDotNetHeader *header;
4727 MonoSectionTable *section;
4728 MonoCLIHeader *cli_header;
4729 guint32 size, image_size, virtual_base, text_offset;
4730 guint32 header_start, section_start, file_offset, virtual_offset;
4731 MonoDynamicImage *assembly;
4732 MonoReflectionAssemblyBuilder *assemblyb;
4733 MonoDynamicStream pefile_stream = {0};
4734 MonoDynamicStream *pefile = &pefile_stream;
4735 int i, nsections;
4736 guint32 *rva, value;
4737 guchar *p;
4738 static const unsigned char msheader[] = {
4739 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4740 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4741 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4742 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4743 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4744 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4745 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4746 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4749 assemblyb = mb->assemblyb;
4751 mono_image_basic_init (assemblyb);
4752 assembly = mb->dynamic_image;
4754 assembly->pe_kind = assemblyb->pe_kind;
4755 assembly->machine = assemblyb->machine;
4756 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
4757 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
4759 mono_image_build_metadata (mb);
4761 if (mb->is_main && assemblyb->resources) {
4762 int len = mono_array_length (assemblyb->resources);
4763 for (i = 0; i < len; ++i)
4764 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4767 if (mb->resources) {
4768 int len = mono_array_length (mb->resources);
4769 for (i = 0; i < len; ++i)
4770 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4773 build_compressed_metadata (assembly);
4775 if (mb->is_main)
4776 assembly_add_win32_resources (assembly, assemblyb);
4778 nsections = calc_section_size (assembly);
4780 /* The DOS header and stub */
4781 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4782 mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
4784 /* the dotnet header */
4785 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4787 /* the section tables */
4788 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4790 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4791 virtual_offset = VIRT_ALIGN;
4792 image_size = 0;
4794 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4795 if (!assembly->sections [i].size)
4796 continue;
4797 /* align offsets */
4798 file_offset += FILE_ALIGN - 1;
4799 file_offset &= ~(FILE_ALIGN - 1);
4800 virtual_offset += VIRT_ALIGN - 1;
4801 virtual_offset &= ~(VIRT_ALIGN - 1);
4803 assembly->sections [i].offset = file_offset;
4804 assembly->sections [i].rva = virtual_offset;
4806 file_offset += assembly->sections [i].size;
4807 virtual_offset += assembly->sections [i].size;
4808 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4811 file_offset += FILE_ALIGN - 1;
4812 file_offset &= ~(FILE_ALIGN - 1);
4814 image_size += section_start + sizeof (MonoSectionTable) * nsections;
4816 /* back-patch info */
4817 msdos = (MonoMSDOSHeader*)pefile->data;
4818 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4820 header = (MonoDotNetHeader*)(pefile->data + header_start);
4821 header->pesig [0] = 'P';
4822 header->pesig [1] = 'E';
4824 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
4825 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4826 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4827 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4828 if (assemblyb->pekind == 1) {
4829 /* it's a dll */
4830 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4831 } else {
4832 /* it's an exe */
4833 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4836 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4838 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4839 header->pe.pe_major = 6;
4840 header->pe.pe_minor = 0;
4841 size = assembly->sections [MONO_SECTION_TEXT].size;
4842 size += FILE_ALIGN - 1;
4843 size &= ~(FILE_ALIGN - 1);
4844 header->pe.pe_code_size = GUINT32_FROM_LE(size);
4845 size = assembly->sections [MONO_SECTION_RSRC].size;
4846 size += FILE_ALIGN - 1;
4847 size &= ~(FILE_ALIGN - 1);
4848 header->pe.pe_data_size = GUINT32_FROM_LE(size);
4849 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4850 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4851 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4852 /* pe_rva_entry_point always at the beginning of the text section */
4853 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4855 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4856 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4857 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4858 header->nt.pe_os_major = GUINT16_FROM_LE (4);
4859 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4860 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4861 size = section_start;
4862 size += FILE_ALIGN - 1;
4863 size &= ~(FILE_ALIGN - 1);
4864 header->nt.pe_header_size = GUINT32_FROM_LE (size);
4865 size = image_size;
4866 size += VIRT_ALIGN - 1;
4867 size &= ~(VIRT_ALIGN - 1);
4868 header->nt.pe_image_size = GUINT32_FROM_LE (size);
4871 // Translate the PEFileKind value to the value expected by the Windows loader
4874 short kind;
4877 // PEFileKinds.Dll == 1
4878 // PEFileKinds.ConsoleApplication == 2
4879 // PEFileKinds.WindowApplication == 3
4881 // need to get:
4882 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4883 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4885 if (assemblyb->pekind == 3)
4886 kind = 2;
4887 else
4888 kind = 3;
4890 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4892 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4893 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4894 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4895 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4896 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4897 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4899 /* fill data directory entries */
4901 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4902 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4904 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4905 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4907 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4908 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4909 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4910 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4911 /* patch entrypoint name */
4912 if (assemblyb->pekind == 1)
4913 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
4914 else
4915 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
4916 /* patch imported function RVA name */
4917 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4918 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4920 /* the import table */
4921 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4922 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4923 /* patch imported dll RVA name and other entries in the dir */
4924 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4925 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
4926 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4927 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4928 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4929 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4931 p = (assembly->code.data + assembly->ilt_offset);
4932 value = (assembly->text_rva + assembly->imp_names_offset);
4933 *p++ = (value) & 0xff;
4934 *p++ = (value >> 8) & (0xff);
4935 *p++ = (value >> 16) & (0xff);
4936 *p++ = (value >> 24) & (0xff);
4938 /* the CLI header info */
4939 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4940 cli_header->ch_size = GUINT32_FROM_LE (72);
4941 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4942 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
4943 if (assemblyb->entry_point) {
4944 guint32 table_idx = 0;
4945 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4946 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4947 table_idx = methodb->table_idx;
4948 } else {
4949 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4951 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4952 } else {
4953 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4955 /* The embedded managed resources */
4956 text_offset = assembly->text_rva + assembly->code.index;
4957 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4958 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4959 text_offset += assembly->resources.index;
4960 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4961 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4962 text_offset += assembly->meta_size;
4963 if (assembly->strong_name_size) {
4964 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4965 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4966 text_offset += assembly->strong_name_size;
4969 /* write the section tables and section content */
4970 section = (MonoSectionTable*)(pefile->data + section_start);
4971 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4972 static const char section_names [][7] = {
4973 ".text", ".rsrc", ".reloc"
4975 if (!assembly->sections [i].size)
4976 continue;
4977 strcpy (section->st_name, section_names [i]);
4978 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
4979 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
4980 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
4981 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
4982 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
4983 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
4984 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
4985 section ++;
4988 checked_write_file (file, pefile->data, pefile->index);
4990 mono_dynamic_stream_reset (pefile);
4992 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4993 if (!assembly->sections [i].size)
4994 continue;
4996 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
4997 g_error ("SetFilePointer returned %d\n", GetLastError ());
4999 switch (i) {
5000 case MONO_SECTION_TEXT:
5001 /* patch entry point */
5002 p = (assembly->code.data + 2);
5003 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5004 *p++ = (value) & 0xff;
5005 *p++ = (value >> 8) & 0xff;
5006 *p++ = (value >> 16) & 0xff;
5007 *p++ = (value >> 24) & 0xff;
5009 checked_write_file (file, assembly->code.data, assembly->code.index);
5010 checked_write_file (file, assembly->resources.data, assembly->resources.index);
5011 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5012 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5015 g_free (assembly->image.raw_metadata);
5016 break;
5017 case MONO_SECTION_RELOC: {
5018 struct {
5019 guint32 page_rva;
5020 guint32 block_size;
5021 guint16 type_and_offset;
5022 guint16 term;
5023 } reloc;
5025 g_assert (sizeof (reloc) == 12);
5027 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5028 reloc.block_size = GUINT32_FROM_LE (12);
5031 * the entrypoint is always at the start of the text section
5032 * 3 is IMAGE_REL_BASED_HIGHLOW
5033 * 2 is patch_size_rva - text_rva
5035 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5036 reloc.term = 0;
5038 checked_write_file (file, &reloc, sizeof (reloc));
5040 break;
5042 case MONO_SECTION_RSRC:
5043 if (assembly->win32_res) {
5045 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5046 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5047 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5049 break;
5050 default:
5051 g_assert_not_reached ();
5055 /* check that the file is properly padded */
5056 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5057 g_error ("SetFilePointer returned %d\n", GetLastError ());
5058 if (! SetEndOfFile (file))
5059 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5061 mono_dynamic_stream_reset (&assembly->code);
5062 mono_dynamic_stream_reset (&assembly->us);
5063 mono_dynamic_stream_reset (&assembly->blob);
5064 mono_dynamic_stream_reset (&assembly->guid);
5065 mono_dynamic_stream_reset (&assembly->sheap);
5067 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5068 g_hash_table_destroy (assembly->blob_cache);
5069 assembly->blob_cache = NULL;
5072 MonoReflectionModule *
5073 mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5075 char *name;
5076 MonoImage *image;
5077 MonoImageOpenStatus status;
5078 MonoDynamicAssembly *assembly;
5079 guint32 module_count;
5080 MonoImage **new_modules;
5082 name = mono_string_to_utf8 (fileName);
5084 image = mono_image_open (name, &status);
5085 if (!image) {
5086 MonoException *exc;
5087 if (status == MONO_IMAGE_ERROR_ERRNO)
5088 exc = mono_get_exception_file_not_found (fileName);
5089 else
5090 exc = mono_get_exception_bad_image_format (name);
5091 g_free (name);
5092 mono_raise_exception (exc);
5095 g_free (name);
5097 assembly = ab->dynamic_assembly;
5098 image->assembly = (MonoAssembly*)assembly;
5100 module_count = image->assembly->image->module_count;
5101 new_modules = g_new0 (MonoImage *, module_count + 1);
5103 if (image->assembly->image->modules)
5104 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5105 new_modules [module_count] = image;
5106 mono_image_addref (image);
5108 g_free (image->assembly->image->modules);
5109 image->assembly->image->modules = new_modules;
5110 image->assembly->image->module_count ++;
5112 mono_assembly_load_references (image, &status);
5113 if (status) {
5114 mono_image_close (image);
5115 mono_raise_exception (mono_get_exception_file_not_found (fileName));
5118 return mono_module_get_object (mono_domain_get (), image);
5122 * We need to return always the same object for MethodInfo, FieldInfo etc..
5123 * but we need to consider the reflected type.
5124 * type uses a different hash, since it uses custom hash/equal functions.
5127 typedef struct {
5128 gpointer item;
5129 MonoClass *refclass;
5130 } ReflectedEntry;
5132 static gboolean
5133 reflected_equal (gconstpointer a, gconstpointer b) {
5134 const ReflectedEntry *ea = a;
5135 const ReflectedEntry *eb = b;
5137 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
5140 static guint
5141 reflected_hash (gconstpointer a) {
5142 const ReflectedEntry *ea = a;
5143 return mono_aligned_addr_hash (ea->item);
5146 #define CHECK_OBJECT(t,p,k) \
5147 do { \
5148 t _obj; \
5149 ReflectedEntry e; \
5150 e.item = (p); \
5151 e.refclass = (k); \
5152 mono_domain_lock (domain); \
5153 if (!domain->refobject_hash) \
5154 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5155 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
5156 mono_domain_unlock (domain); \
5157 return _obj; \
5159 mono_domain_unlock (domain); \
5160 } while (0)
5162 #if HAVE_BOEHM_GC
5163 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
5164 #elif HAVE_SGEN_GC
5165 #define ALLOC_REFENTRY mono_gc_alloc_fixed (sizeof (ReflectedEntry), NULL)
5166 #else
5167 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5168 #endif
5170 #define CACHE_OBJECT(t,p,o,k) \
5171 do { \
5172 t _obj; \
5173 ReflectedEntry pe; \
5174 pe.item = (p); \
5175 pe.refclass = (k); \
5176 mono_domain_lock (domain); \
5177 if (!domain->refobject_hash) \
5178 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5179 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
5180 if (!_obj) { \
5181 ReflectedEntry *e = ALLOC_REFENTRY; \
5182 e->item = (p); \
5183 e->refclass = (k); \
5184 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
5185 _obj = o; \
5187 mono_domain_unlock (domain); \
5188 return _obj; \
5189 } while (0)
5191 static gpointer
5192 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
5194 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5197 static gpointer
5198 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5200 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
5203 void
5204 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5206 MonoDynamicImage *image = moduleb->dynamic_image;
5207 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5208 if (!image) {
5209 int module_count;
5210 MonoImage **new_modules;
5211 MonoImage *ass;
5213 * FIXME: we already created an image in mono_image_basic_init (), but
5214 * we don't know which module it belongs to, since that is only
5215 * determined at assembly save time.
5217 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5218 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5220 moduleb->module.image = &image->image;
5221 moduleb->dynamic_image = image;
5222 register_module (mono_object_domain (moduleb), moduleb, image);
5224 /* register the module with the assembly */
5225 ass = ab->dynamic_assembly->assembly.image;
5226 module_count = ass->module_count;
5227 new_modules = g_new0 (MonoImage *, module_count + 1);
5229 if (ass->modules)
5230 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
5231 new_modules [module_count] = &image->image;
5232 mono_image_addref (&image->image);
5234 g_free (ass->modules);
5235 ass->modules = new_modules;
5236 ass->module_count ++;
5241 * mono_assembly_get_object:
5242 * @domain: an app domain
5243 * @assembly: an assembly
5245 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5247 MonoReflectionAssembly*
5248 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5250 static MonoClass *System_Reflection_Assembly;
5251 MonoReflectionAssembly *res;
5253 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5254 if (!System_Reflection_Assembly)
5255 System_Reflection_Assembly = mono_class_from_name (
5256 mono_defaults.corlib, "System.Reflection", "Assembly");
5257 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5258 res->assembly = assembly;
5260 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5265 MonoReflectionModule*
5266 mono_module_get_object (MonoDomain *domain, MonoImage *image)
5268 static MonoClass *System_Reflection_Module;
5269 MonoReflectionModule *res;
5270 char* basename;
5272 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5273 if (!System_Reflection_Module)
5274 System_Reflection_Module = mono_class_from_name (
5275 mono_defaults.corlib, "System.Reflection", "Module");
5276 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5278 res->image = image;
5279 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5281 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
5282 basename = g_path_get_basename (image->name);
5283 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
5284 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
5286 g_free (basename);
5288 if (image->assembly->image == image) {
5289 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5290 } else {
5291 int i;
5292 res->token = 0;
5293 if (image->assembly->image->modules) {
5294 for (i = 0; i < image->assembly->image->module_count; i++) {
5295 if (image->assembly->image->modules [i] == image)
5296 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5298 g_assert (res->token);
5302 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
5305 MonoReflectionModule*
5306 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5308 static MonoClass *System_Reflection_Module;
5309 MonoReflectionModule *res;
5310 MonoTableInfo *table;
5311 guint32 cols [MONO_FILE_SIZE];
5312 const char *name;
5313 guint32 i, name_idx;
5314 const char *val;
5316 if (!System_Reflection_Module)
5317 System_Reflection_Module = mono_class_from_name (
5318 mono_defaults.corlib, "System.Reflection", "Module");
5319 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5321 table = &image->tables [MONO_TABLE_FILE];
5322 g_assert (table_index < table->rows);
5323 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5325 res->image = NULL;
5326 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5327 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5329 /* Check whenever the row has a corresponding row in the moduleref table */
5330 table = &image->tables [MONO_TABLE_MODULEREF];
5331 for (i = 0; i < table->rows; ++i) {
5332 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5333 val = mono_metadata_string_heap (image, name_idx);
5334 if (strcmp (val, name) == 0)
5335 res->image = image->modules [i];
5338 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
5339 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
5340 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
5341 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5342 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5344 return res;
5347 static gboolean
5348 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5350 if ((t1->type != t2->type) ||
5351 (t1->byref != t2->byref))
5352 return FALSE;
5354 switch (t1->type) {
5355 case MONO_TYPE_VOID:
5356 case MONO_TYPE_BOOLEAN:
5357 case MONO_TYPE_CHAR:
5358 case MONO_TYPE_I1:
5359 case MONO_TYPE_U1:
5360 case MONO_TYPE_I2:
5361 case MONO_TYPE_U2:
5362 case MONO_TYPE_I4:
5363 case MONO_TYPE_U4:
5364 case MONO_TYPE_I8:
5365 case MONO_TYPE_U8:
5366 case MONO_TYPE_R4:
5367 case MONO_TYPE_R8:
5368 case MONO_TYPE_STRING:
5369 case MONO_TYPE_I:
5370 case MONO_TYPE_U:
5371 case MONO_TYPE_OBJECT:
5372 case MONO_TYPE_TYPEDBYREF:
5373 return TRUE;
5374 case MONO_TYPE_VALUETYPE:
5375 case MONO_TYPE_CLASS:
5376 case MONO_TYPE_SZARRAY:
5377 return t1->data.klass == t2->data.klass;
5378 case MONO_TYPE_PTR:
5379 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5380 case MONO_TYPE_ARRAY:
5381 if (t1->data.array->rank != t2->data.array->rank)
5382 return FALSE;
5383 return t1->data.array->eklass == t2->data.array->eklass;
5384 case MONO_TYPE_GENERICINST: {
5385 int i;
5386 if (t1->data.generic_class->inst->type_argc != t2->data.generic_class->inst->type_argc)
5387 return FALSE;
5388 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
5389 &t2->data.generic_class->container_class->byval_arg))
5390 return FALSE;
5391 for (i = 0; i < t1->data.generic_class->inst->type_argc; ++i) {
5392 if (!mono_metadata_type_equal (t1->data.generic_class->inst->type_argv [i], t2->data.generic_class->inst->type_argv [i]))
5393 return FALSE;
5395 return TRUE;
5397 case MONO_TYPE_VAR:
5398 case MONO_TYPE_MVAR:
5399 return t1->data.generic_param == t2->data.generic_param;
5400 default:
5401 g_error ("implement type compare for %0x!", t1->type);
5402 return FALSE;
5405 return FALSE;
5408 static guint
5409 mymono_metadata_type_hash (MonoType *t1)
5411 guint hash;
5413 hash = t1->type;
5415 hash |= t1->byref << 6; /* do not collide with t1->type values */
5416 switch (t1->type) {
5417 case MONO_TYPE_VALUETYPE:
5418 case MONO_TYPE_CLASS:
5419 case MONO_TYPE_SZARRAY:
5420 /* check if the distribution is good enough */
5421 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5422 case MONO_TYPE_PTR:
5423 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5424 case MONO_TYPE_GENERICINST: {
5425 int i;
5426 MonoGenericInst *inst = t1->data.generic_class->inst;
5427 hash += g_str_hash (t1->data.generic_class->container_class->name);
5428 hash *= 13;
5429 for (i = 0; i < inst->type_argc; ++i) {
5430 hash += mymono_metadata_type_hash (inst->type_argv [i]);
5431 hash *= 13;
5433 return hash;
5436 return hash;
5439 static MonoReflectionGenericClass*
5440 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
5442 static MonoClass *System_Reflection_MonoGenericClass;
5443 MonoReflectionGenericClass *res;
5444 MonoInflatedGenericClass *gclass;
5445 MonoClass *gklass;
5447 if (!System_Reflection_MonoGenericClass) {
5448 System_Reflection_MonoGenericClass = mono_class_from_name (
5449 mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
5450 g_assert (System_Reflection_MonoGenericClass);
5453 gclass = mono_get_inflated_generic_class (geninst->data.generic_class);
5454 gklass = gclass->generic_class.container_class;
5455 g_assert (gklass->generic_container);
5457 mono_class_init (gclass->klass);
5459 #ifdef HAVE_SGEN_GC
5460 /* FIXME: allow unpinned later */
5461 res = (MonoReflectionGenericClass *) mono_gc_alloc_pinned_obj (mono_class_vtable (domain, System_Reflection_MonoGenericClass), mono_class_instance_size (System_Reflection_MonoGenericClass));
5462 #else
5463 res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
5464 #endif
5466 res->type.type = geninst;
5467 if (gklass->wastypebuilder && gklass->reflection_info)
5468 MONO_OBJECT_SETREF (res, generic_type, gklass->reflection_info);
5469 else
5470 MONO_OBJECT_SETREF (res, generic_type, mono_type_get_object (domain, &gklass->byval_arg));
5472 return res;
5475 static gboolean
5476 verify_safe_for_managed_space (MonoType *type)
5478 switch (type->type) {
5479 #ifdef DEBUG_HARDER
5480 case MONO_TYPE_ARRAY:
5481 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
5482 case MONO_TYPE_PTR:
5483 return verify_safe_for_managed_space (type->data.type);
5484 case MONO_TYPE_SZARRAY:
5485 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
5486 case MONO_TYPE_GENERICINST: {
5487 MonoGenericInst *inst = type->data.generic_class->inst;
5488 int i;
5489 if (!inst->is_open)
5490 break;
5491 for (i = 0; i < inst->type_argc; ++i)
5492 if (!verify_safe_for_managed_space (inst->type_argv [i]))
5493 return FALSE;
5494 break;
5496 #endif
5497 case MONO_TYPE_VAR:
5498 case MONO_TYPE_MVAR:
5499 return TRUE;
5501 return TRUE;
5505 * mono_type_get_object:
5506 * @domain: an app domain
5507 * @type: a type
5509 * Return an System.MonoType object representing the type @type.
5511 MonoReflectionType*
5512 mono_type_get_object (MonoDomain *domain, MonoType *type)
5514 MonoReflectionType *res;
5515 MonoClass *klass = mono_class_from_mono_type (type);
5517 mono_domain_lock (domain);
5518 if (!domain->type_hash)
5519 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash,
5520 (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
5521 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5522 mono_domain_unlock (domain);
5523 return res;
5525 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic) {
5526 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
5527 mono_g_hash_table_insert (domain->type_hash, type, res);
5528 mono_domain_unlock (domain);
5529 return res;
5532 if (!verify_safe_for_managed_space (type)) {
5533 mono_domain_unlock (domain);
5534 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
5537 if (klass->reflection_info && !klass->wastypebuilder) {
5538 /* g_assert_not_reached (); */
5539 /* should this be considered an error condition? */
5540 if (!type->byref) {
5541 mono_domain_unlock (domain);
5542 return klass->reflection_info;
5545 mono_class_init (klass);
5546 #ifdef HAVE_SGEN_GC
5547 res = (MonoReflectionType *)mono_gc_alloc_pinned_obj (mono_class_vtable (domain, mono_defaults.monotype_class), mono_class_instance_size (mono_defaults.monotype_class));
5548 #else
5549 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5550 #endif
5551 res->type = type;
5552 mono_g_hash_table_insert (domain->type_hash, type, res);
5553 mono_domain_unlock (domain);
5554 return res;
5558 * mono_method_get_object:
5559 * @domain: an app domain
5560 * @method: a method
5561 * @refclass: the reflected type (can be NULL)
5563 * Return an System.Reflection.MonoMethod object representing the method @method.
5565 MonoReflectionMethod*
5566 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5569 * We use the same C representation for methods and constructors, but the type
5570 * name in C# is different.
5572 static MonoClass *System_Reflection_MonoMethod = NULL;
5573 static MonoClass *System_Reflection_MonoCMethod = NULL;
5574 static MonoClass *System_Reflection_MonoGenericMethod = NULL;
5575 static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
5576 const char *cname;
5577 MonoClass *klass;
5578 MonoReflectionMethod *ret;
5580 if (method->is_inflated) {
5581 MonoReflectionGenericMethod *gret;
5583 method = mono_get_inflated_method (method);
5584 refclass = method->klass;
5585 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5586 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
5587 if (!System_Reflection_MonoGenericCMethod)
5588 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
5589 klass = System_Reflection_MonoGenericCMethod;
5590 } else {
5591 if (!System_Reflection_MonoGenericMethod)
5592 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
5593 klass = System_Reflection_MonoGenericMethod;
5595 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
5596 gret->method.method = method;
5597 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
5598 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
5599 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
5602 if (!refclass)
5603 refclass = method->klass;
5605 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5606 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
5607 if (!System_Reflection_MonoCMethod)
5608 System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
5609 klass = System_Reflection_MonoCMethod;
5611 else {
5612 if (!System_Reflection_MonoMethod)
5613 System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
5614 klass = System_Reflection_MonoMethod;
5616 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5617 ret->method = method;
5618 MONO_OBJECT_SETREF (ret, name, mono_string_new (domain, method->name));
5619 MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
5620 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
5624 * mono_field_get_object:
5625 * @domain: an app domain
5626 * @klass: a type
5627 * @field: a field
5629 * Return an System.Reflection.MonoField object representing the field @field
5630 * in class @klass.
5632 MonoReflectionField*
5633 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5635 MonoReflectionField *res;
5636 MonoClass *oklass;
5638 CHECK_OBJECT (MonoReflectionField *, field, klass);
5639 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5640 res = (MonoReflectionField *)mono_object_new (domain, oklass);
5641 res->klass = klass;
5642 res->field = field;
5643 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, field->name));
5644 if (field->generic_info)
5645 res->attrs = field->generic_info->generic_type->attrs;
5646 else
5647 res->attrs = field->type->attrs;
5648 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
5649 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
5653 * mono_property_get_object:
5654 * @domain: an app domain
5655 * @klass: a type
5656 * @property: a property
5658 * Return an System.Reflection.MonoProperty object representing the property @property
5659 * in class @klass.
5661 MonoReflectionProperty*
5662 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5664 MonoReflectionProperty *res;
5665 MonoClass *oklass;
5667 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5668 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5669 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
5670 res->klass = klass;
5671 res->property = property;
5672 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
5676 * mono_event_get_object:
5677 * @domain: an app domain
5678 * @klass: a type
5679 * @event: a event
5681 * Return an System.Reflection.MonoEvent object representing the event @event
5682 * in class @klass.
5684 MonoReflectionEvent*
5685 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5687 MonoReflectionEvent *res;
5688 MonoClass *oklass;
5690 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5691 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5692 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
5693 res->klass = klass;
5694 res->event = event;
5695 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
5699 * mono_param_get_objects:
5700 * @domain: an app domain
5701 * @method: a method
5703 * Return an System.Reflection.ParameterInfo array object representing the parameters
5704 * in the method @method.
5706 MonoArray*
5707 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5709 static MonoClass *System_Reflection_ParameterInfo;
5710 MonoArray *res = NULL;
5711 MonoReflectionMethod *member = NULL;
5712 MonoReflectionParameter *param = NULL;
5713 char **names, **blobs = NULL;
5714 guint32 *types = NULL;
5715 MonoType *type = NULL;
5716 MonoObject *dbnull = mono_get_dbnull_object (domain);
5717 MonoMarshalSpec **mspecs;
5718 MonoMethodSignature *sig;
5719 int i;
5721 if (!System_Reflection_ParameterInfo)
5722 System_Reflection_ParameterInfo = mono_class_from_name (
5723 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5725 if (!mono_method_signature (method)->param_count)
5726 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5728 /* Note: the cache is based on the address of the signature into the method
5729 * since we already cache MethodInfos with the method as keys.
5731 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5733 sig = mono_method_signature (method);
5734 member = mono_method_get_object (domain, method, NULL);
5735 names = g_new (char *, sig->param_count);
5736 mono_method_get_param_names (method, (const char **) names);
5738 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
5739 mono_method_get_marshal_info (method, mspecs);
5741 res = mono_array_new (domain, System_Reflection_ParameterInfo, sig->param_count);
5742 for (i = 0; i < sig->param_count; ++i) {
5743 param = (MonoReflectionParameter *)mono_object_new (domain, System_Reflection_ParameterInfo);
5744 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
5745 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
5746 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
5747 param->PositionImpl = i;
5748 param->AttrsImpl = sig->params [i]->attrs;
5750 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
5751 MONO_OBJECT_SETREF (param, DefaultValueImpl, dbnull);
5752 } else {
5754 if (!blobs) {
5755 blobs = g_new0 (char *, sig->param_count);
5756 types = g_new0 (guint32, sig->param_count);
5757 get_default_param_value_blobs (method, blobs, types);
5760 /* Build MonoType for the type from the Constant Table */
5761 if (!type)
5762 type = g_new0 (MonoType, 1);
5763 type->type = types [i];
5764 type->data.klass = NULL;
5765 if (types [i] == MONO_TYPE_CLASS)
5766 type->data.klass = mono_defaults.object_class;
5767 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
5768 /* For enums, types [i] contains the base type */
5770 type->type = MONO_TYPE_VALUETYPE;
5771 type->data.klass = mono_class_from_mono_type (sig->params [i]);
5772 } else
5773 type->data.klass = mono_class_from_mono_type (type);
5775 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
5777 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
5778 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl)
5779 MONO_OBJECT_SETREF (param, DefaultValueImpl, dbnull);
5783 if (mspecs [i + 1])
5784 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
5786 mono_array_setref (res, i, param);
5788 g_free (names);
5789 g_free (blobs);
5790 g_free (types);
5791 g_free (type);
5793 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
5794 if (mspecs [i])
5795 mono_metadata_free_marshal_spec (mspecs [i]);
5796 g_free (mspecs);
5798 CACHE_OBJECT (MonoArray *, &(method->signature), res, NULL);
5802 * mono_method_body_get_object:
5803 * @domain: an app domain
5804 * @method: a method
5806 * Return an System.Reflection.MethodBody object representing the method @method.
5808 MonoReflectionMethodBody*
5809 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
5811 static MonoClass *System_Reflection_MethodBody = NULL;
5812 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
5813 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
5814 MonoReflectionMethodBody *ret;
5815 MonoMethodNormal *mn;
5816 MonoMethodHeader *header;
5817 guint32 method_rva, local_var_sig_token;
5818 char *ptr;
5819 unsigned char format, flags;
5820 int i;
5822 if (!System_Reflection_MethodBody)
5823 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
5824 if (!System_Reflection_LocalVariableInfo)
5825 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
5826 if (!System_Reflection_ExceptionHandlingClause)
5827 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
5829 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
5831 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
5832 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
5833 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
5834 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
5835 return NULL;
5836 mn = (MonoMethodNormal *)method;
5837 header = mono_method_get_header (method);
5839 /* Obtain local vars signature token */
5840 method_rva = mono_metadata_decode_row_col (&method->klass->image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
5841 ptr = mono_image_rva_map (method->klass->image, method_rva);
5842 flags = *(const unsigned char *) ptr;
5843 format = flags & METHOD_HEADER_FORMAT_MASK;
5844 switch (format){
5845 case METHOD_HEADER_TINY_FORMAT:
5846 case METHOD_HEADER_TINY_FORMAT1:
5847 local_var_sig_token = 0;
5848 break;
5849 case METHOD_HEADER_FAT_FORMAT:
5850 ptr += 2;
5851 ptr += 2;
5852 ptr += 4;
5853 local_var_sig_token = read32 (ptr);
5854 break;
5855 default:
5856 g_assert_not_reached ();
5859 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
5861 ret->init_locals = header->init_locals;
5862 ret->max_stack = header->max_stack;
5863 ret->local_var_sig_token = local_var_sig_token;
5864 MONO_OBJECT_SETREF (ret, il, mono_array_new (domain, mono_defaults.byte_class, header->code_size));
5865 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
5867 /* Locals */
5868 MONO_OBJECT_SETREF (ret, locals, mono_array_new (domain, System_Reflection_LocalVariableInfo, header->num_locals));
5869 for (i = 0; i < header->num_locals; ++i) {
5870 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
5871 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
5872 info->is_pinned = header->locals [i]->pinned;
5873 info->local_index = i;
5874 mono_array_setref (ret->locals, i, info);
5877 /* Exceptions */
5878 MONO_OBJECT_SETREF (ret, clauses, mono_array_new (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
5879 for (i = 0; i < header->num_clauses; ++i) {
5880 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
5881 MonoExceptionClause *clause = &header->clauses [i];
5883 info->flags = clause->flags;
5884 info->try_offset = clause->try_offset;
5885 info->try_length = clause->try_len;
5886 info->handler_offset = clause->handler_offset;
5887 info->handler_length = clause->handler_len;
5888 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
5889 info->filter_offset = clause->data.filter_offset;
5890 else if (clause->data.catch_class)
5891 MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
5893 mono_array_setref (ret->clauses, i, info);
5896 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
5897 return ret;
5900 MonoObject *
5901 mono_get_dbnull_object (MonoDomain *domain)
5903 MonoObject *obj;
5904 MonoClass *klass;
5905 static MonoClassField *dbnull_value_field = NULL;
5907 if (!dbnull_value_field) {
5908 klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
5909 mono_class_init (klass);
5910 dbnull_value_field = mono_class_get_field_from_name (klass, "Value");
5911 g_assert (dbnull_value_field);
5913 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
5914 g_assert (obj);
5915 return obj;
5919 static void
5920 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
5922 guint32 param_index, i, lastp, crow = 0;
5923 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
5924 gint32 idx;
5926 MonoClass *klass = method->klass;
5927 MonoImage *image = klass->image;
5928 MonoMethodSignature *methodsig = mono_method_signature (method);
5930 MonoTableInfo *constt;
5931 MonoTableInfo *methodt;
5932 MonoTableInfo *paramt;
5934 if (!methodsig->param_count)
5935 return;
5937 mono_class_init (klass);
5939 if (klass->image->dynamic) {
5940 MonoReflectionMethodAux *aux;
5941 if (method->is_inflated)
5942 method = ((MonoMethodInflated*)method)->declaring;
5943 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
5944 if (aux && aux->param_defaults) {
5945 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
5946 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
5948 return;
5951 methodt = &klass->image->tables [MONO_TABLE_METHOD];
5952 paramt = &klass->image->tables [MONO_TABLE_PARAM];
5953 constt = &image->tables [MONO_TABLE_CONSTANT];
5955 idx = mono_method_get_index (method) - 1;
5956 g_assert (idx != -1);
5958 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
5959 if (idx + 1 < methodt->rows)
5960 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
5961 else
5962 lastp = paramt->rows + 1;
5964 for (i = param_index; i < lastp; ++i) {
5965 guint32 paramseq;
5967 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
5968 paramseq = param_cols [MONO_PARAM_SEQUENCE];
5970 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT)
5971 continue;
5973 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
5974 if (!crow) {
5975 continue;
5978 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
5979 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
5980 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
5983 return;
5986 static MonoObject *
5987 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
5989 void *retval;
5990 MonoClass *klass;
5991 MonoObject *object;
5992 MonoType *basetype = type;
5994 if (!blob)
5995 return NULL;
5997 klass = mono_class_from_mono_type (type);
5998 if (klass->valuetype) {
5999 object = mono_object_new (domain, klass);
6000 retval = ((gchar *) object + sizeof (MonoObject));
6001 if (klass->enumtype)
6002 basetype = klass->enum_basetype;
6003 } else {
6004 retval = &object;
6007 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
6008 return object;
6009 else
6010 return NULL;
6013 static int
6014 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
6015 int found_sep;
6016 char *s;
6018 memset (assembly, 0, sizeof (MonoAssemblyName));
6019 assembly->name = p;
6020 assembly->culture = "";
6021 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
6023 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
6024 p++;
6025 found_sep = 0;
6026 while (g_ascii_isspace (*p) || *p == ',') {
6027 *p++ = 0;
6028 found_sep = 1;
6029 continue;
6031 /* failed */
6032 if (!found_sep)
6033 return 1;
6034 while (*p) {
6035 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
6036 p += 8;
6037 assembly->major = strtoul (p, &s, 10);
6038 if (s == p || *s != '.')
6039 return 1;
6040 p = ++s;
6041 assembly->minor = strtoul (p, &s, 10);
6042 if (s == p || *s != '.')
6043 return 1;
6044 p = ++s;
6045 assembly->build = strtoul (p, &s, 10);
6046 if (s == p || *s != '.')
6047 return 1;
6048 p = ++s;
6049 assembly->revision = strtoul (p, &s, 10);
6050 if (s == p)
6051 return 1;
6052 p = s;
6053 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
6054 p += 8;
6055 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
6056 assembly->culture = "";
6057 p += 7;
6058 } else {
6059 assembly->culture = p;
6060 while (*p && *p != ',') {
6061 p++;
6064 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
6065 p += 15;
6066 if (strncmp (p, "null", 4) == 0) {
6067 p += 4;
6068 } else {
6069 int len;
6070 gchar *start = p;
6071 while (*p && *p != ',') {
6072 p++;
6074 len = (p - start + 1);
6075 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
6076 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
6077 g_strlcpy (assembly->public_key_token, start, len);
6079 } else {
6080 while (*p && *p != ',')
6081 p++;
6083 found_sep = 0;
6084 while (g_ascii_isspace (*p) || *p == ',') {
6085 *p++ = 0;
6086 found_sep = 1;
6087 continue;
6089 /* failed */
6090 if (!found_sep)
6091 return 1;
6094 return 0;
6098 * mono_reflection_parse_type:
6099 * @name: type name
6101 * Parse a type name as accepted by the GetType () method and output the info
6102 * extracted in the info structure.
6103 * the name param will be mangled, so, make a copy before passing it to this function.
6104 * The fields in info will be valid until the memory pointed to by name is valid.
6106 * See also mono_type_get_name () below.
6108 * Returns: 0 on parse error.
6110 static int
6111 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
6112 MonoTypeNameParse *info)
6114 char *start, *p, *w, *temp, *last_point, *startn;
6115 int in_modifiers = 0;
6116 int isbyref = 0, rank, arity = 0, i;
6118 start = p = w = name;
6120 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
6121 info->name = info->name_space = NULL;
6122 info->nested = NULL;
6123 info->modifiers = NULL;
6124 info->type_arguments = NULL;
6126 /* last_point separates the namespace from the name */
6127 last_point = NULL;
6129 while (*p) {
6130 switch (*p) {
6131 case '+':
6132 *p = 0; /* NULL terminate the name */
6133 startn = p + 1;
6134 info->nested = g_list_append (info->nested, startn);
6135 /* we have parsed the nesting namespace + name */
6136 if (info->name)
6137 break;
6138 if (last_point) {
6139 info->name_space = start;
6140 *last_point = 0;
6141 info->name = last_point + 1;
6142 } else {
6143 info->name_space = (char *)"";
6144 info->name = start;
6146 break;
6147 case '.':
6148 last_point = p;
6149 break;
6150 case '\\':
6151 ++p;
6152 break;
6153 case '&':
6154 case '*':
6155 case '[':
6156 case ',':
6157 case ']':
6158 in_modifiers = 1;
6159 break;
6160 case '`':
6161 ++p;
6162 i = strtol (p, &temp, 10);
6163 arity += i;
6164 if (p == temp)
6165 return 0;
6166 p = temp-1;
6167 break;
6168 default:
6169 break;
6171 if (in_modifiers)
6172 break;
6173 // *w++ = *p++;
6174 p++;
6177 if (!info->name) {
6178 if (last_point) {
6179 info->name_space = start;
6180 *last_point = 0;
6181 info->name = last_point + 1;
6182 } else {
6183 info->name_space = (char *)"";
6184 info->name = start;
6187 while (*p) {
6188 switch (*p) {
6189 case '&':
6190 if (isbyref) /* only one level allowed by the spec */
6191 return 0;
6192 isbyref = 1;
6193 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
6194 *p++ = 0;
6195 break;
6196 case '*':
6197 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
6198 *p++ = 0;
6199 break;
6200 case '[':
6201 if (arity != 0) {
6202 *p++ = 0;
6203 info->type_arguments = g_ptr_array_new ();
6204 for (i = 0; i < arity; i++) {
6205 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
6206 gboolean fqname = FALSE;
6208 g_ptr_array_add (info->type_arguments, subinfo);
6210 if (*p == '[') {
6211 p++;
6212 fqname = TRUE;
6215 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
6216 return 0;
6218 if (fqname) {
6219 char *aname;
6221 if (*p != ',')
6222 return 0;
6223 *p++ = 0;
6225 aname = p;
6226 while (*p && (*p != ']'))
6227 p++;
6229 if (*p != ']')
6230 return 0;
6232 *p++ = 0;
6233 while (*aname) {
6234 if (g_ascii_isspace (*aname)) {
6235 ++aname;
6236 continue;
6238 break;
6240 if (!*aname ||
6241 !assembly_name_to_aname (&subinfo->assembly, aname))
6242 return 0;
6245 if (i + 1 < arity) {
6246 if (*p != ',')
6247 return 0;
6248 } else {
6249 if (*p != ']')
6250 return 0;
6252 *p++ = 0;
6255 arity = 0;
6256 break;
6258 rank = 1;
6259 *p++ = 0;
6260 while (*p) {
6261 if (*p == ']')
6262 break;
6263 if (*p == ',')
6264 rank++;
6265 else if (*p != '*') /* '*' means unknown lower bound */
6266 return 0;
6267 ++p;
6269 if (*p++ != ']')
6270 return 0;
6271 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
6272 break;
6273 case ']':
6274 if (is_recursed)
6275 goto end;
6276 return 0;
6277 case ',':
6278 if (is_recursed)
6279 goto end;
6280 *p++ = 0;
6281 while (*p) {
6282 if (g_ascii_isspace (*p)) {
6283 ++p;
6284 continue;
6286 break;
6288 if (!*p)
6289 return 0; /* missing assembly name */
6290 if (!assembly_name_to_aname (&info->assembly, p))
6291 return 0;
6292 break;
6293 default:
6294 return 0;
6296 if (info->assembly.name)
6297 break;
6299 // *w = 0; /* terminate class name */
6300 end:
6301 if (!info->name || !*info->name)
6302 return 0;
6303 if (endptr)
6304 *endptr = p;
6305 /* add other consistency checks */
6306 return 1;
6310 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
6312 return _mono_reflection_parse_type (name, NULL, FALSE, info);
6315 static MonoType*
6316 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
6318 gboolean type_resolve = FALSE;
6319 MonoType *type;
6321 if (info->assembly.name) {
6322 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
6323 if (!assembly) {
6324 /* then we must load the assembly ourselve - see #60439 */
6325 assembly = mono_assembly_load (&info->assembly, NULL, NULL);
6326 if (!assembly)
6327 return NULL;
6329 image = assembly->image;
6330 } else if (!image) {
6331 image = mono_defaults.corlib;
6334 type = mono_reflection_get_type (image, info, ignorecase, &type_resolve);
6335 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
6336 image = mono_defaults.corlib;
6337 type = mono_reflection_get_type (image, info, ignorecase, &type_resolve);
6340 return type;
6343 static MonoType*
6344 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
6346 MonoClass *klass;
6347 GList *mod;
6348 int modval;
6350 if (!image)
6351 image = mono_defaults.corlib;
6353 if (ignorecase)
6354 klass = mono_class_from_name_case (image, info->name_space, info->name);
6355 else
6356 klass = mono_class_from_name (image, info->name_space, info->name);
6357 if (!klass)
6358 return NULL;
6359 for (mod = info->nested; mod; mod = mod->next) {
6360 GList *nested;
6362 mono_class_init (klass);
6363 nested = klass->nested_classes;
6364 klass = NULL;
6365 while (nested) {
6366 klass = nested->data;
6367 if (ignorecase) {
6368 if (g_strcasecmp (klass->name, mod->data) == 0)
6369 break;
6370 } else {
6371 if (strcmp (klass->name, mod->data) == 0)
6372 break;
6374 klass = NULL;
6375 nested = nested->next;
6377 if (!klass)
6378 break;
6380 if (!klass)
6381 return NULL;
6382 mono_class_init (klass);
6384 if (info->type_arguments) {
6385 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
6386 MonoReflectionType *the_type;
6387 MonoType *instance;
6388 int i;
6390 for (i = 0; i < info->type_arguments->len; i++) {
6391 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
6393 type_args [i] = _mono_reflection_get_type_from_info (subinfo, image, ignorecase);
6394 if (!type_args [i]) {
6395 g_free (type_args);
6396 return NULL;
6400 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
6402 instance = mono_reflection_bind_generic_parameters (
6403 the_type, info->type_arguments->len, type_args);
6405 if (!instance) {
6406 g_free (type_args);
6407 return NULL;
6410 klass = mono_class_from_mono_type (instance);
6413 for (mod = info->modifiers; mod; mod = mod->next) {
6414 modval = GPOINTER_TO_UINT (mod->data);
6415 if (!modval) { /* byref: must be last modifier */
6416 return &klass->this_arg;
6417 } else if (modval == -1) {
6418 klass = mono_ptr_class_get (&klass->byval_arg);
6419 } else { /* array rank */
6420 klass = mono_array_class_get (klass, modval);
6422 mono_class_init (klass);
6425 return &klass->byval_arg;
6429 * mono_reflection_get_type:
6430 * @image: a metadata context
6431 * @info: type description structure
6432 * @ignorecase: flag for case-insensitive string compares
6433 * @type_resolve: whenever type resolve was already tried
6435 * Build a MonoType from the type description in @info.
6439 MonoType*
6440 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
6442 MonoType *type;
6443 MonoReflectionAssembly *assembly;
6444 GString *fullName;
6445 GList *mod;
6447 type = mono_reflection_get_type_internal (image, info, ignorecase);
6448 if (type)
6449 return type;
6450 if (!mono_domain_has_type_resolve (mono_domain_get ()))
6451 return NULL;
6453 if (type_resolve) {
6454 if (*type_resolve)
6455 return NULL;
6456 else
6457 *type_resolve = TRUE;
6460 /* Reconstruct the type name */
6461 fullName = g_string_new ("");
6462 if (info->name_space && (info->name_space [0] != '\0'))
6463 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
6464 else
6465 g_string_printf (fullName, info->name);
6466 for (mod = info->nested; mod; mod = mod->next)
6467 g_string_append_printf (fullName, "+%s", (char*)mod->data);
6469 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
6470 if (assembly) {
6471 if (assembly->assembly->dynamic) {
6472 /* Enumerate all modules */
6473 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
6474 int i;
6476 type = NULL;
6477 if (abuilder->modules) {
6478 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
6479 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
6480 type = mono_reflection_get_type_internal (&mb->dynamic_image->image, info, ignorecase);
6481 if (type)
6482 break;
6486 if (!type && abuilder->loaded_modules) {
6487 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
6488 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
6489 type = mono_reflection_get_type_internal (mod->image, info, ignorecase);
6490 if (type)
6491 break;
6495 else
6496 type = mono_reflection_get_type_internal (assembly->assembly->image,
6497 info, ignorecase);
6499 g_string_free (fullName, TRUE);
6500 return type;
6503 static void
6504 free_type_info (MonoTypeNameParse *info)
6506 g_list_free (info->modifiers);
6507 g_list_free (info->nested);
6509 if (info->type_arguments) {
6510 int i;
6512 for (i = 0; i < info->type_arguments->len; i++) {
6513 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
6515 free_type_info (subinfo);
6518 g_ptr_array_free (info->type_arguments, TRUE);
6523 * mono_reflection_type_from_name:
6524 * @name: type name.
6525 * @image: a metadata context (can be NULL).
6527 * Retrieves a MonoType from its @name. If the name is not fully qualified,
6528 * it defaults to get the type from @image or, if @image is NULL or loading
6529 * from it fails, uses corlib.
6532 MonoType*
6533 mono_reflection_type_from_name (char *name, MonoImage *image)
6535 MonoType *type = NULL;
6536 MonoTypeNameParse info;
6537 char *tmp;
6539 /* Make a copy since parse_type modifies its argument */
6540 tmp = g_strdup (name);
6542 /*g_print ("requested type %s\n", str);*/
6543 if (mono_reflection_parse_type (tmp, &info)) {
6544 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
6547 g_free (tmp);
6548 free_type_info (&info);
6549 return type;
6553 * mono_reflection_get_token:
6555 * Return the metadata token of OBJ which should be an object
6556 * representing a metadata element.
6558 guint32
6559 mono_reflection_get_token (MonoObject *obj)
6561 MonoClass *klass;
6562 guint32 token = 0;
6564 klass = obj->vtable->klass;
6566 if (strcmp (klass->name, "MethodBuilder") == 0) {
6567 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
6569 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6570 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
6571 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
6573 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6574 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
6575 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
6576 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
6577 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
6578 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
6579 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
6580 } else if (strcmp (klass->name, "MonoType") == 0) {
6581 MonoReflectionType *tb = (MonoReflectionType *)obj;
6582 token = mono_class_from_mono_type (tb->type)->type_token;
6583 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
6584 strcmp (klass->name, "MonoMethod") == 0 ||
6585 strcmp (klass->name, "MonoGenericMethod") == 0 ||
6586 strcmp (klass->name, "MonoGenericCMethod") == 0) {
6587 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
6588 if (m->method->is_inflated) {
6589 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
6590 return inflated->declaring->token;
6591 } else {
6592 token = m->method->token;
6594 } else if (strcmp (klass->name, "MonoField") == 0) {
6595 MonoReflectionField *f = (MonoReflectionField*)obj;
6597 if (f->field->generic_info && f->field->generic_info->reflection_info)
6598 return mono_reflection_get_token (f->field->generic_info->reflection_info);
6600 token = mono_class_get_field_token (f->field);
6601 } else if (strcmp (klass->name, "MonoProperty") == 0) {
6602 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
6604 token = mono_class_get_property_token (p->property);
6605 } else if (strcmp (klass->name, "MonoEvent") == 0) {
6606 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
6608 token = mono_class_get_event_token (p->event);
6609 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
6610 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
6612 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
6613 } else if (strcmp (klass->name, "Module") == 0) {
6614 MonoReflectionModule *m = (MonoReflectionModule*)obj;
6616 token = m->token;
6617 } else if (strcmp (klass->name, "Assembly") == 0) {
6618 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
6619 } else {
6620 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
6621 MonoException *ex = mono_get_exception_not_implemented (msg);
6622 g_free (msg);
6623 mono_raise_exception (ex);
6626 return token;
6629 static void*
6630 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
6632 int slen, type = t->type;
6633 MonoClass *tklass = t->data.klass;
6635 handle_enum:
6636 switch (type) {
6637 case MONO_TYPE_U1:
6638 case MONO_TYPE_I1:
6639 case MONO_TYPE_BOOLEAN: {
6640 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
6641 *bval = *p;
6642 *end = p + 1;
6643 return bval;
6645 case MONO_TYPE_CHAR:
6646 case MONO_TYPE_U2:
6647 case MONO_TYPE_I2: {
6648 guint16 *val = g_malloc (sizeof (guint16));
6649 *val = read16 (p);
6650 *end = p + 2;
6651 return val;
6653 #if SIZEOF_VOID_P == 4
6654 case MONO_TYPE_U:
6655 case MONO_TYPE_I:
6656 #endif
6657 case MONO_TYPE_R4:
6658 case MONO_TYPE_U4:
6659 case MONO_TYPE_I4: {
6660 guint32 *val = g_malloc (sizeof (guint32));
6661 *val = read32 (p);
6662 *end = p + 4;
6663 return val;
6665 #if SIZEOF_VOID_P == 8
6666 case MONO_TYPE_U: /* error out instead? this should probably not happen */
6667 case MONO_TYPE_I:
6668 #endif
6669 case MONO_TYPE_R8:
6670 case MONO_TYPE_U8:
6671 case MONO_TYPE_I8: {
6672 guint64 *val = g_malloc (sizeof (guint64));
6673 *val = read64 (p);
6674 *end = p + 8;
6675 return val;
6677 case MONO_TYPE_VALUETYPE:
6678 if (t->data.klass->enumtype) {
6679 type = t->data.klass->enum_basetype->type;
6680 goto handle_enum;
6681 } else {
6682 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
6684 break;
6685 case MONO_TYPE_STRING:
6686 if (*p == (char)0xFF) {
6687 *end = p + 1;
6688 return NULL;
6690 slen = mono_metadata_decode_value (p, &p);
6691 *end = p + slen;
6692 return mono_string_new_len (mono_domain_get (), p, slen);
6693 case MONO_TYPE_CLASS: {
6694 char *n;
6695 MonoType *t;
6696 if (*p == (char)0xFF) {
6697 *end = p + 1;
6698 return NULL;
6700 handle_type:
6701 slen = mono_metadata_decode_value (p, &p);
6702 n = g_memdup (p, slen + 1);
6703 n [slen] = 0;
6704 t = mono_reflection_type_from_name (n, image);
6705 if (!t)
6706 g_warning ("Cannot load type '%s'", n);
6707 g_free (n);
6708 *end = p + slen;
6709 if (t)
6710 return mono_type_get_object (mono_domain_get (), t);
6711 else
6712 return NULL;
6714 case MONO_TYPE_OBJECT: {
6715 char subt = *p++;
6716 MonoObject *obj;
6717 MonoClass *subc = NULL;
6718 void *val;
6720 if (subt == 0x50) {
6721 goto handle_type;
6722 } else if (subt == 0x0E) {
6723 type = MONO_TYPE_STRING;
6724 goto handle_enum;
6725 } else if (subt == 0x1D) {
6726 MonoType simple_type = {{0}};
6727 int etype = *p;
6728 p ++;
6730 type = MONO_TYPE_SZARRAY;
6731 simple_type.type = etype;
6732 tklass = mono_class_from_mono_type (&simple_type);
6733 goto handle_enum;
6734 } else if (subt == 0x55) {
6735 char *n;
6736 MonoType *t;
6737 slen = mono_metadata_decode_value (p, &p);
6738 n = g_memdup (p, slen + 1);
6739 n [slen] = 0;
6740 t = mono_reflection_type_from_name (n, image);
6741 if (!t)
6742 g_error ("Cannot load type '%s'", n);
6743 g_free (n);
6744 p += slen;
6745 subc = mono_class_from_mono_type (t);
6746 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
6747 MonoType simple_type = {{0}};
6748 simple_type.type = subt;
6749 subc = mono_class_from_mono_type (&simple_type);
6750 } else {
6751 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
6753 val = load_cattr_value (image, &subc->byval_arg, p, end);
6754 obj = mono_object_new (mono_domain_get (), subc);
6755 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
6756 g_free (val);
6757 return obj;
6759 case MONO_TYPE_SZARRAY: {
6760 MonoArray *arr;
6761 guint32 i, alen, basetype;
6762 alen = read32 (p);
6763 p += 4;
6764 if (alen == 0xffffffff) {
6765 *end = p;
6766 return NULL;
6768 arr = mono_array_new (mono_domain_get(), tklass, alen);
6769 basetype = tklass->byval_arg.type;
6770 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
6771 basetype = tklass->enum_basetype->type;
6772 switch (basetype)
6774 case MONO_TYPE_U1:
6775 case MONO_TYPE_I1:
6776 case MONO_TYPE_BOOLEAN:
6777 for (i = 0; i < alen; i++) {
6778 MonoBoolean val = *p++;
6779 mono_array_set (arr, MonoBoolean, i, val);
6781 break;
6782 case MONO_TYPE_CHAR:
6783 case MONO_TYPE_U2:
6784 case MONO_TYPE_I2:
6785 for (i = 0; i < alen; i++) {
6786 guint16 val = read16 (p);
6787 mono_array_set (arr, guint16, i, val);
6788 p += 2;
6790 break;
6791 case MONO_TYPE_R4:
6792 case MONO_TYPE_U4:
6793 case MONO_TYPE_I4:
6794 for (i = 0; i < alen; i++) {
6795 guint32 val = read32 (p);
6796 mono_array_set (arr, guint32, i, val);
6797 p += 4;
6799 break;
6800 case MONO_TYPE_R8:
6801 case MONO_TYPE_U8:
6802 case MONO_TYPE_I8:
6803 for (i = 0; i < alen; i++) {
6804 guint64 val = read64 (p);
6805 mono_array_set (arr, guint64, i, val);
6806 p += 8;
6808 break;
6809 case MONO_TYPE_CLASS:
6810 case MONO_TYPE_OBJECT:
6811 case MONO_TYPE_STRING:
6812 for (i = 0; i < alen; i++) {
6813 MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
6814 mono_array_setref (arr, i, item);
6816 break;
6817 default:
6818 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
6820 *end=p;
6821 return arr;
6823 default:
6824 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
6826 return NULL;
6829 static MonoObject*
6830 create_cattr_typed_arg (MonoType *t, MonoObject *val)
6832 static MonoClass *klass;
6833 static MonoMethod *ctor;
6834 MonoObject *retval;
6835 void *params [2], *unboxed;
6837 if (!klass)
6838 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
6839 if (!ctor)
6840 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
6842 params [0] = mono_type_get_object (mono_domain_get (), t);
6843 params [1] = val;
6844 retval = mono_object_new (mono_domain_get (), klass);
6845 unboxed = mono_object_unbox (retval);
6846 mono_runtime_invoke (ctor, unboxed, params, NULL);
6848 return retval;
6851 static MonoObject*
6852 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
6854 static MonoClass *klass;
6855 static MonoMethod *ctor;
6856 MonoObject *retval;
6857 void *unboxed, *params [2];
6859 if (!klass)
6860 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
6861 if (!ctor)
6862 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
6864 params [0] = minfo;
6865 params [1] = typedarg;
6866 retval = mono_object_new (mono_domain_get (), klass);
6867 unboxed = mono_object_unbox (retval);
6868 mono_runtime_invoke (ctor, unboxed, params, NULL);
6870 return retval;
6873 static gboolean
6874 type_is_reference (MonoType *type)
6876 switch (type->type) {
6877 case MONO_TYPE_BOOLEAN:
6878 case MONO_TYPE_CHAR:
6879 case MONO_TYPE_U:
6880 case MONO_TYPE_I:
6881 case MONO_TYPE_U1:
6882 case MONO_TYPE_I1:
6883 case MONO_TYPE_U2:
6884 case MONO_TYPE_I2:
6885 case MONO_TYPE_U4:
6886 case MONO_TYPE_I4:
6887 case MONO_TYPE_U8:
6888 case MONO_TYPE_I8:
6889 case MONO_TYPE_R8:
6890 case MONO_TYPE_R4:
6891 case MONO_TYPE_VALUETYPE:
6892 return FALSE;
6893 default:
6894 return TRUE;
6898 static void
6899 free_param_data (MonoMethodSignature *sig, void **params) {
6900 int i;
6901 for (i = 0; i < sig->param_count; ++i) {
6902 if (!type_is_reference (sig->params [i]))
6903 g_free (params [i]);
6908 * Find the field index in the metadata FieldDef table.
6910 static guint32
6911 find_field_index (MonoClass *klass, MonoClassField *field) {
6912 int i;
6914 for (i = 0; i < klass->field.count; ++i) {
6915 if (field == &klass->fields [i])
6916 return klass->field.first + 1 + i;
6918 return 0;
6922 * Find the property index in the metadata Property table.
6924 static guint32
6925 find_property_index (MonoClass *klass, MonoProperty *property) {
6926 int i;
6928 for (i = 0; i < klass->property.count; ++i) {
6929 if (property == &klass->properties [i])
6930 return klass->property.first + 1 + i;
6932 return 0;
6936 * Find the event index in the metadata Event table.
6938 static guint32
6939 find_event_index (MonoClass *klass, MonoEvent *event) {
6940 int i;
6942 for (i = 0; i < klass->event.count; ++i) {
6943 if (event == &klass->events [i])
6944 return klass->event.first + 1 + i;
6946 return 0;
6949 static MonoObject*
6950 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
6952 const char *p = (const char*)data;
6953 const char *named;
6954 guint32 i, j, num_named;
6955 MonoObject *attr;
6956 void **params;
6958 mono_class_init (method->klass);
6960 if (len == 0) {
6961 attr = mono_object_new (mono_domain_get (), method->klass);
6962 mono_runtime_invoke (method, attr, NULL, NULL);
6963 return attr;
6966 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
6967 return NULL;
6969 /*g_print ("got attr %s\n", method->klass->name);*/
6971 /* Allocate using alloca so it gets GC tracking */
6972 params = alloca (mono_method_signature (method)->param_count * sizeof (void*));
6974 /* skip prolog */
6975 p += 2;
6976 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
6977 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
6980 named = p;
6981 attr = mono_object_new (mono_domain_get (), method->klass);
6982 mono_runtime_invoke (method, attr, params, NULL);
6983 free_param_data (method->signature, params);
6984 num_named = read16 (named);
6985 named += 2;
6986 for (j = 0; j < num_named; j++) {
6987 gint name_len;
6988 char *name, named_type, data_type;
6989 named_type = *named++;
6990 data_type = *named++; /* type of data */
6991 if (data_type == MONO_TYPE_SZARRAY)
6992 data_type = *named++;
6993 if (data_type == MONO_TYPE_ENUM) {
6994 gint type_len;
6995 char *type_name;
6996 type_len = mono_metadata_decode_blob_size (named, &named);
6997 type_name = g_malloc (type_len + 1);
6998 memcpy (type_name, named, type_len);
6999 type_name [type_len] = 0;
7000 named += type_len;
7001 /* FIXME: lookup the type and check type consistency */
7002 g_free (type_name);
7004 name_len = mono_metadata_decode_blob_size (named, &named);
7005 name = g_malloc (name_len + 1);
7006 memcpy (name, named, name_len);
7007 name [name_len] = 0;
7008 named += name_len;
7009 if (named_type == 0x53) {
7010 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
7011 void *val = load_cattr_value (image, field->type, named, &named);
7012 mono_field_set_value (attr, field, val);
7013 if (!type_is_reference (field->type))
7014 g_free (val);
7015 } else if (named_type == 0x54) {
7016 MonoProperty *prop;
7017 void *pparams [1];
7018 MonoType *prop_type;
7020 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
7021 /* can we have more that 1 arg in a custom attr named property? */
7022 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7023 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7024 pparams [0] = load_cattr_value (image, prop_type, named, &named);
7025 mono_property_set_value (prop, attr, pparams, NULL);
7026 if (!type_is_reference (prop_type))
7027 g_free (pparams [0]);
7029 g_free (name);
7032 return attr;
7035 static MonoObject*
7036 create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7038 MonoArray *typedargs, *namedargs;
7039 MonoClass *attrklass;
7040 static MonoClass *klass;
7041 static MonoMethod *ctor;
7042 MonoDomain *domain;
7043 MonoObject *attr;
7044 const char *p = (const char*)data;
7045 const char *named;
7046 guint32 i, j, num_named;
7047 void *params [3];
7049 mono_class_init (method->klass);
7051 if (!klass)
7052 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
7053 if (!ctor)
7054 ctor = mono_class_get_method_from_name (klass, ".ctor", 3);
7056 domain = mono_domain_get ();
7057 if (len == 0) {
7058 /* This is for Attributes with no parameters */
7059 attr = mono_object_new (domain, klass);
7060 params [0] = mono_method_get_object (domain, method, NULL);
7061 params [1] = params [2] = NULL;
7062 mono_runtime_invoke (method, attr, params, NULL);
7063 return attr;
7066 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7067 return NULL;
7069 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
7071 /* skip prolog */
7072 p += 2;
7073 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7074 MonoObject *obj, *typedarg;
7075 void *val;
7077 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7078 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
7079 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
7080 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
7081 mono_array_setref (typedargs, i, typedarg);
7083 if (!type_is_reference (mono_method_signature (method)->params [i]))
7084 g_free (val);
7087 named = p;
7088 num_named = read16 (named);
7089 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
7090 named += 2;
7091 attrklass = method->klass;
7092 for (j = 0; j < num_named; j++) {
7093 gint name_len;
7094 char *name, named_type, data_type;
7095 named_type = *named++;
7096 data_type = *named++; /* type of data */
7097 if (data_type == MONO_TYPE_SZARRAY)
7098 data_type = *named++;
7099 if (data_type == MONO_TYPE_ENUM) {
7100 gint type_len;
7101 char *type_name;
7102 type_len = mono_metadata_decode_blob_size (named, &named);
7103 type_name = g_malloc (type_len + 1);
7104 memcpy (type_name, named, type_len);
7105 type_name [type_len] = 0;
7106 named += type_len;
7107 /* FIXME: lookup the type and check type consistency */
7108 g_free (type_name);
7110 name_len = mono_metadata_decode_blob_size (named, &named);
7111 name = g_malloc (name_len + 1);
7112 memcpy (name, named, name_len);
7113 name [name_len] = 0;
7114 named += name_len;
7115 if (named_type == 0x53) {
7116 MonoObject *obj, *typedarg, *namedarg;
7117 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
7118 void *minfo, *val = load_cattr_value (image, field->type, named, &named);
7120 minfo = mono_field_get_object (domain, NULL, field);
7121 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
7122 typedarg = create_cattr_typed_arg (field->type, obj);
7123 namedarg = create_cattr_named_arg (minfo, typedarg);
7124 mono_array_setref (namedargs, j, namedarg);
7125 if (!type_is_reference (field->type))
7126 g_free (val);
7127 } else if (named_type == 0x54) {
7128 MonoObject *obj, *typedarg, *namedarg;
7129 MonoType *prop_type;
7130 void *val, *minfo;
7131 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
7133 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7134 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7135 minfo = mono_property_get_object (domain, NULL, prop);
7136 val = load_cattr_value (image, prop_type, named, &named);
7137 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
7138 typedarg = create_cattr_typed_arg (prop_type, obj);
7139 namedarg = create_cattr_named_arg (minfo, typedarg);
7140 mono_array_setref (namedargs, j, namedarg);
7141 if (!type_is_reference (prop_type))
7142 g_free (val);
7144 g_free (name);
7146 attr = mono_object_new (domain, klass);
7147 params [0] = mono_method_get_object (domain, method, NULL);
7148 params [1] = typedargs;
7149 params [2] = namedargs;
7150 mono_runtime_invoke (ctor, attr, params, NULL);
7151 return attr;
7154 MonoArray*
7155 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
7157 MonoArray *result;
7158 MonoClass *klass;
7159 MonoObject *attr;
7160 int i;
7162 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
7163 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
7164 for (i = 0; i < cinfo->num_attrs; ++i) {
7165 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7166 mono_array_setref (result, i, attr);
7168 return result;
7171 static MonoArray*
7172 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass)
7174 MonoArray *result;
7175 MonoObject *attr;
7176 MonoClass *klass;
7177 int i, n;
7179 n = 0;
7180 for (i = 0; i < cinfo->num_attrs; ++i) {
7181 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
7182 n ++;
7185 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
7186 result = mono_array_new (mono_domain_get (), klass, n);
7187 n = 0;
7188 for (i = 0; i < cinfo->num_attrs; ++i) {
7189 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
7190 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7191 mono_array_setref (result, n, attr);
7192 n ++;
7195 return result;
7198 static MonoArray*
7199 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
7201 MonoArray *result;
7202 static MonoClass *klass;
7203 MonoObject *attr;
7204 int i;
7206 if (!klass)
7207 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
7209 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
7210 for (i = 0; i < cinfo->num_attrs; ++i) {
7211 attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7212 mono_array_setref (result, i, attr);
7214 return result;
7217 MonoCustomAttrInfo*
7218 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
7220 guint32 mtoken, i, len;
7221 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
7222 MonoTableInfo *ca;
7223 MonoCustomAttrInfo *ainfo;
7224 GList *tmp, *list = NULL;
7225 const char *data;
7227 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
7229 i = mono_metadata_custom_attrs_from_index (image, idx);
7230 if (!i)
7231 return NULL;
7232 i --;
7233 while (i < ca->rows) {
7234 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
7235 break;
7236 list = g_list_prepend (list, GUINT_TO_POINTER (i));
7237 ++i;
7239 len = g_list_length (list);
7240 if (!len)
7241 return NULL;
7242 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
7243 ainfo->num_attrs = len;
7244 ainfo->image = image;
7245 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
7246 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
7247 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
7248 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
7249 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
7250 mtoken |= MONO_TOKEN_METHOD_DEF;
7251 break;
7252 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
7253 mtoken |= MONO_TOKEN_MEMBER_REF;
7254 break;
7255 default:
7256 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
7257 break;
7259 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
7260 if (!ainfo->attrs [i].ctor)
7261 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
7262 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
7263 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
7264 ainfo->attrs [i].data = (guchar*)data;
7266 g_list_free (list);
7268 return ainfo;
7271 MonoCustomAttrInfo*
7272 mono_custom_attrs_from_method (MonoMethod *method)
7274 MonoCustomAttrInfo *cinfo;
7275 guint32 idx;
7277 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
7278 return cinfo;
7279 idx = mono_method_get_index (method);
7280 idx <<= MONO_CUSTOM_ATTR_BITS;
7281 idx |= MONO_CUSTOM_ATTR_METHODDEF;
7282 return mono_custom_attrs_from_index (method->klass->image, idx);
7285 MonoCustomAttrInfo*
7286 mono_custom_attrs_from_class (MonoClass *klass)
7288 MonoCustomAttrInfo *cinfo;
7289 guint32 idx;
7291 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
7292 return cinfo;
7293 idx = mono_metadata_token_index (klass->type_token);
7294 idx <<= MONO_CUSTOM_ATTR_BITS;
7295 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
7296 return mono_custom_attrs_from_index (klass->image, idx);
7299 MonoCustomAttrInfo*
7300 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
7302 MonoCustomAttrInfo *cinfo;
7303 guint32 idx;
7305 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
7306 return cinfo;
7307 idx = 1; /* there is only one assembly */
7308 idx <<= MONO_CUSTOM_ATTR_BITS;
7309 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
7310 return mono_custom_attrs_from_index (assembly->image, idx);
7313 static MonoCustomAttrInfo*
7314 mono_custom_attrs_from_module (MonoImage *image)
7316 MonoCustomAttrInfo *cinfo;
7317 guint32 idx;
7319 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
7320 return cinfo;
7321 idx = 1; /* there is only one module */
7322 idx <<= MONO_CUSTOM_ATTR_BITS;
7323 idx |= MONO_CUSTOM_ATTR_MODULE;
7324 return mono_custom_attrs_from_index (image, idx);
7327 MonoCustomAttrInfo*
7328 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
7330 MonoCustomAttrInfo *cinfo;
7331 guint32 idx;
7333 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
7334 return cinfo;
7335 idx = find_property_index (klass, property);
7336 idx <<= MONO_CUSTOM_ATTR_BITS;
7337 idx |= MONO_CUSTOM_ATTR_PROPERTY;
7338 return mono_custom_attrs_from_index (klass->image, idx);
7341 MonoCustomAttrInfo*
7342 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
7344 MonoCustomAttrInfo *cinfo;
7345 guint32 idx;
7347 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
7348 return cinfo;
7349 idx = find_event_index (klass, event);
7350 idx <<= MONO_CUSTOM_ATTR_BITS;
7351 idx |= MONO_CUSTOM_ATTR_EVENT;
7352 return mono_custom_attrs_from_index (klass->image, idx);
7355 MonoCustomAttrInfo*
7356 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
7358 MonoCustomAttrInfo *cinfo;
7359 guint32 idx;
7361 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
7362 return cinfo;
7363 idx = find_field_index (klass, field);
7364 idx <<= MONO_CUSTOM_ATTR_BITS;
7365 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
7366 return mono_custom_attrs_from_index (klass->image, idx);
7369 MonoCustomAttrInfo*
7370 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
7372 MonoTableInfo *ca;
7373 guint32 i, idx, method_index;
7374 guint32 param_list, param_last, param_pos, found;
7375 MonoImage *image;
7376 MonoReflectionMethodAux *aux;
7378 if (method->klass->image->dynamic) {
7379 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7380 if (!aux || !aux->param_cattr)
7381 return NULL;
7382 return aux->param_cattr [param];
7385 image = method->klass->image;
7386 method_index = mono_method_get_index (method);
7387 ca = &image->tables [MONO_TABLE_METHOD];
7389 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
7390 if (method_index == ca->rows) {
7391 ca = &image->tables [MONO_TABLE_PARAM];
7392 param_last = ca->rows + 1;
7393 } else {
7394 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
7395 ca = &image->tables [MONO_TABLE_PARAM];
7397 found = FALSE;
7398 for (i = param_list; i < param_last; ++i) {
7399 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
7400 if (param_pos == param) {
7401 found = TRUE;
7402 break;
7405 if (!found)
7406 return NULL;
7407 idx = i;
7408 idx <<= MONO_CUSTOM_ATTR_BITS;
7409 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
7410 return mono_custom_attrs_from_index (image, idx);
7413 gboolean
7414 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
7416 int i;
7417 MonoClass *klass;
7418 for (i = 0; i < ainfo->num_attrs; ++i) {
7419 klass = ainfo->attrs [i].ctor->klass;
7420 if (mono_class_has_parent (klass, attr_klass))
7421 return TRUE;
7423 return FALSE;
7426 MonoObject*
7427 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
7429 int i, attr_index;
7430 MonoClass *klass;
7431 MonoArray *attrs;
7433 attr_index = -1;
7434 for (i = 0; i < ainfo->num_attrs; ++i) {
7435 klass = ainfo->attrs [i].ctor->klass;
7436 if (mono_class_has_parent (klass, attr_klass)) {
7437 attr_index = i;
7438 break;
7441 if (attr_index == -1)
7442 return NULL;
7444 attrs = mono_custom_attrs_construct (ainfo);
7445 if (attrs)
7446 return mono_array_get (attrs, MonoObject*, attr_index);
7447 else
7448 return NULL;
7452 * mono_reflection_get_custom_attrs_info:
7453 * @obj: a reflection object handle
7455 * Return the custom attribute info for attributes defined for the
7456 * reflection handle @obj. The objects.
7458 MonoCustomAttrInfo*
7459 mono_reflection_get_custom_attrs_info (MonoObject *obj)
7461 MonoClass *klass;
7462 MonoCustomAttrInfo *cinfo = NULL;
7464 klass = obj->vtable->klass;
7465 if (klass == mono_defaults.monotype_class) {
7466 MonoReflectionType *rtype = (MonoReflectionType*)obj;
7467 klass = mono_class_from_mono_type (rtype->type);
7468 cinfo = mono_custom_attrs_from_class (klass);
7469 } else if (strcmp ("Assembly", klass->name) == 0) {
7470 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
7471 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
7472 } else if (strcmp ("Module", klass->name) == 0) {
7473 MonoReflectionModule *module = (MonoReflectionModule*)obj;
7474 cinfo = mono_custom_attrs_from_module (module->image);
7475 } else if (strcmp ("MonoProperty", klass->name) == 0) {
7476 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
7477 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
7478 } else if (strcmp ("MonoEvent", klass->name) == 0) {
7479 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
7480 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
7481 } else if (strcmp ("MonoField", klass->name) == 0) {
7482 MonoReflectionField *rfield = (MonoReflectionField*)obj;
7483 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
7484 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
7485 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
7486 cinfo = mono_custom_attrs_from_method (rmethod->method);
7487 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
7488 MonoMethod *method = mono_get_inflated_method (((MonoReflectionMethod*)obj)->method);
7489 cinfo = mono_custom_attrs_from_method (method);
7490 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
7491 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
7492 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7493 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
7494 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
7495 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
7496 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
7497 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
7498 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
7499 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
7500 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
7501 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
7502 cinfo = mono_custom_attrs_from_builders (&mb->dynamic_image->image, mb->cattrs);
7503 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
7504 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
7505 cinfo = mono_custom_attrs_from_builders (cb->mhandle->klass->image, cb->cattrs);
7506 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
7507 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
7508 cinfo = mono_custom_attrs_from_builders (mb->mhandle->klass->image, mb->cattrs);
7509 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
7510 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
7511 cinfo = mono_custom_attrs_from_builders (&((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
7512 } else { /* handle other types here... */
7513 g_error ("get custom attrs not yet supported for %s", klass->name);
7516 return cinfo;
7520 * mono_reflection_get_custom_attrs_by_type:
7521 * @obj: a reflection object handle
7523 * Return an array with all the custom attributes defined of the
7524 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
7525 * of that type are returned. The objects are fully build.
7527 MonoArray*
7528 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass)
7530 MonoArray *result;
7531 MonoCustomAttrInfo *cinfo;
7533 cinfo = mono_reflection_get_custom_attrs_info (obj);
7534 if (cinfo) {
7535 if (attr_klass)
7536 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass);
7537 else
7538 result = mono_custom_attrs_construct (cinfo);
7539 if (!cinfo->cached)
7540 mono_custom_attrs_free (cinfo);
7541 } else {
7542 MonoClass *klass;
7543 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
7544 result = mono_array_new (mono_domain_get (), klass, 0);
7547 return result;
7551 * mono_reflection_get_custom_attrs:
7552 * @obj: a reflection object handle
7554 * Return an array with all the custom attributes defined of the
7555 * reflection handle @obj. The objects are fully build.
7557 MonoArray*
7558 mono_reflection_get_custom_attrs (MonoObject *obj)
7560 return mono_reflection_get_custom_attrs_by_type (obj, NULL);
7564 * mono_reflection_get_custom_attrs_data:
7565 * @obj: a reflection obj handle
7567 * Returns an array of System.Reflection.CustomAttributeData,
7568 * which include information about attributes reflected on
7569 * types loaded using the Reflection Only methods
7571 MonoArray*
7572 mono_reflection_get_custom_attrs_data (MonoObject *obj)
7574 MonoArray *result;
7575 MonoCustomAttrInfo *cinfo;
7577 cinfo = mono_reflection_get_custom_attrs_info (obj);
7578 if (cinfo) {
7579 result = mono_custom_attrs_data_construct (cinfo);
7580 if (!cinfo->cached)
7581 mono_custom_attrs_free (cinfo);
7582 } else {
7583 MonoClass *klass;
7584 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
7585 result = mono_array_new (mono_domain_get (), klass, 0);
7588 return result;
7592 * LOCKING: Assumes the loader lock is held.
7594 static MonoMethodSignature*
7595 parameters_to_signature (MonoMemPool *mp, MonoArray *parameters) {
7596 MonoMethodSignature *sig;
7597 int count, i;
7599 count = parameters? mono_array_length (parameters): 0;
7601 sig = mp_g_malloc0 (mp, sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
7602 sig->param_count = count;
7603 sig->sentinelpos = -1; /* FIXME */
7604 for (i = 0; i < count; ++i) {
7605 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
7606 sig->params [i] = pt->type;
7608 return sig;
7612 * LOCKING: Assumes the loader lock is held.
7614 static MonoMethodSignature*
7615 ctor_builder_to_signature (MonoMemPool *mp, MonoReflectionCtorBuilder *ctor) {
7616 MonoMethodSignature *sig;
7618 sig = parameters_to_signature (mp, ctor->parameters);
7619 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7620 sig->ret = &mono_defaults.void_class->byval_arg;
7621 return sig;
7625 * LOCKING: Assumes the loader lock is held.
7627 static MonoMethodSignature*
7628 method_builder_to_signature (MonoMemPool *mp, MonoReflectionMethodBuilder *method) {
7629 MonoMethodSignature *sig;
7631 sig = parameters_to_signature (mp, method->parameters);
7632 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7633 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
7634 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
7635 return sig;
7638 static MonoMethodSignature*
7639 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
7640 MonoMethodSignature *sig;
7642 sig = parameters_to_signature (NULL, method->parameters);
7643 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7644 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
7645 sig->generic_param_count = 0;
7646 return sig;
7649 static void
7650 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
7652 MonoClass *klass = mono_object_class (prop);
7653 if (strcmp (klass->name, "PropertyBuilder") == 0) {
7654 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
7655 *name = mono_string_to_utf8 (pb->name);
7656 *type = pb->type->type;
7657 } else {
7658 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
7659 *name = g_strdup (p->property->name);
7660 if (p->property->get)
7661 *type = mono_method_signature (p->property->get)->ret;
7662 else
7663 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
7667 static void
7668 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
7670 MonoClass *klass = mono_object_class (field);
7671 if (strcmp (klass->name, "FieldBuilder") == 0) {
7672 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
7673 *name = mono_string_to_utf8 (fb->name);
7674 *type = fb->type->type;
7675 } else {
7676 MonoReflectionField *f = (MonoReflectionField *)field;
7677 *name = g_strdup (f->field->name);
7678 *type = f->field->type;
7683 * Encode a value in a custom attribute stream of bytes.
7684 * The value to encode is either supplied as an object in argument val
7685 * (valuetypes are boxed), or as a pointer to the data in the
7686 * argument argval.
7687 * @type represents the type of the value
7688 * @buffer is the start of the buffer
7689 * @p the current position in the buffer
7690 * @buflen contains the size of the buffer and is used to return the new buffer size
7691 * if this needs to be realloced.
7692 * @retbuffer and @retp return the start and the position of the buffer
7694 static void
7695 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
7697 MonoTypeEnum simple_type;
7699 if ((p-buffer) + 10 >= *buflen) {
7700 char *newbuf;
7701 *buflen *= 2;
7702 newbuf = g_realloc (buffer, *buflen);
7703 p = newbuf + (p-buffer);
7704 buffer = newbuf;
7706 if (!argval)
7707 argval = ((char*)arg + sizeof (MonoObject));
7708 simple_type = type->type;
7709 handle_enum:
7710 switch (simple_type) {
7711 case MONO_TYPE_BOOLEAN:
7712 case MONO_TYPE_U1:
7713 case MONO_TYPE_I1:
7714 *p++ = *argval;
7715 break;
7716 case MONO_TYPE_CHAR:
7717 case MONO_TYPE_U2:
7718 case MONO_TYPE_I2:
7719 swap_with_size (p, argval, 2, 1);
7720 p += 2;
7721 break;
7722 case MONO_TYPE_U4:
7723 case MONO_TYPE_I4:
7724 case MONO_TYPE_R4:
7725 swap_with_size (p, argval, 4, 1);
7726 p += 4;
7727 break;
7728 case MONO_TYPE_U8:
7729 case MONO_TYPE_I8:
7730 case MONO_TYPE_R8:
7731 swap_with_size (p, argval, 8, 1);
7732 p += 8;
7733 break;
7734 case MONO_TYPE_VALUETYPE:
7735 if (type->data.klass->enumtype) {
7736 simple_type = type->data.klass->enum_basetype->type;
7737 goto handle_enum;
7738 } else {
7739 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
7741 break;
7742 case MONO_TYPE_STRING: {
7743 char *str;
7744 guint32 slen;
7745 if (!arg) {
7746 *p++ = 0xFF;
7747 break;
7749 str = mono_string_to_utf8 ((MonoString*)arg);
7750 slen = strlen (str);
7751 if ((p-buffer) + 10 + slen >= *buflen) {
7752 char *newbuf;
7753 *buflen *= 2;
7754 *buflen += slen;
7755 newbuf = g_realloc (buffer, *buflen);
7756 p = newbuf + (p-buffer);
7757 buffer = newbuf;
7759 mono_metadata_encode_value (slen, p, &p);
7760 memcpy (p, str, slen);
7761 p += slen;
7762 g_free (str);
7763 break;
7765 case MONO_TYPE_CLASS: {
7766 char *str;
7767 guint32 slen;
7768 MonoClass *k;
7769 if (!arg) {
7770 *p++ = 0xFF;
7771 break;
7773 k = mono_object_class (arg);
7774 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
7775 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
7776 g_error ("Only System.Type allowed, not %s.%s", k->name_space, k->name);
7777 handle_type:
7778 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
7779 slen = strlen (str);
7780 if ((p-buffer) + 10 + slen >= *buflen) {
7781 char *newbuf;
7782 *buflen *= 2;
7783 *buflen += slen;
7784 newbuf = g_realloc (buffer, *buflen);
7785 p = newbuf + (p-buffer);
7786 buffer = newbuf;
7788 mono_metadata_encode_value (slen, p, &p);
7789 memcpy (p, str, slen);
7790 p += slen;
7791 g_free (str);
7792 break;
7794 case MONO_TYPE_SZARRAY: {
7795 int len, i;
7796 MonoClass *eclass, *arg_eclass;
7798 if (!arg) {
7799 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
7800 break;
7802 len = mono_array_length ((MonoArray*)arg);
7803 *p++ = len & 0xff;
7804 *p++ = (len >> 8) & 0xff;
7805 *p++ = (len >> 16) & 0xff;
7806 *p++ = (len >> 24) & 0xff;
7807 *retp = p;
7808 *retbuffer = buffer;
7809 eclass = type->data.klass;
7810 arg_eclass = mono_object_class (arg)->element_class;
7812 if (!eclass) {
7813 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
7814 eclass = mono_defaults.object_class;
7816 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
7817 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
7818 int elsize = mono_class_array_element_size (arg_eclass);
7819 for (i = 0; i < len; ++i) {
7820 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
7821 elptr += elsize;
7823 } else if (eclass->valuetype && arg_eclass->valuetype) {
7824 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
7825 int elsize = mono_class_array_element_size (eclass);
7826 for (i = 0; i < len; ++i) {
7827 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
7828 elptr += elsize;
7830 } else {
7831 for (i = 0; i < len; ++i) {
7832 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
7835 break;
7837 case MONO_TYPE_OBJECT: {
7838 MonoClass *klass;
7839 char *str;
7840 guint32 slen;
7843 * The parameter type is 'object' but the type of the actual
7844 * argument is not. So we have to add type information to the blob
7845 * too. This is completely undocumented in the spec.
7848 if (arg == NULL) {
7849 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
7850 *p++ = 0xFF;
7851 break;
7854 klass = mono_object_class (arg);
7856 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
7857 *p++ = 0x50;
7858 goto handle_type;
7859 } else if (klass->enumtype) {
7860 *p++ = 0x55;
7861 } else if (klass == mono_defaults.string_class) {
7862 simple_type = MONO_TYPE_STRING;
7863 *p++ = 0x0E;
7864 goto handle_enum;
7865 } else if (klass->rank == 1) {
7866 simple_type = MONO_TYPE_SZARRAY;
7867 *p++ = 0x1D;
7868 *p++ = klass->element_class->byval_arg.type;
7869 goto handle_enum;
7870 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
7871 *p++ = simple_type = klass->byval_arg.type;
7872 goto handle_enum;
7873 } else {
7874 g_error ("unhandled type in custom attr");
7876 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
7877 slen = strlen (str);
7878 if ((p-buffer) + 10 + slen >= *buflen) {
7879 char *newbuf;
7880 *buflen *= 2;
7881 *buflen += slen;
7882 newbuf = g_realloc (buffer, *buflen);
7883 p = newbuf + (p-buffer);
7884 buffer = newbuf;
7886 mono_metadata_encode_value (slen, p, &p);
7887 memcpy (p, str, slen);
7888 p += slen;
7889 g_free (str);
7890 simple_type = klass->enum_basetype->type;
7891 goto handle_enum;
7893 default:
7894 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
7896 *retp = p;
7897 *retbuffer = buffer;
7900 static void
7901 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
7903 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
7904 char *str = type_get_qualified_name (type, NULL);
7905 int slen = strlen (str);
7907 *p++ = 0x55;
7909 * This seems to be optional...
7910 * *p++ = 0x80;
7912 mono_metadata_encode_value (slen, p, &p);
7913 memcpy (p, str, slen);
7914 p += slen;
7915 g_free (str);
7916 } else if (type->type == MONO_TYPE_OBJECT) {
7917 *p++ = 0x51;
7918 } else if (type->type == MONO_TYPE_CLASS) {
7919 /* it should be a type: encode_cattr_value () has the check */
7920 *p++ = 0x50;
7921 } else {
7922 mono_metadata_encode_value (type->type, p, &p);
7923 if (type->type == MONO_TYPE_SZARRAY)
7924 /* See the examples in Partition VI, Annex B */
7925 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
7928 *retp = p;
7931 static void
7932 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
7934 int len;
7935 /* Preallocate a large enough buffer */
7936 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
7937 char *str = type_get_qualified_name (type, NULL);
7938 len = strlen (str);
7939 g_free (str);
7940 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
7941 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
7942 len = strlen (str);
7943 g_free (str);
7944 } else {
7945 len = 0;
7947 len += strlen (name);
7949 if ((p-buffer) + 20 + len >= *buflen) {
7950 char *newbuf;
7951 *buflen *= 2;
7952 *buflen += len;
7953 newbuf = g_realloc (buffer, *buflen);
7954 p = newbuf + (p-buffer);
7955 buffer = newbuf;
7958 encode_field_or_prop_type (type, p, &p);
7960 len = strlen (name);
7961 mono_metadata_encode_value (len, p, &p);
7962 memcpy (p, name, len);
7963 p += len;
7964 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
7965 *retp = p;
7966 *retbuffer = buffer;
7970 * mono_reflection_get_custom_attrs_blob:
7971 * @ctor: custom attribute constructor
7972 * @ctorArgs: arguments o the constructor
7973 * @properties:
7974 * @propValues:
7975 * @fields:
7976 * @fieldValues:
7978 * Creates the blob of data that needs to be saved in the metadata and that represents
7979 * the custom attributed described by @ctor, @ctorArgs etc.
7980 * Returns: a Byte array representing the blob of data.
7982 MonoArray*
7983 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
7985 MonoArray *result;
7986 MonoMethodSignature *sig;
7987 MonoObject *arg;
7988 char *buffer, *p;
7989 guint32 buflen, i;
7991 MONO_ARCH_SAVE_REGS;
7993 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
7994 /* sig is freed later so allocate it in the heap */
7995 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
7996 } else {
7997 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
8000 g_assert (mono_array_length (ctorArgs) == sig->param_count);
8001 buflen = 256;
8002 p = buffer = g_malloc (buflen);
8003 /* write the prolog */
8004 *p++ = 1;
8005 *p++ = 0;
8006 for (i = 0; i < sig->param_count; ++i) {
8007 arg = mono_array_get (ctorArgs, MonoObject*, i);
8008 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
8010 i = 0;
8011 if (properties)
8012 i += mono_array_length (properties);
8013 if (fields)
8014 i += mono_array_length (fields);
8015 *p++ = i & 0xff;
8016 *p++ = (i >> 8) & 0xff;
8017 if (properties) {
8018 MonoObject *prop;
8019 for (i = 0; i < mono_array_length (properties); ++i) {
8020 MonoType *ptype;
8021 char *pname;
8023 prop = mono_array_get (properties, gpointer, i);
8024 get_prop_name_and_type (prop, &pname, &ptype);
8025 *p++ = 0x54; /* PROPERTY signature */
8026 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
8027 g_free (pname);
8031 if (fields) {
8032 MonoObject *field;
8033 for (i = 0; i < mono_array_length (fields); ++i) {
8034 MonoType *ftype;
8035 char *fname;
8037 field = mono_array_get (fields, gpointer, i);
8038 get_field_name_and_type (field, &fname, &ftype);
8039 *p++ = 0x53; /* FIELD signature */
8040 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
8041 g_free (fname);
8045 g_assert (p - buffer <= buflen);
8046 buflen = p - buffer;
8047 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8048 p = mono_array_addr (result, char, 0);
8049 memcpy (p, buffer, buflen);
8050 g_free (buffer);
8051 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
8052 g_free (sig);
8053 return result;
8056 #if HAVE_SGEN_GC
8057 static void* reflection_info_desc = NULL;
8058 #define MOVING_GC_REGISTER(addr) do { \
8059 if (!reflection_info_desc) { \
8060 gsize bmap = 1; \
8061 reflection_info_desc = mono_gc_make_descr_from_bitmap (&bmap, 1); \
8063 mono_gc_register_root ((addr), sizeof (gpointer), reflection_info_desc); \
8064 } while (0)
8065 #else
8066 #define MOVING_GC_REGISTER(addr)
8067 #endif
8070 * mono_reflection_setup_internal_class:
8071 * @tb: a TypeBuilder object
8073 * Creates a MonoClass that represents the TypeBuilder.
8074 * This is a trick that lets us simplify a lot of reflection code
8075 * (and will allow us to support Build and Run assemblies easier).
8077 void
8078 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
8080 MonoClass *klass, *parent;
8082 MONO_ARCH_SAVE_REGS;
8084 mono_loader_lock ();
8086 if (tb->parent) {
8087 /* check so we can compile corlib correctly */
8088 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
8089 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
8090 parent = tb->parent->type->data.klass;
8091 } else {
8092 parent = my_mono_class_from_mono_type (tb->parent->type);
8094 } else {
8095 parent = NULL;
8098 /* the type has already being created: it means we just have to change the parent */
8099 if (tb->type.type) {
8100 klass = mono_class_from_mono_type (tb->type.type);
8101 klass->parent = NULL;
8102 /* fool mono_class_setup_parent */
8103 klass->supertypes = NULL;
8104 mono_class_setup_parent (klass, parent);
8105 mono_class_setup_mono_type (klass);
8106 mono_loader_unlock ();
8107 return;
8110 klass = mono_mempool_alloc0 (tb->module->dynamic_image->image.mempool, sizeof (MonoClass));
8112 klass->image = &tb->module->dynamic_image->image;
8114 klass->inited = 1; /* we lie to the runtime */
8115 klass->name = mono_string_to_utf8_mp (klass->image->mempool, tb->name);
8116 klass->name_space = mono_string_to_utf8_mp (klass->image->mempool, tb->nspace);
8117 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
8118 klass->flags = tb->attrs;
8120 klass->element_class = klass;
8122 MOVING_GC_REGISTER (&klass->reflection_info);
8123 klass->reflection_info = tb;
8125 /* Put into cache so mono_class_get () will find it */
8126 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
8128 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
8129 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
8131 if (parent != NULL) {
8132 mono_class_setup_parent (klass, parent);
8133 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
8134 const char *old_n = klass->name;
8135 /* trick to get relative numbering right when compiling corlib */
8136 klass->name = "BuildingObject";
8137 mono_class_setup_parent (klass, mono_defaults.object_class);
8138 klass->name = old_n;
8141 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
8142 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
8143 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
8144 klass->instance_size = sizeof (MonoObject);
8145 klass->size_inited = 1;
8146 mono_class_setup_vtable_general (klass, NULL, 0);
8149 mono_class_setup_mono_type (klass);
8151 mono_class_setup_supertypes (klass);
8154 * FIXME: handle interfaces.
8157 tb->type.type = &klass->byval_arg;
8159 if (tb->nesting_type) {
8160 g_assert (tb->nesting_type->type);
8161 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
8164 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
8166 mono_loader_unlock ();
8170 * mono_reflection_setup_generic_class:
8171 * @tb: a TypeBuilder object
8173 * Setup the generic class before adding the first generic parameter.
8175 void
8176 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
8178 MonoClass *klass;
8180 MONO_ARCH_SAVE_REGS;
8182 klass = my_mono_class_from_mono_type (tb->type.type);
8183 if (tb->generic_container)
8184 return;
8186 tb->generic_container = g_new0 (MonoGenericContainer, 1);
8187 tb->generic_container->klass = klass;
8189 tb->generic_container->context.container = tb->generic_container;
8193 * mono_reflection_create_generic_class:
8194 * @tb: a TypeBuilder object
8196 * Creates the generic class after all generic parameters have been added.
8198 void
8199 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
8201 MonoClass *klass;
8202 int count, i;
8204 MONO_ARCH_SAVE_REGS;
8206 klass = my_mono_class_from_mono_type (tb->type.type);
8208 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
8210 if (klass->generic_container || (count == 0))
8211 return;
8213 g_assert (tb->generic_container && (tb->generic_container->klass == klass));
8215 klass->generic_container = tb->generic_container;
8217 klass->generic_container->type_argc = count;
8218 klass->generic_container->type_params = g_new0 (MonoGenericParam, count);
8220 for (i = 0; i < count; i++) {
8221 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
8222 klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
8223 g_assert (klass->generic_container->type_params [i].owner);
8226 klass->generic_container->context.gclass = mono_get_shared_generic_class (klass->generic_container, TRUE);
8230 * mono_reflection_create_internal_class:
8231 * @tb: a TypeBuilder object
8233 * Actually create the MonoClass that is associated with the TypeBuilder.
8235 void
8236 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
8238 MonoClass *klass;
8240 MONO_ARCH_SAVE_REGS;
8242 klass = my_mono_class_from_mono_type (tb->type.type);
8244 mono_loader_lock ();
8245 if (klass->enumtype && klass->enum_basetype == NULL) {
8246 MonoReflectionFieldBuilder *fb;
8247 MonoClass *ec;
8249 g_assert (tb->fields != NULL);
8250 g_assert (mono_array_length (tb->fields) >= 1);
8252 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
8254 klass->enum_basetype = fb->type->type;
8255 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
8256 if (!klass->element_class)
8257 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
8260 * get the element_class from the current corlib.
8262 ec = default_class_from_mono_type (klass->enum_basetype);
8263 klass->instance_size = ec->instance_size;
8264 klass->size_inited = 1;
8266 * this is almost safe to do with enums and it's needed to be able
8267 * to create objects of the enum type (for use in SetConstant).
8269 /* FIXME: Does this mean enums can't have method overrides ? */
8270 mono_class_setup_vtable_general (klass, NULL, 0);
8272 mono_loader_unlock ();
8275 static MonoMarshalSpec*
8276 mono_marshal_spec_from_builder (MonoAssembly *assembly,
8277 MonoReflectionMarshal *minfo)
8279 MonoMarshalSpec *res;
8281 res = g_new0 (MonoMarshalSpec, 1);
8282 res->native = minfo->type;
8284 switch (minfo->type) {
8285 case MONO_NATIVE_LPARRAY:
8286 res->data.array_data.elem_type = minfo->eltype;
8287 if (minfo->has_size) {
8288 res->data.array_data.param_num = minfo->param_num;
8289 res->data.array_data.num_elem = minfo->count;
8290 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
8292 else {
8293 res->data.array_data.param_num = -1;
8294 res->data.array_data.num_elem = -1;
8295 res->data.array_data.elem_mult = -1;
8297 break;
8299 case MONO_NATIVE_BYVALTSTR:
8300 case MONO_NATIVE_BYVALARRAY:
8301 res->data.array_data.num_elem = minfo->count;
8302 break;
8304 case MONO_NATIVE_CUSTOM:
8305 if (minfo->marshaltyperef)
8306 res->data.custom_data.custom_name =
8307 type_get_fully_qualified_name (minfo->marshaltyperef->type);
8308 if (minfo->mcookie)
8309 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
8310 break;
8312 default:
8313 break;
8316 return res;
8319 MonoReflectionMarshal*
8320 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
8321 MonoMarshalSpec *spec)
8323 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
8324 MonoReflectionMarshal *minfo;
8325 MonoType *mtype;
8327 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
8328 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
8329 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
8330 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
8333 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
8334 minfo->type = spec->native;
8336 switch (minfo->type) {
8337 case MONO_NATIVE_LPARRAY:
8338 minfo->eltype = spec->data.array_data.elem_type;
8339 minfo->count = spec->data.array_data.num_elem;
8340 minfo->param_num = spec->data.array_data.param_num;
8341 break;
8343 case MONO_NATIVE_BYVALTSTR:
8344 case MONO_NATIVE_BYVALARRAY:
8345 minfo->count = spec->data.array_data.num_elem;
8346 break;
8348 case MONO_NATIVE_CUSTOM:
8349 if (spec->data.custom_data.custom_name) {
8350 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
8351 if (mtype)
8352 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
8354 MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
8356 if (spec->data.custom_data.cookie)
8357 MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
8358 break;
8360 default:
8361 break;
8364 return minfo;
8367 static MonoMethod*
8368 reflection_methodbuilder_to_mono_method (MonoClass *klass,
8369 ReflectionMethodBuilder *rmb,
8370 MonoMethodSignature *sig)
8372 MonoMethod *m;
8373 MonoMethodNormal *pm;
8374 MonoMarshalSpec **specs;
8375 MonoReflectionMethodAux *method_aux;
8376 MonoMemPool *mp;
8377 gboolean dynamic;
8378 int i;
8380 g_assert (!klass->generic_class);
8383 * Methods created using a MethodBuilder should have their memory allocated
8384 * inside the image mempool, while dynamic methods should have their memory
8385 * malloc'd.
8387 dynamic = rmb->refs != NULL;
8388 mp = dynamic ? NULL : klass->image->mempool;
8390 mono_loader_lock ();
8392 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
8393 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
8394 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodPInvoke, 1);
8395 else if (rmb->refs)
8396 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodWrapper, 1);
8397 else
8398 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodNormal, 1);
8400 pm = (MonoMethodNormal*)m;
8402 m->slot = -1;
8403 m->flags = rmb->attrs;
8404 m->iflags = rmb->iattrs;
8405 m->name = dynamic ? mono_string_to_utf8 (rmb->name) : mono_string_to_utf8_mp (mp, rmb->name);
8406 m->klass = klass;
8407 m->signature = sig;
8408 m->skip_visibility = rmb->skip_visibility;
8409 if (rmb->table_idx)
8410 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
8412 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
8413 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
8414 m->string_ctor = 1;
8416 m->signature->pinvoke = 1;
8417 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
8418 m->signature->pinvoke = 1;
8420 method_aux = g_new0 (MonoReflectionMethodAux, 1);
8422 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_mp (mp, rmb->dllentry) : mono_mempool_strdup (mp, m->name);
8423 method_aux->dll = mono_string_to_utf8_mp (mp, rmb->dll);
8425 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
8427 if (klass->image->dynamic)
8428 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
8430 mono_loader_unlock ();
8432 return m;
8433 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
8434 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
8435 MonoMethodHeader *header;
8436 guint32 code_size;
8437 gint32 max_stack, i;
8438 gint32 num_locals = 0;
8439 gint32 num_clauses = 0;
8440 guint8 *code;
8442 if (rmb->ilgen) {
8443 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
8444 code_size = rmb->ilgen->code_len;
8445 max_stack = rmb->ilgen->max_stack;
8446 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
8447 if (rmb->ilgen->ex_handlers)
8448 num_clauses = method_count_clauses (rmb->ilgen);
8449 } else {
8450 if (rmb->code) {
8451 code = mono_array_addr (rmb->code, guint8, 0);
8452 code_size = mono_array_length (rmb->code);
8453 /* we probably need to run a verifier on the code... */
8454 max_stack = 8;
8456 else {
8457 code = NULL;
8458 code_size = 0;
8459 max_stack = 8;
8463 header = mp_g_malloc0 (mp, sizeof (MonoMethodHeader) +
8464 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
8465 header->code_size = code_size;
8466 header->code = mp_g_malloc (mp, code_size);
8467 memcpy ((char*)header->code, code, code_size);
8468 header->max_stack = max_stack;
8469 header->init_locals = rmb->init_locals;
8470 header->num_locals = num_locals;
8472 for (i = 0; i < num_locals; ++i) {
8473 MonoReflectionLocalBuilder *lb =
8474 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
8476 header->locals [i] = mp_g_new0 (mp, MonoType, 1);
8477 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
8480 header->num_clauses = num_clauses;
8481 if (num_clauses) {
8482 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
8483 rmb->ilgen, num_clauses);
8486 pm->header = header;
8489 if (rmb->generic_params) {
8490 int count = mono_array_length (rmb->generic_params);
8491 MonoGenericContainer *container;
8492 MonoGenericContext *context;
8494 m->generic_container = container = rmb->generic_container;
8495 container->type_argc = count;
8496 container->type_params = g_new0 (MonoGenericParam, count);
8498 for (i = 0; i < count; i++) {
8499 MonoReflectionGenericParam *gp =
8500 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
8502 container->type_params [i] = *gp->type.type->data.generic_param;
8503 container->type_params [i].method = m;
8506 context = &container->context;
8507 context->container = container;
8508 if (klass->generic_container) {
8509 container->parent = klass->generic_container;
8510 context->gclass = klass->generic_container->context.gclass;
8512 context->gmethod = mono_get_shared_generic_method (container);
8515 if (rmb->refs) {
8516 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
8517 int i;
8518 void **data;
8520 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
8522 mw->method_data = data = mp_g_new (mp, gpointer, rmb->nrefs + 1);
8523 data [0] = GUINT_TO_POINTER (rmb->nrefs);
8524 for (i = 0; i < rmb->nrefs; ++i)
8525 data [i + 1] = rmb->refs [i];
8528 method_aux = NULL;
8530 /* Parameter info */
8531 if (rmb->pinfo) {
8532 if (!method_aux)
8533 method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
8534 method_aux->param_names = mp_g_new0 (mp, char *, mono_method_signature (m)->param_count + 1);
8535 for (i = 0; i <= m->signature->param_count; ++i) {
8536 MonoReflectionParamBuilder *pb;
8537 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
8538 if ((i > 0) && (pb->attrs)) {
8539 /* Make a copy since it might point to a shared type structure */
8540 /* FIXME: Alloc this from a mempool */
8541 m->signature->params [i - 1] = g_memdup (m->signature->params [i - 1], sizeof (MonoType) + ((m->signature->params [i - 1]->num_mods - MONO_ZERO_LEN_ARRAY) * sizeof (MonoCustomMod)));
8542 m->signature->params [i - 1]->attrs = pb->attrs;
8545 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
8546 MonoDynamicImage *assembly;
8547 guint32 idx, def_type, len;
8548 char *p;
8549 const char *p2;
8551 if (!method_aux->param_defaults) {
8552 method_aux->param_defaults = mp_g_new0 (mp, guint8*, m->signature->param_count + 1);
8553 method_aux->param_default_types = mp_g_new0 (mp, guint32, m->signature->param_count + 1);
8555 assembly = (MonoDynamicImage*)klass->image;
8556 idx = encode_constant (assembly, pb->def_value, &def_type);
8557 /* Copy the data from the blob since it might get realloc-ed */
8558 p = assembly->blob.data + idx;
8559 len = mono_metadata_decode_blob_size (p, &p2);
8560 len += p2 - p;
8561 method_aux->param_defaults [i] = mp_g_malloc (mp, len);
8562 method_aux->param_default_types [i] = def_type;
8563 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
8566 if (pb->name)
8567 method_aux->param_names [i] = dynamic ? mono_string_to_utf8 (pb->name) : mono_string_to_utf8_mp (mp, pb->name);
8568 if (pb->cattrs) {
8569 if (!method_aux->param_cattr)
8570 method_aux->param_cattr = mp_g_new0 (mp, MonoCustomAttrInfo*, m->signature->param_count + 1);
8571 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
8577 /* Parameter marshalling */
8578 specs = NULL;
8579 if (rmb->pinfo)
8580 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
8581 MonoReflectionParamBuilder *pb;
8582 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
8583 if (pb->marshal_info) {
8584 if (specs == NULL)
8585 specs = mp_g_new0 (mp, MonoMarshalSpec*, sig->param_count + 1);
8586 specs [pb->position] =
8587 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
8591 if (specs != NULL) {
8592 if (!method_aux)
8593 method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
8594 method_aux->param_marshall = specs;
8597 if (klass->image->dynamic && method_aux)
8598 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
8600 mono_loader_unlock ();
8602 return m;
8605 static MonoMethod*
8606 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
8608 ReflectionMethodBuilder rmb;
8609 MonoMethodSignature *sig;
8611 mono_loader_lock ();
8612 sig = ctor_builder_to_signature (klass->image->mempool, mb);
8613 mono_loader_unlock ();
8615 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
8617 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
8618 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
8620 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
8621 /* ilgen is no longer needed */
8622 mb->ilgen = NULL;
8625 return mb->mhandle;
8628 static MonoMethod*
8629 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
8631 ReflectionMethodBuilder rmb;
8632 MonoMethodSignature *sig;
8634 mono_loader_lock ();
8635 sig = method_builder_to_signature (klass->image->mempool, mb);
8636 mono_loader_unlock ();
8638 reflection_methodbuilder_from_method_builder (&rmb, mb);
8640 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
8641 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
8643 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
8644 /* ilgen is no longer needed */
8645 mb->ilgen = NULL;
8647 return mb->mhandle;
8650 static MonoClassField*
8651 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
8653 MonoClassField *field;
8654 const char *p, *p2;
8655 guint32 len, idx;
8657 field = g_new0 (MonoClassField, 1);
8659 field->name = mono_string_to_utf8 (fb->name);
8660 if (fb->attrs) {
8661 /* FIXME: handle type modifiers */
8662 field->type = g_memdup (fb->type->type, sizeof (MonoType));
8663 field->type->attrs = fb->attrs;
8664 } else {
8665 field->type = fb->type->type;
8667 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
8668 field->data = mono_array_addr (fb->rva_data, char, 0); /* FIXME: GC pin array */
8669 if (fb->offset != -1)
8670 field->offset = fb->offset;
8671 field->parent = klass;
8672 mono_save_custom_attrs (klass->image, field, fb->cattrs);
8674 if (fb->def_value) {
8675 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
8676 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
8677 idx = encode_constant (assembly, fb->def_value, &field->def_type);
8678 /* Copy the data from the blob since it might get realloc-ed */
8679 p = assembly->blob.data + idx;
8680 len = mono_metadata_decode_blob_size (p, &p2);
8681 len += p2 - p;
8682 field->data = g_malloc (len);
8683 memcpy ((gpointer)field->data, p, len);
8686 return field;
8689 MonoType*
8690 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
8692 MonoClass *klass;
8693 MonoReflectionTypeBuilder *tb = NULL;
8694 MonoGenericClass *gclass, *cached;
8695 gboolean is_dynamic = FALSE;
8696 MonoDomain *domain;
8697 MonoType *geninst;
8698 int i;
8700 mono_loader_lock ();
8702 domain = mono_object_domain (type);
8704 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
8705 tb = (MonoReflectionTypeBuilder *) type;
8707 is_dynamic = TRUE;
8708 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
8709 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
8710 MonoReflectionType *rgt = rgi->generic_type;
8712 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
8713 tb = (MonoReflectionTypeBuilder *) rgt;
8715 is_dynamic = TRUE;
8718 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
8719 if (tb && tb->generic_container)
8720 mono_reflection_create_generic_class (tb);
8722 klass = mono_class_from_mono_type (type->type);
8723 if (!klass->generic_container) {
8724 mono_loader_unlock ();
8725 return NULL;
8728 if (klass->wastypebuilder) {
8729 tb = (MonoReflectionTypeBuilder *) klass->reflection_info;
8731 is_dynamic = TRUE;
8734 if (is_dynamic) {
8735 MonoDynamicGenericClass *dgclass = g_new0 (MonoDynamicGenericClass, 1);
8736 MonoInflatedGenericClass *igclass = &dgclass->generic_class;
8737 gclass = &igclass->generic_class;
8738 gclass->is_dynamic = TRUE;
8739 gclass->is_inflated = TRUE;
8740 } else {
8741 MonoInflatedGenericClass *igclass = g_new0 (MonoInflatedGenericClass, 1);
8742 gclass = &igclass->generic_class;
8743 gclass->is_inflated = TRUE;
8746 gclass->inst = g_new0 (MonoGenericInst, 1);
8748 gclass->inst->type_argc = type_argc;
8749 gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc);
8750 gclass->inst->is_reference = 1;
8752 for (i = 0; i < gclass->inst->type_argc; ++i) {
8753 MonoType *t = dup_type (types [i]);
8755 if (!gclass->inst->is_open)
8756 gclass->inst->is_open = mono_class_is_open_constructed_type (t);
8757 if (gclass->inst->is_reference)
8758 gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (t);
8759 gclass->inst->type_argv [i] = t;
8762 gclass->inst = mono_metadata_lookup_generic_inst (gclass->inst);
8764 gclass->container_class = klass;
8766 geninst = g_new0 (MonoType, 1);
8767 geninst->type = MONO_TYPE_GENERICINST;
8769 cached = mono_metadata_lookup_generic_class (gclass);
8770 if (cached) {
8771 g_free (gclass);
8772 mono_loader_unlock ();
8773 geninst->data.generic_class = cached;
8774 return geninst;
8777 geninst->data.generic_class = gclass;
8779 gclass->context = g_new0 (MonoGenericContext, 1);
8780 gclass->context->container = gclass->container_class->generic_container;
8781 gclass->context->gclass = gclass;
8783 mono_loader_unlock ();
8785 return geninst;
8788 MonoType*
8789 mono_class_bind_generic_parameters (MonoType *type, int type_argc, MonoType **types)
8791 MonoClass *klass;
8792 MonoGenericClass *gclass, *cached;
8793 MonoInflatedGenericClass *igclass;
8794 MonoType *geninst;
8795 int i;
8797 klass = mono_class_from_mono_type (type);
8798 if (!klass->generic_container && !klass->generic_class &&
8799 !(klass->nested_in && klass->nested_in->generic_container))
8800 return NULL;
8802 mono_loader_lock ();
8804 igclass = g_new0 (MonoInflatedGenericClass, 1);
8805 gclass = &igclass->generic_class;
8806 gclass->is_inflated = TRUE;
8808 gclass->inst = g_new0 (MonoGenericInst, 1);
8809 gclass->inst->type_argc = type_argc;
8810 gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc);
8811 gclass->inst->is_reference = 1;
8813 for (i = 0; i < gclass->inst->type_argc; ++i) {
8814 MonoType *t = dup_type (types [i]);
8816 if (!gclass->inst->is_open)
8817 gclass->inst->is_open = mono_class_is_open_constructed_type (t);
8818 if (gclass->inst->is_reference)
8819 gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (t);
8821 gclass->inst->type_argv [i] = t;
8824 gclass->inst = mono_metadata_lookup_generic_inst (gclass->inst);
8826 gclass->container_class = klass;
8828 if (klass->generic_class) {
8829 MonoGenericClass *kgclass = klass->generic_class;
8830 MonoGenericClass *ogclass = gclass;
8832 gclass->context = g_new0 (MonoGenericContext, 1);
8833 gclass->context->container = gclass->container_class->generic_container;
8834 gclass->context->gclass = gclass;
8836 igclass = g_new0 (MonoInflatedGenericClass, 1);
8837 gclass = &igclass->generic_class;
8838 gclass->is_inflated = TRUE;
8840 gclass->inst = g_new0 (MonoGenericInst, 1);
8841 gclass->inst->type_argc = kgclass->inst->type_argc;
8842 gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc);
8843 gclass->inst->is_reference = 1;
8845 for (i = 0; i < gclass->inst->type_argc; i++) {
8846 MonoType *t = kgclass->inst->type_argv [i];
8848 t = mono_class_inflate_generic_type (t, ogclass->context);
8850 if (!gclass->inst->is_open)
8851 gclass->inst->is_open = mono_class_is_open_constructed_type (t);
8852 if (gclass->inst->is_reference)
8853 gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (t);
8855 gclass->inst->type_argv [i] = t;
8858 gclass->inst = mono_metadata_lookup_generic_inst (gclass->inst);
8860 gclass->container_class = kgclass->container_class;
8863 geninst = g_new0 (MonoType, 1);
8864 geninst->type = MONO_TYPE_GENERICINST;
8866 cached = mono_metadata_lookup_generic_class (gclass);
8867 if (cached) {
8868 g_free (gclass);
8869 mono_loader_unlock ();
8870 geninst->data.generic_class = cached;
8871 return geninst;
8874 geninst->data.generic_class = gclass;
8876 gclass->context = g_new0 (MonoGenericContext, 1);
8877 gclass->context->container = gclass->container_class->generic_container;
8878 gclass->context->gclass = gclass;
8880 mono_loader_unlock ();
8882 return geninst;
8885 static inline MonoType*
8886 dup_type (const MonoType *original)
8888 MonoType *r = g_new0 (MonoType, 1);
8889 *r = *original;
8890 r->attrs = original->attrs;
8891 r->byref = original->byref;
8892 if (original->type == MONO_TYPE_PTR)
8893 r->data.type = dup_type (original->data.type);
8894 else if (original->type == MONO_TYPE_ARRAY)
8895 r->data.array = mono_dup_array_type (original->data.array);
8896 else if (original->type == MONO_TYPE_FNPTR)
8897 r->data.method = mono_metadata_signature_deep_dup (original->data.method);
8898 mono_stats.generics_metadata_size += sizeof (MonoType);
8899 return r;
8902 MonoReflectionMethod*
8903 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
8905 MonoMethod *method, *inflated;
8906 MonoReflectionMethodBuilder *mb = NULL;
8907 MonoGenericContainer *container;
8908 MonoGenericMethod *gmethod;
8909 MonoGenericContext *context;
8910 MonoGenericInst *ginst;
8911 int count, i;
8913 MONO_ARCH_SAVE_REGS;
8914 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
8915 MonoReflectionTypeBuilder *tb;
8916 MonoClass *klass;
8918 mb = (MonoReflectionMethodBuilder *) rmethod;
8919 tb = (MonoReflectionTypeBuilder *) mb->type;
8920 klass = mono_class_from_mono_type (tb->type.type);
8922 method = methodbuilder_to_mono_method (klass, mb);
8923 } else {
8924 method = rmethod->method;
8927 method = mono_get_inflated_method (method);
8929 count = mono_method_signature (method)->generic_param_count;
8930 if (count != mono_array_length (types))
8931 return NULL;
8933 container = method->generic_container;
8934 g_assert (container);
8936 if (!container->method_hash)
8937 container->method_hash = g_hash_table_new (
8938 (GHashFunc) mono_metadata_generic_method_hash,
8939 (GCompareFunc) mono_metadata_generic_method_equal);
8941 ginst = g_new0 (MonoGenericInst,1 );
8942 ginst->type_argc = count;
8943 ginst->type_argv = g_new0 (MonoType *, count);
8944 ginst->is_reference = 1;
8945 for (i = 0; i < count; i++) {
8946 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
8947 ginst->type_argv [i] = dup_type (garg->type);
8949 if (!ginst->is_open)
8950 ginst->is_open = mono_class_is_open_constructed_type (ginst->type_argv [i]);
8951 if (ginst->is_reference)
8952 ginst->is_reference = MONO_TYPE_IS_REFERENCE (ginst->type_argv [i]);
8954 ginst = mono_metadata_lookup_generic_inst (ginst);
8956 gmethod = g_new0 (MonoGenericMethod, 1);
8957 gmethod->generic_class = method->klass->generic_class;
8958 gmethod->container = container;
8959 gmethod->inst = ginst;
8961 inflated = g_hash_table_lookup (container->method_hash, gmethod);
8962 if (inflated) {
8963 g_free (gmethod);
8965 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
8968 MOVING_GC_REGISTER (&gmethod->reflection_info);
8969 gmethod->reflection_info = rmethod;
8971 context = g_new0 (MonoGenericContext, 1);
8972 context->container = container;
8973 context->gclass = method->klass->generic_class;
8974 context->gmethod = gmethod;
8976 if (method->is_inflated)
8977 method = ((MonoMethodInflated *) method)->declaring;
8979 inflated = mono_class_inflate_generic_method (method, context);
8980 g_hash_table_insert (container->method_hash, gmethod, inflated);
8982 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
8985 static MonoMethod *
8986 inflate_mono_method (MonoReflectionGenericClass *type, MonoMethod *method, MonoObject *obj)
8988 MonoGenericMethod *gmethod = NULL;
8989 MonoInflatedGenericClass *gclass;
8990 MonoGenericContext *context;
8991 MonoClass *klass;
8992 int i, n;
8994 klass = mono_class_from_mono_type (type->type.type);
8995 gclass = mono_get_inflated_generic_class (type->type.type->data.generic_class);
8996 n = mono_method_signature (method)->generic_param_count;
8998 context = gclass->generic_class.context;
8999 g_assert (context && context->container);
9000 if (n) {
9001 gmethod = g_new0 (MonoGenericMethod, 1);
9002 gmethod->generic_class = &gclass->generic_class;
9003 gmethod->container = method->generic_container;
9004 MOVING_GC_REGISTER (&gmethod->reflection_info);
9005 gmethod->reflection_info = obj;
9007 gmethod->inst = g_new0 (MonoGenericInst, 1);
9008 gmethod->inst->type_argc = n;
9009 gmethod->inst->type_argv = g_new0 (MonoType *, n);
9011 for (i = 0; i < n; i++) {
9012 MonoGenericParam *gparam = &method->generic_container->type_params [i];
9013 g_assert (gparam->pklass);
9014 gmethod->inst->type_argv [i] = &gparam->pklass->byval_arg;
9017 g_assert (gmethod->container->parent == context->container);
9019 context = g_new0 (MonoGenericContext, 1);
9020 context->container = gmethod->container;
9021 context->gclass = &gclass->generic_class;
9022 context->gmethod = gmethod;
9025 return mono_class_inflate_generic_method (method, context);
9028 static MonoMethod *
9029 inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
9031 MonoMethod *method;
9032 MonoClass *gklass;
9034 gklass = mono_class_from_mono_type (type->generic_type->type);
9036 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
9037 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
9038 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
9039 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
9040 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
9041 method = ((MonoReflectionMethod *) obj)->method;
9042 else {
9043 method = NULL; /* prevent compiler warning */
9044 g_assert_not_reached ();
9047 return inflate_mono_method (type, method, obj);
9050 void
9051 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
9052 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
9053 MonoArray *events)
9055 MonoGenericClass *gclass;
9056 MonoDynamicGenericClass *dgclass;
9057 MonoClass *klass, *gklass;
9058 int i;
9060 MONO_ARCH_SAVE_REGS;
9062 klass = mono_class_from_mono_type (type->type.type);
9063 gclass = type->type.type->data.generic_class;
9065 g_assert (gclass->is_dynamic);
9066 dgclass = (MonoDynamicGenericClass *) gclass;
9068 if (dgclass->initialized)
9069 return;
9071 gklass = gclass->container_class;
9072 mono_class_init (gklass);
9074 dgclass->count_methods = methods ? mono_array_length (methods) : 0;
9075 dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
9076 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
9077 dgclass->count_properties = properties ? mono_array_length (properties) : 0;
9078 dgclass->count_events = events ? mono_array_length (events) : 0;
9080 dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
9081 dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
9082 dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
9083 dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
9084 dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
9086 for (i = 0; i < dgclass->count_methods; i++) {
9087 MonoObject *obj = mono_array_get (methods, gpointer, i);
9089 dgclass->methods [i] = inflate_method (type, obj);
9092 for (i = 0; i < dgclass->count_ctors; i++) {
9093 MonoObject *obj = mono_array_get (ctors, gpointer, i);
9095 dgclass->ctors [i] = inflate_method (type, obj);
9098 for (i = 0; i < dgclass->count_fields; i++) {
9099 MonoObject *obj = mono_array_get (fields, gpointer, i);
9100 MonoClassField *field;
9101 MonoInflatedField *ifield;
9103 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
9104 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
9105 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
9106 field = ((MonoReflectionField *) obj)->field;
9107 else {
9108 field = NULL; /* prevent compiler warning */
9109 g_assert_not_reached ();
9112 ifield = g_new0 (MonoInflatedField, 1);
9113 ifield->generic_type = field->type;
9114 MOVING_GC_REGISTER (&ifield->reflection_info);
9115 ifield->reflection_info = obj;
9117 dgclass->fields [i] = *field;
9118 dgclass->fields [i].parent = klass;
9119 dgclass->fields [i].generic_info = ifield;
9120 dgclass->fields [i].type = mono_class_inflate_generic_type (
9121 field->type, dgclass->generic_class.generic_class.context);
9124 for (i = 0; i < dgclass->count_properties; i++) {
9125 MonoObject *obj = mono_array_get (properties, gpointer, i);
9126 MonoProperty *property = &dgclass->properties [i];
9128 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
9129 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
9131 property->parent = klass;
9132 property->attrs = pb->attrs;
9133 property->name = mono_string_to_utf8 (pb->name);
9134 if (pb->get_method)
9135 property->get = inflate_method (type, (MonoObject *) pb->get_method);
9136 if (pb->set_method)
9137 property->set = inflate_method (type, (MonoObject *) pb->set_method);
9138 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
9139 *property = *((MonoReflectionProperty *) obj)->property;
9141 if (property->get)
9142 property->get = inflate_mono_method (type, property->get, NULL);
9143 if (property->set)
9144 property->set = inflate_mono_method (type, property->set, NULL);
9145 } else
9146 g_assert_not_reached ();
9149 for (i = 0; i < dgclass->count_events; i++) {
9150 MonoObject *obj = mono_array_get (events, gpointer, i);
9151 MonoEvent *event = &dgclass->events [i];
9153 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
9154 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
9156 event->parent = klass;
9157 event->attrs = eb->attrs;
9158 event->name = mono_string_to_utf8 (eb->name);
9159 if (eb->add_method)
9160 event->add = inflate_method (type, (MonoObject *) eb->add_method);
9161 if (eb->remove_method)
9162 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
9163 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
9164 *event = *((MonoReflectionEvent *) obj)->event;
9166 if (event->add)
9167 event->add = inflate_mono_method (type, event->add, NULL);
9168 if (event->remove)
9169 event->remove = inflate_mono_method (type, event->remove, NULL);
9170 } else
9171 g_assert_not_reached ();
9174 dgclass->initialized = TRUE;
9177 static void
9178 ensure_runtime_vtable (MonoClass *klass)
9180 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9181 int i, num, j;
9183 if (!tb || klass->wastypebuilder)
9184 return;
9185 if (klass->parent)
9186 ensure_runtime_vtable (klass->parent);
9188 num = tb->ctors? mono_array_length (tb->ctors): 0;
9189 num += tb->num_methods;
9190 klass->method.count = num;
9191 klass->methods = mono_mempool_alloc (klass->image->mempool, sizeof (MonoMethod*) * num);
9192 num = tb->ctors? mono_array_length (tb->ctors): 0;
9193 for (i = 0; i < num; ++i)
9194 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
9195 num = tb->num_methods;
9196 j = i;
9197 for (i = 0; i < num; ++i)
9198 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
9200 if (tb->interfaces) {
9201 klass->interface_count = mono_array_length (tb->interfaces);
9202 klass->interfaces = mono_mempool_alloc (klass->image->mempool, sizeof (MonoClass*) * klass->interface_count);
9203 for (i = 0; i < klass->interface_count; ++i) {
9204 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
9205 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
9209 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
9210 for (i = 0; i < klass->method.count; ++i)
9211 klass->methods [i]->slot = i;
9213 mono_class_setup_interface_offsets (klass);
9217 * The generic vtable is needed even if image->run is not set since some
9218 * runtime code like ves_icall_Type_GetMethodsByName depends on
9219 * method->slot being defined.
9223 * tb->methods could not be freed since it is used for determining
9224 * overrides during dynamic vtable construction.
9228 void
9229 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
9231 MonoReflectionTypeBuilder *tb;
9232 int i, onum;
9234 *overrides = NULL;
9235 *num_overrides = 0;
9237 g_assert (klass->image->dynamic);
9239 if (!klass->reflection_info)
9240 return;
9242 g_assert (strcmp (((MonoObject*)klass->reflection_info)->vtable->klass->name, "TypeBuilder") == 0);
9244 tb = (MonoReflectionTypeBuilder*)klass->reflection_info;
9246 onum = 0;
9247 if (tb->methods) {
9248 for (i = 0; i < tb->num_methods; ++i) {
9249 MonoReflectionMethodBuilder *mb =
9250 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9251 if (mb->override_method)
9252 onum ++;
9256 if (onum) {
9257 *overrides = g_new0 (MonoMethod*, onum * 2);
9259 onum = 0;
9260 for (i = 0; i < tb->num_methods; ++i) {
9261 MonoReflectionMethodBuilder *mb =
9262 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9263 if (mb->override_method) {
9264 (*overrides) [onum * 2] =
9265 mb->override_method->method;
9266 (*overrides) [onum * 2 + 1] =
9267 mb->mhandle;
9269 /* FIXME: What if 'override_method' is a MethodBuilder ? */
9270 g_assert (mb->override_method->method);
9271 g_assert (mb->mhandle);
9273 onum ++;
9278 *num_overrides = onum;
9281 static void
9282 typebuilder_setup_fields (MonoClass *klass)
9284 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9285 MonoReflectionFieldBuilder *fb;
9286 MonoClassField *field;
9287 const char *p, *p2;
9288 int i;
9289 guint32 len, idx;
9291 klass->field.count = tb->num_fields;
9292 klass->field.first = 0;
9294 if (!klass->field.count)
9295 return;
9297 klass->fields = g_new0 (MonoClassField, klass->field.count);
9299 for (i = 0; i < klass->field.count; ++i) {
9300 fb = mono_array_get (tb->fields, gpointer, i);
9301 field = &klass->fields [i];
9302 field->name = mono_string_to_utf8 (fb->name);
9303 if (fb->attrs) {
9304 /* FIXME: handle type modifiers */
9305 field->type = g_memdup (fb->type->type, sizeof (MonoType));
9306 field->type->attrs = fb->attrs;
9307 } else {
9308 field->type = fb->type->type;
9310 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
9311 field->data = mono_array_addr (fb->rva_data, char, 0);
9312 if (fb->offset != -1)
9313 field->offset = fb->offset;
9314 field->parent = klass;
9315 fb->handle = field;
9316 mono_save_custom_attrs (klass->image, field, fb->cattrs);
9318 if (fb->def_value) {
9319 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
9320 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
9321 idx = encode_constant (assembly, fb->def_value, &field->def_type);
9322 /* Copy the data from the blob since it might get realloc-ed */
9323 p = assembly->blob.data + idx;
9324 len = mono_metadata_decode_blob_size (p, &p2);
9325 len += p2 - p;
9326 field->data = g_malloc (len);
9327 memcpy ((gpointer)field->data, p, len);
9330 mono_class_layout_fields (klass);
9333 static void
9334 typebuilder_setup_properties (MonoClass *klass)
9336 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9337 MonoReflectionPropertyBuilder *pb;
9338 int i;
9340 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
9341 klass->property.first = 0;
9343 klass->properties = g_new0 (MonoProperty, klass->property.count);
9344 for (i = 0; i < klass->property.count; ++i) {
9345 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
9346 klass->properties [i].parent = klass;
9347 klass->properties [i].attrs = pb->attrs;
9348 klass->properties [i].name = mono_string_to_utf8 (pb->name);
9349 if (pb->get_method)
9350 klass->properties [i].get = pb->get_method->mhandle;
9351 if (pb->set_method)
9352 klass->properties [i].set = pb->set_method->mhandle;
9354 mono_save_custom_attrs (klass->image, &klass->properties [i], pb->cattrs);
9358 MonoReflectionEvent *
9359 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
9361 MonoEvent *event = g_new0 (MonoEvent, 1);
9362 MonoClass *klass;
9363 int j;
9365 klass = my_mono_class_from_mono_type (tb->type.type);
9367 event->parent = klass;
9368 event->attrs = eb->attrs;
9369 event->name = mono_string_to_utf8 (eb->name);
9370 if (eb->add_method)
9371 event->add = eb->add_method->mhandle;
9372 if (eb->remove_method)
9373 event->remove = eb->remove_method->mhandle;
9374 if (eb->raise_method)
9375 event->raise = eb->raise_method->mhandle;
9377 if (eb->other_methods) {
9378 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
9379 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
9380 MonoReflectionMethodBuilder *mb =
9381 mono_array_get (eb->other_methods,
9382 MonoReflectionMethodBuilder*, j);
9383 event->other [j] = mb->mhandle;
9387 return mono_event_get_object (mono_object_domain (tb), klass, event);
9390 static void
9391 typebuilder_setup_events (MonoClass *klass)
9393 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9394 MonoReflectionEventBuilder *eb;
9395 int i, j;
9397 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
9398 klass->event.first = 0;
9400 klass->events = g_new0 (MonoEvent, klass->event.count);
9401 for (i = 0; i < klass->event.count; ++i) {
9402 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
9403 klass->events [i].parent = klass;
9404 klass->events [i].attrs = eb->attrs;
9405 klass->events [i].name = mono_string_to_utf8 (eb->name);
9406 if (eb->add_method)
9407 klass->events [i].add = eb->add_method->mhandle;
9408 if (eb->remove_method)
9409 klass->events [i].remove = eb->remove_method->mhandle;
9410 if (eb->raise_method)
9411 klass->events [i].raise = eb->raise_method->mhandle;
9413 if (eb->other_methods) {
9414 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
9415 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
9416 MonoReflectionMethodBuilder *mb =
9417 mono_array_get (eb->other_methods,
9418 MonoReflectionMethodBuilder*, j);
9419 klass->events [i].other [j] = mb->mhandle;
9425 MonoReflectionType*
9426 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
9428 MonoClass *klass;
9429 MonoDomain* domain;
9430 MonoReflectionType* res;
9431 int i;
9433 MONO_ARCH_SAVE_REGS;
9435 domain = mono_object_domain (tb);
9436 klass = my_mono_class_from_mono_type (tb->type.type);
9438 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
9441 * we need to lock the domain because the lock will be taken inside
9442 * So, we need to keep the locking order correct.
9444 mono_domain_lock (domain);
9445 mono_loader_lock ();
9446 if (klass->wastypebuilder) {
9447 mono_loader_unlock ();
9448 mono_domain_unlock (domain);
9449 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9452 * Fields to set in klass:
9453 * the various flags: delegate/unicode/contextbound etc.
9455 klass->flags = tb->attrs;
9456 klass->has_cctor = 1;
9457 klass->has_finalize = 1;
9459 #if 0
9460 if (!((MonoDynamicImage*)klass->image)->run) {
9461 if (klass->generic_container) {
9462 /* FIXME: The code below can't handle generic classes */
9463 klass->wastypebuilder = TRUE;
9464 mono_loader_unlock ();
9465 mono_domain_unlock (domain);
9466 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9469 #endif
9471 /* enums are done right away */
9472 if (!klass->enumtype)
9473 ensure_runtime_vtable (klass);
9475 if (tb->subtypes) {
9476 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
9477 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
9478 klass->nested_classes = g_list_prepend (klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
9482 /* fields and object layout */
9483 if (klass->parent) {
9484 if (!klass->parent->size_inited)
9485 mono_class_init (klass->parent);
9486 klass->instance_size = klass->parent->instance_size;
9487 klass->sizes.class_size = 0;
9488 klass->min_align = klass->parent->min_align;
9489 /* if the type has no fields we won't call the field_setup
9490 * routine which sets up klass->has_references.
9492 klass->has_references |= klass->parent->has_references;
9493 } else {
9494 klass->instance_size = sizeof (MonoObject);
9495 klass->min_align = 1;
9498 /* FIXME: handle packing_size and instance_size */
9499 typebuilder_setup_fields (klass);
9501 typebuilder_setup_properties (klass);
9503 typebuilder_setup_events (klass);
9505 klass->wastypebuilder = TRUE;
9506 mono_loader_unlock ();
9507 mono_domain_unlock (domain);
9509 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9510 g_assert (res != (MonoReflectionType*)tb);
9512 return res;
9515 void
9516 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
9518 MonoGenericParam *param;
9519 MonoImage *image;
9521 MONO_ARCH_SAVE_REGS;
9523 param = g_new0 (MonoGenericParam, 1);
9525 if (gparam->mbuilder) {
9526 if (!gparam->mbuilder->generic_container)
9527 gparam->mbuilder->generic_container = g_new0 (MonoGenericContainer, 1);
9528 param->owner = gparam->mbuilder->generic_container;
9529 } else if (gparam->tbuilder) {
9530 g_assert (gparam->tbuilder->generic_container);
9531 param->owner = gparam->tbuilder->generic_container;
9534 param->method = NULL;
9535 param->name = mono_string_to_utf8 (gparam->name);
9536 param->num = gparam->index;
9538 image = &gparam->tbuilder->module->dynamic_image->image;
9539 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
9541 MOVING_GC_REGISTER (&param->pklass->reflection_info);
9542 param->pklass->reflection_info = gparam; /* FIXME: GC pin gparam */
9544 gparam->type.type = g_new0 (MonoType, 1);
9545 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
9546 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
9547 gparam->type.type->data.generic_param = param;
9550 MonoArray *
9551 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
9553 MonoDynamicImage *assembly = sig->module->dynamic_image;
9554 guint32 na = mono_array_length (sig->arguments);
9555 guint32 buflen, i, size;
9556 MonoArray *result;
9557 char *buf, *p;
9559 MONO_ARCH_SAVE_REGS;
9561 p = buf = g_malloc (size = 50 + na * 50);
9563 mono_metadata_encode_value (0x07, p, &p);
9564 mono_metadata_encode_value (na, p, &p);
9565 for (i = 0; i < na; ++i) {
9566 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
9567 encode_reflection_type (assembly, type, p, &p);
9570 buflen = p - buf;
9571 g_assert (buflen < size);
9572 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9573 p = mono_array_addr (result, char, 0);
9574 memcpy (p, buf, buflen);
9575 g_free (buf);
9577 return result;
9580 MonoArray *
9581 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
9583 MonoDynamicImage *assembly = sig->module->dynamic_image;
9584 guint32 na = mono_array_length (sig->arguments);
9585 guint32 buflen, i, size;
9586 MonoArray *result;
9587 char *buf, *p;
9589 MONO_ARCH_SAVE_REGS;
9591 p = buf = g_malloc (size = 10 + na * 10);
9593 mono_metadata_encode_value (0x06, p, &p);
9594 for (i = 0; i < na; ++i) {
9595 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
9596 encode_reflection_type (assembly, type, p, &p);
9599 buflen = p - buf;
9600 g_assert (buflen < size);
9601 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9602 p = mono_array_addr (result, char, 0);
9603 memcpy (p, buf, buflen);
9604 g_free (buf);
9606 return result;
9609 void
9610 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
9612 ReflectionMethodBuilder rmb;
9613 MonoMethodSignature *sig;
9614 int i;
9616 sig = dynamic_method_to_signature (mb);
9618 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
9621 * Resolve references.
9624 * Every second entry in the refs array is reserved for storing handle_class,
9625 * which is needed by the ldtoken implementation in the JIT.
9627 rmb.nrefs = mb->nrefs;
9628 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
9629 for (i = 0; i < mb->nrefs; i += 2) {
9630 MonoClass *handle_class;
9631 gpointer ref = resolve_object (mb->module->image,
9632 mono_array_get (mb->refs, MonoObject*, i), &handle_class);
9633 if (!ref) {
9634 g_free (rmb.refs);
9635 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
9636 return;
9638 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
9639 rmb.refs [i + 1] = handle_class;
9642 /* FIXME: class */
9643 mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
9645 g_free (rmb.refs);
9647 /* ilgen is no longer needed */
9648 mb->ilgen = NULL;
9652 * mono_reflection_lookup_dynamic_token:
9654 * Finish the Builder object pointed to by TOKEN and return the corresponding
9655 * runtime structure. HANDLE_CLASS is set to the class required by
9656 * mono_ldtoken.
9658 gpointer
9659 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, MonoClass **handle_class)
9661 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
9662 MonoObject *obj;
9664 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
9665 g_assert (obj);
9667 return resolve_object (image, obj, handle_class);
9670 static gpointer
9671 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class)
9673 gpointer result = NULL;
9675 if (strcmp (obj->vtable->klass->name, "String") == 0) {
9676 result = mono_string_intern ((MonoString*)obj);
9677 *handle_class = NULL;
9678 g_assert (result);
9679 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
9680 MonoReflectionType *tb = (MonoReflectionType*)obj;
9681 result = mono_class_from_mono_type (tb->type);
9682 *handle_class = mono_defaults.typehandle_class;
9683 g_assert (result);
9684 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
9685 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
9686 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
9687 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
9688 result = ((MonoReflectionMethod*)obj)->method;
9689 *handle_class = mono_defaults.methodhandle_class;
9690 g_assert (result);
9691 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
9692 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
9693 result = mb->mhandle;
9694 if (!result) {
9695 /* Type is not yet created */
9696 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
9698 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9701 * Hopefully this has been filled in by calling CreateType() on the
9702 * TypeBuilder.
9705 * TODO: This won't work if the application finishes another
9706 * TypeBuilder instance instead of this one.
9708 result = mb->mhandle;
9710 *handle_class = mono_defaults.methodhandle_class;
9711 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
9712 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
9714 result = cb->mhandle;
9715 if (!result) {
9716 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
9718 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9719 result = cb->mhandle;
9721 *handle_class = mono_defaults.methodhandle_class;
9722 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
9723 result = ((MonoReflectionField*)obj)->field;
9724 *handle_class = mono_defaults.fieldhandle_class;
9725 g_assert (result);
9726 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
9727 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
9728 result = fb->handle;
9730 if (!result) {
9731 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
9733 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9734 result = fb->handle;
9736 *handle_class = mono_defaults.fieldhandle_class;
9737 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
9738 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
9739 MonoClass *klass;
9741 klass = tb->type.type->data.klass;
9742 if (klass->wastypebuilder) {
9743 /* Already created */
9744 result = klass;
9746 else {
9747 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9748 result = tb->type.type->data.klass;
9749 g_assert (result);
9751 *handle_class = mono_defaults.typehandle_class;
9752 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
9753 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
9754 MonoMethodSignature *sig;
9755 int nargs, i;
9757 if (helper->arguments)
9758 nargs = mono_array_length (helper->arguments);
9759 else
9760 nargs = 0;
9762 sig = mono_metadata_signature_alloc (image, nargs);
9763 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
9764 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
9766 if (helper->call_conv == 0) /* unmanaged */
9767 sig->call_convention = helper->unmanaged_call_conv - 1;
9768 else
9769 if (helper->call_conv & 0x02)
9770 sig->call_convention = MONO_CALL_VARARG;
9771 else
9772 sig->call_convention = MONO_CALL_DEFAULT;
9774 sig->param_count = nargs;
9775 /* TODO: Copy type ? */
9776 sig->ret = helper->return_type->type;
9777 for (i = 0; i < nargs; ++i) {
9778 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
9779 sig->params [i] = rt->type;
9782 result = sig;
9783 *handle_class = NULL;
9784 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
9785 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
9786 /* Already created by the managed code */
9787 g_assert (method->mhandle);
9788 result = method->mhandle;
9789 *handle_class = mono_defaults.methodhandle_class;
9790 } else {
9791 g_print (obj->vtable->klass->name);
9792 g_assert_not_reached ();
9794 return result;
9798 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
9799 const static guint32 declsec_flags_map[] = {
9800 0x00000000, /* empty */
9801 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
9802 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
9803 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
9804 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
9805 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
9806 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
9807 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
9808 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
9809 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
9810 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
9811 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
9812 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
9813 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
9814 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
9815 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
9816 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
9817 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
9818 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
9822 * Returns flags that includes all available security action associated to the handle.
9823 * @token: metadata token (either for a class or a method)
9824 * @image: image where resides the metadata.
9826 static guint32
9827 mono_declsec_get_flags (MonoImage *image, guint32 token)
9829 guint32 index = mono_metadata_declsec_from_index (image, token);
9830 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
9831 guint32 result = 0;
9832 guint32 action;
9833 int i;
9835 for (i = index; i < t->rows; i++) {
9836 guint32 cols [MONO_DECL_SECURITY_SIZE];
9838 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
9839 if (cols [MONO_DECL_SECURITY_PARENT] != token)
9840 break;
9842 action = cols [MONO_DECL_SECURITY_ACTION];
9843 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
9844 result |= declsec_flags_map [action];
9845 } else {
9846 g_assert_not_reached ();
9849 return result;
9853 * Get the security actions (in the form of flags) associated with the specified method.
9855 * @method: The method for which we want the declarative security flags.
9856 * Return the declarative security flags for the method (only).
9858 * Note: To keep MonoMethod size down we do not cache the declarative security flags
9859 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
9861 guint32
9862 mono_declsec_flags_from_method (MonoMethod *method)
9864 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9865 /* FIXME: No cache (for the moment) */
9866 guint32 idx = mono_method_get_index (method);
9867 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9868 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
9869 return mono_declsec_get_flags (method->klass->image, idx);
9871 return 0;
9875 * Get the security actions (in the form of flags) associated with the specified class.
9877 * @klass: The class for which we want the declarative security flags.
9878 * Return the declarative security flags for the class.
9880 * Note: We cache the flags inside the MonoClass structure as this will get
9881 * called very often (at least for each method).
9883 guint32
9884 mono_declsec_flags_from_class (MonoClass *klass)
9886 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
9887 if (!klass->declsec_flags) {
9888 guint32 idx = mono_metadata_token_index (klass->type_token);
9889 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9890 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
9891 /* we cache the flags on classes */
9892 klass->declsec_flags = mono_declsec_get_flags (klass->image, idx);
9894 return klass->declsec_flags;
9896 return 0;
9900 * Get the security actions (in the form of flags) associated with the specified assembly.
9902 * @assembly: The assembly for which we want the declarative security flags.
9903 * Return the declarative security flags for the assembly.
9905 guint32
9906 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
9908 guint32 idx = 1; /* there is only one assembly */
9909 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9910 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
9911 return mono_declsec_get_flags (assembly->image, idx);
9916 * Fill actions for the specific index (which may either be an encoded class token or
9917 * an encoded method token) from the metadata image.
9918 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
9920 static MonoBoolean
9921 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
9922 guint32 id_std, guint32 id_noncas, guint32 id_choice)
9924 MonoBoolean result = FALSE;
9925 MonoTableInfo *t;
9926 guint32 cols [MONO_DECL_SECURITY_SIZE];
9927 int index = mono_metadata_declsec_from_index (image, token);
9928 int i;
9930 t = &image->tables [MONO_TABLE_DECLSECURITY];
9931 for (i = index; i < t->rows; i++) {
9932 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
9934 if (cols [MONO_DECL_SECURITY_PARENT] != token)
9935 return result;
9937 /* if present only replace (class) permissions with method permissions */
9938 /* if empty accept either class or method permissions */
9939 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
9940 if (!actions->demand.blob) {
9941 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9942 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9943 actions->demand.blob = (char*) (blob + 2);
9944 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
9945 result = TRUE;
9947 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
9948 if (!actions->noncasdemand.blob) {
9949 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9950 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9951 actions->noncasdemand.blob = (char*) (blob + 2);
9952 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
9953 result = TRUE;
9955 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
9956 if (!actions->demandchoice.blob) {
9957 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9958 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9959 actions->demandchoice.blob = (char*) (blob + 2);
9960 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
9961 result = TRUE;
9966 return result;
9969 static MonoBoolean
9970 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
9971 guint32 id_std, guint32 id_noncas, guint32 id_choice)
9973 guint32 idx = mono_metadata_token_index (klass->type_token);
9974 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9975 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
9976 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
9979 static MonoBoolean
9980 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
9981 guint32 id_std, guint32 id_noncas, guint32 id_choice)
9983 guint32 idx = mono_method_get_index (method);
9984 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9985 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
9986 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
9990 * Collect all actions (that requires to generate code in mini) assigned for
9991 * the specified method.
9992 * Note: Don't use the content of actions if the function return FALSE.
9994 MonoBoolean
9995 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
9997 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
9998 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
9999 MonoBoolean result = FALSE;
10000 guint32 flags;
10002 /* quick exit if no declarative security is present in the metadata */
10003 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10004 return FALSE;
10006 /* we want the original as the wrapper is "free" of the security informations */
10007 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
10008 method = mono_marshal_method_from_wrapper (method);
10009 if (!method)
10010 return FALSE;
10013 /* First we look for method-level attributes */
10014 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10015 mono_class_init (method->klass);
10016 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10018 result = mono_declsec_get_method_demands_params (method, demands,
10019 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
10022 /* Here we use (or create) the class declarative cache to look for demands */
10023 flags = mono_declsec_flags_from_class (method->klass);
10024 if (flags & mask) {
10025 if (!result) {
10026 mono_class_init (method->klass);
10027 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10029 result |= mono_declsec_get_class_demands_params (method->klass, demands,
10030 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
10033 /* The boolean return value is used as a shortcut in case nothing needs to
10034 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
10035 return result;
10040 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
10042 * Note: Don't use the content of actions if the function return FALSE.
10044 MonoBoolean
10045 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
10047 MonoBoolean result = FALSE;
10048 guint32 flags;
10050 /* quick exit if no declarative security is present in the metadata */
10051 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10052 return FALSE;
10054 /* we want the original as the wrapper is "free" of the security informations */
10055 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
10056 method = mono_marshal_method_from_wrapper (method);
10057 if (!method)
10058 return FALSE;
10061 /* results are independant - zeroize both */
10062 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
10063 memset (klass, 0, sizeof (MonoDeclSecurityActions));
10065 /* First we look for method-level attributes */
10066 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10067 mono_class_init (method->klass);
10069 result = mono_declsec_get_method_demands_params (method, cmethod,
10070 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
10073 /* Here we use (or create) the class declarative cache to look for demands */
10074 flags = mono_declsec_flags_from_class (method->klass);
10075 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
10076 mono_class_init (method->klass);
10078 result |= mono_declsec_get_class_demands_params (method->klass, klass,
10079 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
10082 return result;
10086 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
10088 * @klass The inherited class - this is the class that provides the security check (attributes)
10089 * @demans
10090 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
10092 * Note: Don't use the content of actions if the function return FALSE.
10094 MonoBoolean
10095 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
10097 MonoBoolean result = FALSE;
10098 guint32 flags;
10100 /* quick exit if no declarative security is present in the metadata */
10101 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10102 return FALSE;
10104 /* Here we use (or create) the class declarative cache to look for demands */
10105 flags = mono_declsec_flags_from_class (klass);
10106 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
10107 mono_class_init (klass);
10108 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10110 result |= mono_declsec_get_class_demands_params (klass, demands,
10111 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
10114 return result;
10118 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
10120 * Note: Don't use the content of actions if the function return FALSE.
10122 MonoBoolean
10123 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
10125 /* quick exit if no declarative security is present in the metadata */
10126 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10127 return FALSE;
10129 /* we want the original as the wrapper is "free" of the security informations */
10130 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
10131 method = mono_marshal_method_from_wrapper (method);
10132 if (!method)
10133 return FALSE;
10136 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10137 mono_class_init (method->klass);
10138 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10140 return mono_declsec_get_method_demands_params (method, demands,
10141 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
10143 return FALSE;
10147 static MonoBoolean
10148 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
10150 guint32 cols [MONO_DECL_SECURITY_SIZE];
10151 MonoTableInfo *t;
10152 int i;
10154 int index = mono_metadata_declsec_from_index (image, token);
10155 if (index == -1)
10156 return FALSE;
10158 t = &image->tables [MONO_TABLE_DECLSECURITY];
10159 for (i = index; i < t->rows; i++) {
10160 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
10162 /* shortcut - index are ordered */
10163 if (token != cols [MONO_DECL_SECURITY_PARENT])
10164 return FALSE;
10166 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
10167 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10168 entry->blob = (char*) (metadata + 2);
10169 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
10170 return TRUE;
10174 return FALSE;
10177 MonoBoolean
10178 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
10180 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10181 guint32 idx = mono_method_get_index (method);
10182 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10183 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
10184 return get_declsec_action (method->klass->image, idx, action, entry);
10186 return FALSE;
10189 MonoBoolean
10190 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
10192 /* use cache */
10193 guint32 flags = mono_declsec_flags_from_class (klass);
10194 if (declsec_flags_map [action] & flags) {
10195 guint32 idx = mono_metadata_token_index (klass->type_token);
10196 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10197 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
10198 return get_declsec_action (klass->image, idx, action, entry);
10200 return FALSE;
10203 MonoBoolean
10204 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
10206 guint32 idx = 1; /* there is only one assembly */
10207 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10208 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
10210 return get_declsec_action (assembly->image, idx, action, entry);
10213 gboolean
10214 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
10216 MonoObject *res, *exc;
10217 void *params [1];
10218 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
10219 static MonoMethod *method = NULL;
10221 if (!System_Reflection_Emit_TypeBuilder) {
10222 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
10223 g_assert (System_Reflection_Emit_TypeBuilder);
10225 if (method == NULL) {
10226 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
10227 g_assert (method);
10231 * The result of mono_type_get_object () might be a System.MonoType but we
10232 * need a TypeBuilder so use klass->reflection_info.
10234 g_assert (klass->reflection_info);
10235 g_assert (!strcmp (((MonoObject*)(klass->reflection_info))->vtable->klass->name, "TypeBuilder"));
10237 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
10239 res = mono_runtime_invoke (method, (MonoObject*)(klass->reflection_info), params, &exc);
10240 if (exc)
10241 return FALSE;
10242 else
10243 return *(MonoBoolean*)mono_object_unbox (res);