[runtime] Make mono_value_box use MonoError
[mono-project.git] / mono / metadata / reflection.c
blob4bdb89cf00704cd76f54f1bc5dd3972104a632b0
1 /*
2 * reflection.c: Routines for creating an image at runtime.
3 *
4 * Author:
5 * Paolo Molaro (lupus@ximian.com)
7 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9 * Copyright 2011 Rodrigo Kumpera
12 #include <config.h>
13 #include "mono/utils/mono-digest.h"
14 #include "mono/utils/mono-membar.h"
15 #include "mono/metadata/reflection-internals.h"
16 #include "mono/metadata/tabledefs.h"
17 #include "mono/metadata/metadata-internals.h"
18 #include <mono/metadata/profiler-private.h>
19 #include "mono/metadata/class-internals.h"
20 #include "mono/metadata/gc-internals.h"
21 #include "mono/metadata/tokentype.h"
22 #include "mono/metadata/domain-internals.h"
23 #include "mono/metadata/opcodes.h"
24 #include "mono/metadata/assembly.h"
25 #include "mono/metadata/object-internals.h"
26 #include <mono/metadata/exception.h>
27 #include <mono/metadata/marshal.h>
28 #include <mono/metadata/security-manager.h>
29 #include <stdio.h>
30 #include <glib.h>
31 #include <errno.h>
32 #include <time.h>
33 #include <string.h>
34 #include <ctype.h>
35 #include "image.h"
36 #include "cil-coff.h"
37 #include "mono-endian.h"
38 #include <mono/metadata/gc-internals.h>
39 #include <mono/metadata/mempool-internals.h>
40 #include <mono/metadata/security-core-clr.h>
41 #include <mono/metadata/debug-helpers.h>
42 #include <mono/metadata/verify-internals.h>
43 #include <mono/metadata/mono-ptr-array.h>
44 #include <mono/utils/mono-string.h>
45 #include <mono/utils/mono-error-internals.h>
46 #include <mono/utils/checked-build.h>
48 static gboolean is_usertype (MonoReflectionType *ref);
49 static MonoReflectionType *mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error);
51 typedef struct {
52 char *p;
53 char *buf;
54 char *end;
55 } SigBuffer;
57 #define TEXT_OFFSET 512
58 #define CLI_H_SIZE 136
59 #define FILE_ALIGN 512
60 #define VIRT_ALIGN 8192
61 #define START_TEXT_RVA 0x00002000
63 typedef struct {
64 MonoReflectionILGen *ilgen;
65 MonoReflectionType *rtype;
66 MonoArray *parameters;
67 MonoArray *generic_params;
68 MonoGenericContainer *generic_container;
69 MonoArray *pinfo;
70 MonoArray *opt_types;
71 guint32 attrs;
72 guint32 iattrs;
73 guint32 call_conv;
74 guint32 *table_idx; /* note: it's a pointer */
75 MonoArray *code;
76 MonoObject *type;
77 MonoString *name;
78 MonoBoolean init_locals;
79 MonoBoolean skip_visibility;
80 MonoArray *return_modreq;
81 MonoArray *return_modopt;
82 MonoArray *param_modreq;
83 MonoArray *param_modopt;
84 MonoArray *permissions;
85 MonoMethod *mhandle;
86 guint32 nrefs;
87 gpointer *refs;
88 /* for PInvoke */
89 int charset, extra_flags, native_cc;
90 MonoString *dll, *dllentry;
91 } ReflectionMethodBuilder;
93 typedef struct {
94 guint32 owner;
95 MonoReflectionGenericParam *gparam;
96 } GenericParamTableEntry;
98 const unsigned char table_sizes [MONO_TABLE_NUM] = {
99 MONO_MODULE_SIZE,
100 MONO_TYPEREF_SIZE,
101 MONO_TYPEDEF_SIZE,
103 MONO_FIELD_SIZE,
105 MONO_METHOD_SIZE,
107 MONO_PARAM_SIZE,
108 MONO_INTERFACEIMPL_SIZE,
109 MONO_MEMBERREF_SIZE, /* 0x0A */
110 MONO_CONSTANT_SIZE,
111 MONO_CUSTOM_ATTR_SIZE,
112 MONO_FIELD_MARSHAL_SIZE,
113 MONO_DECL_SECURITY_SIZE,
114 MONO_CLASS_LAYOUT_SIZE,
115 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
116 MONO_STAND_ALONE_SIGNATURE_SIZE,
117 MONO_EVENT_MAP_SIZE,
119 MONO_EVENT_SIZE,
120 MONO_PROPERTY_MAP_SIZE,
122 MONO_PROPERTY_SIZE,
123 MONO_METHOD_SEMA_SIZE,
124 MONO_METHODIMPL_SIZE,
125 MONO_MODULEREF_SIZE, /* 0x1A */
126 MONO_TYPESPEC_SIZE,
127 MONO_IMPLMAP_SIZE,
128 MONO_FIELD_RVA_SIZE,
131 MONO_ASSEMBLY_SIZE, /* 0x20 */
132 MONO_ASSEMBLY_PROCESSOR_SIZE,
133 MONO_ASSEMBLYOS_SIZE,
134 MONO_ASSEMBLYREF_SIZE,
135 MONO_ASSEMBLYREFPROC_SIZE,
136 MONO_ASSEMBLYREFOS_SIZE,
137 MONO_FILE_SIZE,
138 MONO_EXP_TYPE_SIZE,
139 MONO_MANIFEST_SIZE,
140 MONO_NESTED_CLASS_SIZE,
142 MONO_GENERICPARAM_SIZE, /* 0x2A */
143 MONO_METHODSPEC_SIZE,
144 MONO_GENPARCONSTRAINT_SIZE
148 #ifndef DISABLE_REFLECTION_EMIT
149 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
150 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_open_instance, MonoError *error);
151 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb, MonoError *error);
152 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error);
153 static gboolean ensure_runtime_vtable (MonoClass *klass, MonoError *error);
154 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context, MonoError *error);
155 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method, MonoError *error);
156 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
157 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
158 static gboolean reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error);
159 static gboolean reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error);
160 static guint32 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error);
161 #endif
163 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
164 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
165 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
166 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo, MonoError *error);
167 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
168 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
169 static void encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
170 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
171 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error);
172 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error);
173 static MonoReflectionType* mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error);
174 static gboolean is_sre_array (MonoClass *klass);
175 static gboolean is_sre_byref (MonoClass *klass);
176 static gboolean is_sre_pointer (MonoClass *klass);
177 static gboolean is_sre_type_builder (MonoClass *klass);
178 static gboolean is_sre_method_builder (MonoClass *klass);
179 static gboolean is_sre_ctor_builder (MonoClass *klass);
180 static gboolean is_sre_field_builder (MonoClass *klass);
181 static gboolean is_sr_mono_method (MonoClass *klass);
182 static gboolean is_sr_mono_cmethod (MonoClass *klass);
183 static gboolean is_sr_mono_generic_method (MonoClass *klass);
184 static gboolean is_sr_mono_generic_cmethod (MonoClass *klass);
185 static gboolean is_sr_mono_field (MonoClass *klass);
186 static gboolean is_sr_mono_property (MonoClass *klass);
187 static gboolean is_sre_method_on_tb_inst (MonoClass *klass);
188 static gboolean is_sre_ctor_on_tb_inst (MonoClass *klass);
190 static gboolean type_is_reference (MonoType *type);
192 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
193 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
194 static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error);
196 static guint32 create_typespec (MonoDynamicImage *assembly, MonoType *type);
197 static void init_type_builder_generics (MonoObject *type);
199 #define RESOLVE_TYPE(type, error) do { \
200 type = (MonoObject *)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type, error); \
201 } while (0)
202 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index, error) do { \
203 MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index); \
204 __type = mono_reflection_type_resolve_user_types (__type, error); \
205 if (mono_error_ok (error)) \
206 mono_array_set (arr, MonoReflectionType*, index, __type); \
207 } while (0)
209 #define mono_type_array_get_and_resolve(array, index, error) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index), error)
211 #define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
212 #define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
214 #if SIZEOF_VOID_P == 4
215 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
216 #else
217 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
218 #endif
220 #define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
221 #define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
223 /* Class lazy loading functions */
224 static GENERATE_GET_CLASS_WITH_CACHE (mono_assembly, System.Reflection, MonoAssembly)
225 static GENERATE_GET_CLASS_WITH_CACHE (mono_module, System.Reflection, MonoModule)
226 static GENERATE_GET_CLASS_WITH_CACHE (mono_generic_method, System.Reflection, MonoGenericMethod);
227 static GENERATE_GET_CLASS_WITH_CACHE (mono_generic_cmethod, System.Reflection, MonoGenericCMethod);
228 static GENERATE_GET_CLASS_WITH_CACHE (mono_method, System.Reflection, MonoMethod);
229 static GENERATE_GET_CLASS_WITH_CACHE (mono_cmethod, System.Reflection, MonoCMethod);
230 static GENERATE_GET_CLASS_WITH_CACHE (mono_field, System.Reflection, MonoField);
231 static GENERATE_GET_CLASS_WITH_CACHE (mono_event, System.Reflection, MonoEvent);
232 static GENERATE_GET_CLASS_WITH_CACHE (mono_property, System.Reflection, MonoProperty);
233 static GENERATE_GET_CLASS_WITH_CACHE (mono_parameter_info, System.Reflection, MonoParameterInfo);
234 static GENERATE_GET_CLASS_WITH_CACHE (missing, System.Reflection, Missing);
235 static GENERATE_GET_CLASS_WITH_CACHE (method_body, System.Reflection, MethodBody);
236 static GENERATE_GET_CLASS_WITH_CACHE (local_variable_info, System.Reflection, LocalVariableInfo);
237 static GENERATE_GET_CLASS_WITH_CACHE (exception_handling_clause, System.Reflection, ExceptionHandlingClause);
238 static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_typed_argument, System.Reflection, CustomAttributeTypedArgument);
239 static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_named_argument, System.Reflection, CustomAttributeNamedArgument);
240 static GENERATE_GET_CLASS_WITH_CACHE (type_builder, System.Reflection.Emit, TypeBuilder);
241 static GENERATE_GET_CLASS_WITH_CACHE (marshal_as_attribute, System.Runtime.InteropServices, MarshalAsAttribute);
242 static GENERATE_GET_CLASS_WITH_CACHE (dbnull, System, DBNull);
244 // The dynamic images list is only needed to support the mempool reference tracking feature in checked-build.
245 static GPtrArray *dynamic_images;
246 static mono_mutex_t dynamic_images_mutex;
248 static inline void
249 dynamic_images_lock (void)
251 mono_os_mutex_lock (&dynamic_images_mutex);
254 static inline void
255 dynamic_images_unlock (void)
257 mono_os_mutex_unlock (&dynamic_images_mutex);
261 * mono_find_dynamic_image_owner:
263 * Find the dynamic image, if any, which a given pointer is located in the memory of.
265 MonoImage *
266 mono_find_dynamic_image_owner (void *ptr)
268 MonoImage *owner = NULL;
269 int i;
271 dynamic_images_lock ();
273 if (dynamic_images)
275 for (i = 0; !owner && i < dynamic_images->len; ++i) {
276 MonoImage *image = (MonoImage *)g_ptr_array_index (dynamic_images, i);
277 if (mono_mempool_contains_addr (image->mempool, ptr))
278 owner = image;
282 dynamic_images_unlock ();
284 return owner;
287 void
288 mono_reflection_init (void)
290 mono_os_mutex_init (&dynamic_images_mutex);
293 static inline void
294 dynamic_image_lock (MonoDynamicImage *image)
296 MONO_PREPARE_BLOCKING;
297 mono_image_lock ((MonoImage*)image);
298 MONO_FINISH_BLOCKING;
301 static inline void
302 dynamic_image_unlock (MonoDynamicImage *image)
304 mono_image_unlock ((MonoImage*)image);
307 static void
308 register_dyn_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
310 MONO_REQ_GC_UNSAFE_MODE;
312 dynamic_image_lock (assembly);
313 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
314 dynamic_image_unlock (assembly);
317 static MonoObject*
318 lookup_dyn_token (MonoDynamicImage *assembly, guint32 token)
320 MONO_REQ_GC_UNSAFE_MODE;
322 MonoObject *obj;
324 dynamic_image_lock (assembly);
325 obj = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
326 dynamic_image_unlock (assembly);
328 return obj;
331 static void
332 sigbuffer_init (SigBuffer *buf, int size)
334 MONO_REQ_GC_NEUTRAL_MODE;
336 buf->buf = (char *)g_malloc (size);
337 buf->p = buf->buf;
338 buf->end = buf->buf + size;
341 static void
342 sigbuffer_make_room (SigBuffer *buf, int size)
344 MONO_REQ_GC_NEUTRAL_MODE;
346 if (buf->end - buf->p < size) {
347 int new_size = buf->end - buf->buf + size + 32;
348 char *p = (char *)g_realloc (buf->buf, new_size);
349 size = buf->p - buf->buf;
350 buf->buf = p;
351 buf->p = p + size;
352 buf->end = buf->buf + new_size;
356 static void
357 sigbuffer_add_value (SigBuffer *buf, guint32 val)
359 MONO_REQ_GC_NEUTRAL_MODE;
361 sigbuffer_make_room (buf, 6);
362 mono_metadata_encode_value (val, buf->p, &buf->p);
365 static void
366 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
368 MONO_REQ_GC_NEUTRAL_MODE;
370 sigbuffer_make_room (buf, 1);
371 buf->p [0] = val;
372 buf->p++;
375 static void
376 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
378 MONO_REQ_GC_NEUTRAL_MODE;
380 sigbuffer_make_room (buf, size);
381 memcpy (buf->p, p, size);
382 buf->p += size;
385 static void
386 sigbuffer_free (SigBuffer *buf)
388 MONO_REQ_GC_NEUTRAL_MODE;
390 g_free (buf->buf);
393 #ifndef DISABLE_REFLECTION_EMIT
395 * mp_g_alloc:
397 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
398 * from the C heap.
400 static gpointer
401 image_g_malloc (MonoImage *image, guint size)
403 MONO_REQ_GC_NEUTRAL_MODE;
405 if (image)
406 return mono_image_alloc (image, size);
407 else
408 return g_malloc (size);
410 #endif /* !DISABLE_REFLECTION_EMIT */
413 * image_g_alloc0:
415 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
416 * from the C heap.
418 static gpointer
419 image_g_malloc0 (MonoImage *image, guint size)
421 MONO_REQ_GC_NEUTRAL_MODE;
423 if (image)
424 return mono_image_alloc0 (image, size);
425 else
426 return g_malloc0 (size);
430 * image_g_free:
431 * @image: a MonoImage
432 * @ptr: pointer
434 * If @image is NULL, free @ptr, otherwise do nothing.
436 static void
437 image_g_free (MonoImage *image, gpointer ptr)
439 if (image == NULL)
440 g_free (ptr);
443 #ifndef DISABLE_REFLECTION_EMIT
444 static char*
445 image_strdup (MonoImage *image, const char *s)
447 MONO_REQ_GC_NEUTRAL_MODE;
449 if (image)
450 return mono_image_strdup (image, s);
451 else
452 return g_strdup (s);
454 #endif
456 #define image_g_new(image,struct_type, n_structs) \
457 ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
459 #define image_g_new0(image,struct_type, n_structs) \
460 ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
463 static void
464 alloc_table (MonoDynamicTable *table, guint nrows)
466 MONO_REQ_GC_NEUTRAL_MODE;
468 table->rows = nrows;
469 g_assert (table->columns);
470 if (nrows + 1 >= table->alloc_rows) {
471 while (nrows + 1 >= table->alloc_rows) {
472 if (table->alloc_rows == 0)
473 table->alloc_rows = 16;
474 else
475 table->alloc_rows *= 2;
478 table->values = (guint32 *)g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
482 static void
483 make_room_in_stream (MonoDynamicStream *stream, int size)
485 MONO_REQ_GC_NEUTRAL_MODE;
487 if (size <= stream->alloc_size)
488 return;
490 while (stream->alloc_size <= size) {
491 if (stream->alloc_size < 4096)
492 stream->alloc_size = 4096;
493 else
494 stream->alloc_size *= 2;
497 stream->data = (char *)g_realloc (stream->data, stream->alloc_size);
500 static guint32
501 string_heap_insert (MonoDynamicStream *sh, const char *str)
503 MONO_REQ_GC_NEUTRAL_MODE;
505 guint32 idx;
506 guint32 len;
507 gpointer oldkey, oldval;
509 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
510 return GPOINTER_TO_UINT (oldval);
512 len = strlen (str) + 1;
513 idx = sh->index;
515 make_room_in_stream (sh, idx + len);
518 * We strdup the string even if we already copy them in sh->data
519 * so that the string pointers in the hash remain valid even if
520 * we need to realloc sh->data. We may want to avoid that later.
522 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
523 memcpy (sh->data + idx, str, len);
524 sh->index += len;
525 return idx;
528 static guint32
529 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
531 MONO_REQ_GC_UNSAFE_MODE;
533 char *name = mono_string_to_utf8 (str);
534 guint32 idx;
535 idx = string_heap_insert (sh, name);
536 g_free (name);
537 return idx;
540 #ifndef DISABLE_REFLECTION_EMIT
541 static void
542 string_heap_init (MonoDynamicStream *sh)
544 MONO_REQ_GC_NEUTRAL_MODE;
546 sh->index = 0;
547 sh->alloc_size = 4096;
548 sh->data = (char *)g_malloc (4096);
549 sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
550 string_heap_insert (sh, "");
552 #endif
554 static guint32
555 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
557 MONO_REQ_GC_NEUTRAL_MODE;
559 guint32 idx;
561 make_room_in_stream (stream, stream->index + len);
562 memcpy (stream->data + stream->index, data, len);
563 idx = stream->index;
564 stream->index += len;
566 * align index? Not without adding an additional param that controls it since
567 * we may store a blob value in pieces.
569 return idx;
572 static guint32
573 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
575 MONO_REQ_GC_NEUTRAL_MODE;
577 guint32 idx;
579 make_room_in_stream (stream, stream->index + len);
580 memset (stream->data + stream->index, 0, len);
581 idx = stream->index;
582 stream->index += len;
583 return idx;
586 static void
587 stream_data_align (MonoDynamicStream *stream)
589 MONO_REQ_GC_NEUTRAL_MODE;
591 char buf [4] = {0};
592 guint32 count = stream->index % 4;
594 /* we assume the stream data will be aligned */
595 if (count)
596 mono_image_add_stream_data (stream, buf, 4 - count);
599 #ifndef DISABLE_REFLECTION_EMIT
600 static int
601 mono_blob_entry_hash (const char* str)
603 MONO_REQ_GC_NEUTRAL_MODE;
605 guint len, h;
606 const char *end;
607 len = mono_metadata_decode_blob_size (str, &str);
608 if (len > 0) {
609 end = str + len;
610 h = *str;
611 for (str += 1; str < end; str++)
612 h = (h << 5) - h + *str;
613 return h;
614 } else {
615 return 0;
619 static gboolean
620 mono_blob_entry_equal (const char *str1, const char *str2) {
621 MONO_REQ_GC_NEUTRAL_MODE;
623 int len, len2;
624 const char *end1;
625 const char *end2;
626 len = mono_metadata_decode_blob_size (str1, &end1);
627 len2 = mono_metadata_decode_blob_size (str2, &end2);
628 if (len != len2)
629 return 0;
630 return memcmp (end1, end2, len) == 0;
632 #endif
633 static guint32
634 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
636 MONO_REQ_GC_NEUTRAL_MODE;
638 guint32 idx;
639 char *copy;
640 gpointer oldkey, oldval;
642 copy = (char *)g_malloc (s1+s2);
643 memcpy (copy, b1, s1);
644 memcpy (copy + s1, b2, s2);
645 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
646 g_free (copy);
647 idx = GPOINTER_TO_UINT (oldval);
648 } else {
649 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
650 mono_image_add_stream_data (&assembly->blob, b2, s2);
651 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
653 return idx;
656 static guint32
657 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
659 MONO_REQ_GC_NEUTRAL_MODE;
661 char blob_size [8];
662 char *b = blob_size;
663 guint32 size = buf->p - buf->buf;
664 /* store length */
665 g_assert (size <= (buf->end - buf->buf));
666 mono_metadata_encode_value (size, b, &b);
667 return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
671 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
672 * dest may be misaligned.
674 static void
675 swap_with_size (char *dest, const char* val, int len, int nelem) {
676 MONO_REQ_GC_NEUTRAL_MODE;
677 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
678 int elem;
680 for (elem = 0; elem < nelem; ++elem) {
681 switch (len) {
682 case 1:
683 *dest = *val;
684 break;
685 case 2:
686 dest [0] = val [1];
687 dest [1] = val [0];
688 break;
689 case 4:
690 dest [0] = val [3];
691 dest [1] = val [2];
692 dest [2] = val [1];
693 dest [3] = val [0];
694 break;
695 case 8:
696 dest [0] = val [7];
697 dest [1] = val [6];
698 dest [2] = val [5];
699 dest [3] = val [4];
700 dest [4] = val [3];
701 dest [5] = val [2];
702 dest [6] = val [1];
703 dest [7] = val [0];
704 break;
705 default:
706 g_assert_not_reached ();
708 dest += len;
709 val += len;
711 #else
712 memcpy (dest, val, len * nelem);
713 #endif
716 static guint32
717 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
719 MONO_REQ_GC_UNSAFE_MODE;
721 char blob_size [64];
722 char *b = blob_size;
723 guint32 idx = 0, len;
725 len = str->length * 2;
726 mono_metadata_encode_value (len, b, &b);
727 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
729 char *swapped = g_malloc (2 * mono_string_length (str));
730 const char *p = (const char*)mono_string_chars (str);
732 swap_with_size (swapped, p, 2, mono_string_length (str));
733 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
734 g_free (swapped);
736 #else
737 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
738 #endif
739 return idx;
742 #ifndef DISABLE_REFLECTION_EMIT
743 static MonoClass *
744 default_class_from_mono_type (MonoType *type)
746 MONO_REQ_GC_NEUTRAL_MODE;
748 switch (type->type) {
749 case MONO_TYPE_OBJECT:
750 return mono_defaults.object_class;
751 case MONO_TYPE_VOID:
752 return mono_defaults.void_class;
753 case MONO_TYPE_BOOLEAN:
754 return mono_defaults.boolean_class;
755 case MONO_TYPE_CHAR:
756 return mono_defaults.char_class;
757 case MONO_TYPE_I1:
758 return mono_defaults.sbyte_class;
759 case MONO_TYPE_U1:
760 return mono_defaults.byte_class;
761 case MONO_TYPE_I2:
762 return mono_defaults.int16_class;
763 case MONO_TYPE_U2:
764 return mono_defaults.uint16_class;
765 case MONO_TYPE_I4:
766 return mono_defaults.int32_class;
767 case MONO_TYPE_U4:
768 return mono_defaults.uint32_class;
769 case MONO_TYPE_I:
770 return mono_defaults.int_class;
771 case MONO_TYPE_U:
772 return mono_defaults.uint_class;
773 case MONO_TYPE_I8:
774 return mono_defaults.int64_class;
775 case MONO_TYPE_U8:
776 return mono_defaults.uint64_class;
777 case MONO_TYPE_R4:
778 return mono_defaults.single_class;
779 case MONO_TYPE_R8:
780 return mono_defaults.double_class;
781 case MONO_TYPE_STRING:
782 return mono_defaults.string_class;
783 default:
784 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
785 g_assert_not_reached ();
788 return NULL;
790 #endif
793 * mono_class_get_ref_info:
795 * Return the type builder/generic param builder corresponding to KLASS, if it exists.
797 gpointer
798 mono_class_get_ref_info (MonoClass *klass)
800 MONO_REQ_GC_UNSAFE_MODE;
802 if (klass->ref_info_handle == 0)
803 return NULL;
804 else
805 return mono_gchandle_get_target (klass->ref_info_handle);
808 void
809 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
811 MONO_REQ_GC_UNSAFE_MODE;
813 klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
814 g_assert (klass->ref_info_handle != 0);
817 void
818 mono_class_free_ref_info (MonoClass *klass)
820 MONO_REQ_GC_NEUTRAL_MODE;
822 if (klass->ref_info_handle) {
823 mono_gchandle_free (klass->ref_info_handle);
824 klass->ref_info_handle = 0;
828 static void
829 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
831 MONO_REQ_GC_NEUTRAL_MODE;
833 int i;
834 MonoGenericInst *class_inst;
835 MonoClass *klass;
837 g_assert (gclass);
839 class_inst = gclass->context.class_inst;
841 sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
842 klass = gclass->container_class;
843 sigbuffer_add_value (buf, klass->byval_arg.type);
844 sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
846 sigbuffer_add_value (buf, class_inst->type_argc);
847 for (i = 0; i < class_inst->type_argc; ++i)
848 encode_type (assembly, class_inst->type_argv [i], buf);
852 static void
853 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
855 MONO_REQ_GC_NEUTRAL_MODE;
857 if (!type) {
858 g_assert_not_reached ();
859 return;
862 if (type->byref)
863 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
865 switch (type->type){
866 case MONO_TYPE_VOID:
867 case MONO_TYPE_BOOLEAN:
868 case MONO_TYPE_CHAR:
869 case MONO_TYPE_I1:
870 case MONO_TYPE_U1:
871 case MONO_TYPE_I2:
872 case MONO_TYPE_U2:
873 case MONO_TYPE_I4:
874 case MONO_TYPE_U4:
875 case MONO_TYPE_I8:
876 case MONO_TYPE_U8:
877 case MONO_TYPE_R4:
878 case MONO_TYPE_R8:
879 case MONO_TYPE_I:
880 case MONO_TYPE_U:
881 case MONO_TYPE_STRING:
882 case MONO_TYPE_OBJECT:
883 case MONO_TYPE_TYPEDBYREF:
884 sigbuffer_add_value (buf, type->type);
885 break;
886 case MONO_TYPE_PTR:
887 sigbuffer_add_value (buf, type->type);
888 encode_type (assembly, type->data.type, buf);
889 break;
890 case MONO_TYPE_SZARRAY:
891 sigbuffer_add_value (buf, type->type);
892 encode_type (assembly, &type->data.klass->byval_arg, buf);
893 break;
894 case MONO_TYPE_VALUETYPE:
895 case MONO_TYPE_CLASS: {
896 MonoClass *k = mono_class_from_mono_type (type);
898 if (k->generic_container) {
899 MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
900 encode_generic_class (assembly, gclass, buf);
901 } else {
903 * Make sure we use the correct type.
905 sigbuffer_add_value (buf, k->byval_arg.type);
907 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
908 * otherwise two typerefs could point to the same type, leading to
909 * verification errors.
911 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
913 break;
915 case MONO_TYPE_ARRAY:
916 sigbuffer_add_value (buf, type->type);
917 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
918 sigbuffer_add_value (buf, type->data.array->rank);
919 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
920 sigbuffer_add_value (buf, 0);
921 break;
922 case MONO_TYPE_GENERICINST:
923 encode_generic_class (assembly, type->data.generic_class, buf);
924 break;
925 case MONO_TYPE_VAR:
926 case MONO_TYPE_MVAR:
927 sigbuffer_add_value (buf, type->type);
928 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
929 break;
930 default:
931 g_error ("need to encode type %x", type->type);
935 static void
936 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf, MonoError *error)
938 MONO_REQ_GC_UNSAFE_MODE;
940 mono_error_init (error);
942 if (!type) {
943 sigbuffer_add_value (buf, MONO_TYPE_VOID);
944 return;
947 MonoType *t = mono_reflection_type_get_handle (type, error);
948 return_if_nok (error);
949 encode_type (assembly, t, buf);
952 static void
953 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf, MonoError *error)
955 MONO_REQ_GC_UNSAFE_MODE;
957 int i;
959 mono_error_init (error);
961 if (modreq) {
962 for (i = 0; i < mono_array_length (modreq); ++i) {
963 MonoType *mod = mono_type_array_get_and_resolve (modreq, i, error);
964 return_if_nok (error);
965 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
966 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
969 if (modopt) {
970 for (i = 0; i < mono_array_length (modopt); ++i) {
971 MonoType *mod = mono_type_array_get_and_resolve (modopt, i, error);
972 return_if_nok (error);
973 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
974 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
979 #ifndef DISABLE_REFLECTION_EMIT
980 static guint32
981 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
983 MONO_REQ_GC_UNSAFE_MODE;
985 SigBuffer buf;
986 int i;
987 guint32 nparams = sig->param_count;
988 guint32 idx;
990 if (!assembly->save)
991 return 0;
993 sigbuffer_init (&buf, 32);
995 * FIXME: vararg, explicit_this, differenc call_conv values...
997 idx = sig->call_convention;
998 if (sig->hasthis)
999 idx |= 0x20; /* hasthis */
1000 if (sig->generic_param_count)
1001 idx |= 0x10; /* generic */
1002 sigbuffer_add_byte (&buf, idx);
1003 if (sig->generic_param_count)
1004 sigbuffer_add_value (&buf, sig->generic_param_count);
1005 sigbuffer_add_value (&buf, nparams);
1006 encode_type (assembly, sig->ret, &buf);
1007 for (i = 0; i < nparams; ++i) {
1008 if (i == sig->sentinelpos)
1009 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
1010 encode_type (assembly, sig->params [i], &buf);
1012 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1013 sigbuffer_free (&buf);
1014 return idx;
1016 #endif
1018 static guint32
1019 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
1021 MONO_REQ_GC_UNSAFE_MODE;
1023 mono_error_init (error);
1026 * FIXME: reuse code from method_encode_signature().
1028 SigBuffer buf;
1029 int i;
1030 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
1031 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
1032 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
1033 guint32 idx;
1035 sigbuffer_init (&buf, 32);
1036 /* LAMESPEC: all the call conv spec is foobared */
1037 idx = mb->call_conv & 0x60; /* has-this, explicit-this */
1038 if (mb->call_conv & 2)
1039 idx |= 0x5; /* vararg */
1040 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
1041 idx |= 0x20; /* hasthis */
1042 if (ngparams)
1043 idx |= 0x10; /* generic */
1044 sigbuffer_add_byte (&buf, idx);
1045 if (ngparams)
1046 sigbuffer_add_value (&buf, ngparams);
1047 sigbuffer_add_value (&buf, nparams + notypes);
1048 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf, error);
1049 if (!is_ok (error))
1050 goto leave;
1051 encode_reflection_type (assembly, mb->rtype, &buf, error);
1052 if (!is_ok (error))
1053 goto leave;
1054 for (i = 0; i < nparams; ++i) {
1055 MonoArray *modreq = NULL;
1056 MonoArray *modopt = NULL;
1057 MonoReflectionType *pt;
1059 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
1060 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
1061 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
1062 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
1063 encode_custom_modifiers (assembly, modreq, modopt, &buf, error);
1064 if (!is_ok (error))
1065 goto leave;
1066 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1067 encode_reflection_type (assembly, pt, &buf, error);
1068 if (!is_ok (error))
1069 goto leave;
1071 if (notypes)
1072 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
1073 for (i = 0; i < notypes; ++i) {
1074 MonoReflectionType *pt;
1076 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
1077 encode_reflection_type (assembly, pt, &buf, error);
1078 if (!is_ok (error))
1079 goto leave;
1082 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1083 leave:
1084 sigbuffer_free (&buf);
1085 return idx;
1088 static guint32
1089 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, MonoError *error)
1091 MONO_REQ_GC_UNSAFE_MODE;
1093 mono_error_init (error);
1095 MonoDynamicTable *table;
1096 guint32 *values;
1097 guint32 idx, sig_idx;
1098 guint nl = mono_array_length (ilgen->locals);
1099 SigBuffer buf;
1100 int i;
1102 sigbuffer_init (&buf, 32);
1103 sigbuffer_add_value (&buf, 0x07);
1104 sigbuffer_add_value (&buf, nl);
1105 for (i = 0; i < nl; ++i) {
1106 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
1108 if (lb->is_pinned)
1109 sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
1111 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf, error);
1112 if (!is_ok (error)) {
1113 sigbuffer_free (&buf);
1114 return 0;
1117 sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1118 sigbuffer_free (&buf);
1120 if (assembly->standalonesig_cache == NULL)
1121 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
1122 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
1123 if (idx)
1124 return idx;
1126 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
1127 idx = table->next_idx ++;
1128 table->rows ++;
1129 alloc_table (table, table->rows);
1130 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
1132 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
1134 g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
1136 return idx;
1139 static guint32
1140 method_count_clauses (MonoReflectionILGen *ilgen)
1142 MONO_REQ_GC_UNSAFE_MODE;
1144 guint32 num_clauses = 0;
1145 int i;
1147 MonoILExceptionInfo *ex_info;
1148 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
1149 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1150 if (ex_info->handlers)
1151 num_clauses += mono_array_length (ex_info->handlers);
1152 else
1153 num_clauses++;
1156 return num_clauses;
1159 #ifndef DISABLE_REFLECTION_EMIT
1160 static MonoExceptionClause*
1161 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses, MonoError *error)
1163 MONO_REQ_GC_UNSAFE_MODE;
1165 mono_error_init (error);
1167 MonoExceptionClause *clauses;
1168 MonoExceptionClause *clause;
1169 MonoILExceptionInfo *ex_info;
1170 MonoILExceptionBlock *ex_block;
1171 guint32 finally_start;
1172 int i, j, clause_index;;
1174 clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
1176 clause_index = 0;
1177 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
1178 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1179 finally_start = ex_info->start + ex_info->len;
1180 if (!ex_info->handlers)
1181 continue;
1182 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1183 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1184 clause = &(clauses [clause_index]);
1186 clause->flags = ex_block->type;
1187 clause->try_offset = ex_info->start;
1189 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1190 clause->try_len = finally_start - ex_info->start;
1191 else
1192 clause->try_len = ex_info->len;
1193 clause->handler_offset = ex_block->start;
1194 clause->handler_len = ex_block->len;
1195 if (ex_block->extype) {
1196 MonoType *extype = mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype, error);
1198 if (!is_ok (error)) {
1199 image_g_free (image, clauses);
1200 return NULL;
1202 clause->data.catch_class = mono_class_from_mono_type (extype);
1203 } else {
1204 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1205 clause->data.filter_offset = ex_block->filter_offset;
1206 else
1207 clause->data.filter_offset = 0;
1209 finally_start = ex_block->start + ex_block->len;
1211 clause_index ++;
1215 return clauses;
1217 #endif /* !DISABLE_REFLECTION_EMIT */
1220 * method_encode_code:
1222 * @assembly the assembly
1223 * @mb the managed MethodBuilder
1224 * @error set on error
1226 * Note that the return value is not sensible if @error is set.
1228 static guint32
1229 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
1231 MONO_REQ_GC_UNSAFE_MODE;
1233 char flags = 0;
1234 guint32 idx;
1235 guint32 code_size;
1236 gint32 max_stack, i;
1237 gint32 num_locals = 0;
1238 gint32 num_exception = 0;
1239 gint maybe_small;
1240 guint32 fat_flags;
1241 char fat_header [12];
1242 guint32 int_value;
1243 guint16 short_value;
1244 guint32 local_sig = 0;
1245 guint32 header_size = 12;
1246 MonoArray *code;
1248 mono_error_init (error);
1250 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
1251 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
1252 return 0;
1254 /*if (mb->name)
1255 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1256 if (mb->ilgen) {
1257 code = mb->ilgen->code;
1258 code_size = mb->ilgen->code_len;
1259 max_stack = mb->ilgen->max_stack;
1260 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1261 if (mb->ilgen->ex_handlers)
1262 num_exception = method_count_clauses (mb->ilgen);
1263 } else {
1264 code = mb->code;
1265 if (code == NULL){
1266 char *name = mono_string_to_utf8 (mb->name);
1267 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1268 mono_error_set_argument (error, NULL, "a method does not have any IL associated");
1269 g_free (str);
1270 g_free (name);
1271 return 0;
1274 code_size = mono_array_length (code);
1275 max_stack = 8; /* we probably need to run a verifier on the code... */
1278 stream_data_align (&assembly->code);
1280 /* check for exceptions, maxstack, locals */
1281 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1282 if (maybe_small) {
1283 if (code_size < 64 && !(code_size & 1)) {
1284 flags = (code_size << 2) | 0x2;
1285 } else if (code_size < 32 && (code_size & 1)) {
1286 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1287 } else {
1288 goto fat_header;
1290 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1291 /* add to the fixup todo list */
1292 if (mb->ilgen && mb->ilgen->num_token_fixups)
1293 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1294 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1295 return assembly->text_rva + idx;
1297 fat_header:
1298 if (num_locals) {
1299 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen, error);
1300 return_val_if_nok (error, 0);
1303 * FIXME: need to set also the header size in fat_flags.
1304 * (and more sects and init locals flags)
1306 fat_flags = 0x03;
1307 if (num_exception)
1308 fat_flags |= METHOD_HEADER_MORE_SECTS;
1309 if (mb->init_locals)
1310 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1311 fat_header [0] = fat_flags;
1312 fat_header [1] = (header_size / 4 ) << 4;
1313 short_value = GUINT16_TO_LE (max_stack);
1314 memcpy (fat_header + 2, &short_value, 2);
1315 int_value = GUINT32_TO_LE (code_size);
1316 memcpy (fat_header + 4, &int_value, 4);
1317 int_value = GUINT32_TO_LE (local_sig);
1318 memcpy (fat_header + 8, &int_value, 4);
1319 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1320 /* add to the fixup todo list */
1321 if (mb->ilgen && mb->ilgen->num_token_fixups)
1322 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1324 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1325 if (num_exception) {
1326 unsigned char sheader [4];
1327 MonoILExceptionInfo * ex_info;
1328 MonoILExceptionBlock * ex_block;
1329 int j;
1331 stream_data_align (&assembly->code);
1332 /* always use fat format for now */
1333 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1334 num_exception *= 6 * sizeof (guint32);
1335 num_exception += 4; /* include the size of the header */
1336 sheader [1] = num_exception & 0xff;
1337 sheader [2] = (num_exception >> 8) & 0xff;
1338 sheader [3] = (num_exception >> 16) & 0xff;
1339 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1340 /* fat header, so we are already aligned */
1341 /* reverse order */
1342 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1343 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1344 if (ex_info->handlers) {
1345 int finally_start = ex_info->start + ex_info->len;
1346 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1347 guint32 val;
1348 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1349 /* the flags */
1350 val = GUINT32_TO_LE (ex_block->type);
1351 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1352 /* try offset */
1353 val = GUINT32_TO_LE (ex_info->start);
1354 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1355 /* need fault, too, probably */
1356 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1357 val = GUINT32_TO_LE (finally_start - ex_info->start);
1358 else
1359 val = GUINT32_TO_LE (ex_info->len);
1360 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1361 /* handler offset */
1362 val = GUINT32_TO_LE (ex_block->start);
1363 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1364 /* handler len */
1365 val = GUINT32_TO_LE (ex_block->len);
1366 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1367 finally_start = ex_block->start + ex_block->len;
1368 if (ex_block->extype) {
1369 MonoType *extype = mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype, error);
1370 return_val_if_nok (error, 0);
1372 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, extype));
1373 } else {
1374 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1375 val = ex_block->filter_offset;
1376 else
1377 val = 0;
1379 val = GUINT32_TO_LE (val);
1380 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1381 /*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",
1382 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);*/
1384 } else {
1385 g_error ("No clauses for ex info block %d", i);
1389 return assembly->text_rva + idx;
1392 static guint32
1393 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1395 MONO_REQ_GC_NEUTRAL_MODE;
1397 int i;
1398 MonoDynamicTable *table;
1399 guint32 *values;
1401 table = &assembly->tables [table_idx];
1403 g_assert (col < table->columns);
1405 values = table->values + table->columns;
1406 for (i = 1; i <= table->rows; ++i) {
1407 if (values [col] == token)
1408 return i;
1409 values += table->columns;
1411 return 0;
1415 * LOCKING: Acquires the loader lock.
1417 static MonoCustomAttrInfo*
1418 lookup_custom_attr (MonoImage *image, gpointer member)
1420 MONO_REQ_GC_NEUTRAL_MODE;
1422 MonoCustomAttrInfo* res;
1424 res = (MonoCustomAttrInfo *)mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1426 if (!res)
1427 return NULL;
1429 res = (MonoCustomAttrInfo *)g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1430 res->cached = 0;
1431 return res;
1434 static gboolean
1435 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1437 MONO_REQ_GC_UNSAFE_MODE;
1439 /* FIXME: Need to do more checks */
1440 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1441 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1443 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1444 return FALSE;
1447 return TRUE;
1450 static MonoCustomAttrInfo*
1451 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1453 MONO_REQ_GC_UNSAFE_MODE;
1455 int i, index, count, not_visible;
1456 MonoCustomAttrInfo *ainfo;
1457 MonoReflectionCustomAttr *cattr;
1459 if (!cattrs)
1460 return NULL;
1461 /* FIXME: check in assembly the Run flag is set */
1463 count = mono_array_length (cattrs);
1465 /* Skip nonpublic attributes since MS.NET seems to do the same */
1466 /* FIXME: This needs to be done more globally */
1467 not_visible = 0;
1468 for (i = 0; i < count; ++i) {
1469 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1470 if (!custom_attr_visible (image, cattr))
1471 not_visible ++;
1473 count -= not_visible;
1475 ainfo = (MonoCustomAttrInfo *)image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1477 ainfo->image = image;
1478 ainfo->num_attrs = count;
1479 ainfo->cached = alloc_img != NULL;
1480 index = 0;
1481 for (i = 0; i < count; ++i) {
1482 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1483 if (custom_attr_visible (image, cattr)) {
1484 unsigned char *saved = (unsigned char *)mono_image_alloc (image, mono_array_length (cattr->data));
1485 memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1486 ainfo->attrs [index].ctor = cattr->ctor->method;
1487 ainfo->attrs [index].data = saved;
1488 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1489 index ++;
1493 return ainfo;
1496 #ifndef DISABLE_REFLECTION_EMIT
1498 * LOCKING: Acquires the loader lock.
1500 static void
1501 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1503 MONO_REQ_GC_UNSAFE_MODE;
1505 MonoCustomAttrInfo *ainfo, *tmp;
1507 if (!cattrs || !mono_array_length (cattrs))
1508 return;
1510 ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1512 mono_loader_lock ();
1513 tmp = (MonoCustomAttrInfo *)mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1514 if (tmp)
1515 mono_custom_attrs_free (tmp);
1516 mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1517 mono_loader_unlock ();
1520 #endif
1522 void
1523 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1525 MONO_REQ_GC_NEUTRAL_MODE;
1527 if (ainfo && !ainfo->cached)
1528 g_free (ainfo);
1532 * idx is the table index of the object
1533 * type is one of MONO_CUSTOM_ATTR_*
1535 static gboolean
1536 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs, MonoError *error)
1538 MONO_REQ_GC_UNSAFE_MODE;
1540 MonoDynamicTable *table;
1541 MonoReflectionCustomAttr *cattr;
1542 guint32 *values;
1543 guint32 count, i, token;
1544 char blob_size [6];
1545 char *p = blob_size;
1547 mono_error_init (error);
1549 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1550 if (!cattrs)
1551 return TRUE;
1552 count = mono_array_length (cattrs);
1553 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1554 table->rows += count;
1555 alloc_table (table, table->rows);
1556 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1557 idx <<= MONO_CUSTOM_ATTR_BITS;
1558 idx |= type;
1559 for (i = 0; i < count; ++i) {
1560 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1561 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1562 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE, error);
1563 if (!mono_error_ok (error)) goto fail;
1564 type = mono_metadata_token_index (token);
1565 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1566 switch (mono_metadata_token_table (token)) {
1567 case MONO_TABLE_METHOD:
1568 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1570 * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
1571 * method, not the one returned by mono_image_create_token ().
1573 mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
1574 break;
1575 case MONO_TABLE_MEMBERREF:
1576 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1577 break;
1578 default:
1579 g_warning ("got wrong token in custom attr");
1580 continue;
1582 values [MONO_CUSTOM_ATTR_TYPE] = type;
1583 p = blob_size;
1584 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1585 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1586 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1587 values += MONO_CUSTOM_ATTR_SIZE;
1588 ++table->next_idx;
1591 return TRUE;
1593 fail:
1594 return FALSE;
1597 static void
1598 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1600 MONO_REQ_GC_UNSAFE_MODE;
1602 MonoDynamicTable *table;
1603 guint32 *values;
1604 guint32 count, i, idx;
1605 MonoReflectionPermissionSet *perm;
1607 if (!permissions)
1608 return;
1610 count = mono_array_length (permissions);
1611 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1612 table->rows += count;
1613 alloc_table (table, table->rows);
1615 for (i = 0; i < mono_array_length (permissions); ++i) {
1616 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1618 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1620 idx = mono_metadata_token_index (parent_token);
1621 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1622 switch (mono_metadata_token_table (parent_token)) {
1623 case MONO_TABLE_TYPEDEF:
1624 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1625 break;
1626 case MONO_TABLE_METHOD:
1627 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1628 break;
1629 case MONO_TABLE_ASSEMBLY:
1630 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1631 break;
1632 default:
1633 g_assert_not_reached ();
1636 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1637 values [MONO_DECL_SECURITY_PARENT] = idx;
1638 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1640 ++table->next_idx;
1645 * Fill in the MethodDef and ParamDef tables for a method.
1646 * This is used for both normal methods and constructors.
1648 static gboolean
1649 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1651 MONO_REQ_GC_UNSAFE_MODE;
1653 MonoDynamicTable *table;
1654 guint32 *values;
1655 guint i, count;
1657 mono_error_init (error);
1659 /* room in this table is already allocated */
1660 table = &assembly->tables [MONO_TABLE_METHOD];
1661 *mb->table_idx = table->next_idx ++;
1662 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1663 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1664 values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1665 values [MONO_METHOD_FLAGS] = mb->attrs;
1666 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1667 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb, error);
1668 return_val_if_nok (error, FALSE);
1669 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb, error);
1670 return_val_if_nok (error, FALSE);
1672 table = &assembly->tables [MONO_TABLE_PARAM];
1673 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1675 mono_image_add_decl_security (assembly,
1676 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1678 if (mb->pinfo) {
1679 MonoDynamicTable *mtable;
1680 guint32 *mvalues;
1682 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1683 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1685 count = 0;
1686 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1687 if (mono_array_get (mb->pinfo, gpointer, i))
1688 count++;
1690 table->rows += count;
1691 alloc_table (table, table->rows);
1692 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1693 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1694 MonoReflectionParamBuilder *pb;
1695 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1696 values [MONO_PARAM_FLAGS] = pb->attrs;
1697 values [MONO_PARAM_SEQUENCE] = i;
1698 if (pb->name != NULL) {
1699 values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1700 } else {
1701 values [MONO_PARAM_NAME] = 0;
1703 values += MONO_PARAM_SIZE;
1704 if (pb->marshal_info) {
1705 mtable->rows++;
1706 alloc_table (mtable, mtable->rows);
1707 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1708 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1709 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info, error);
1710 return_val_if_nok (error, FALSE);
1712 pb->table_idx = table->next_idx++;
1713 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1714 guint32 field_type = 0;
1715 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1716 mtable->rows ++;
1717 alloc_table (mtable, mtable->rows);
1718 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1719 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1720 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1721 mvalues [MONO_CONSTANT_TYPE] = field_type;
1722 mvalues [MONO_CONSTANT_PADDING] = 0;
1728 return TRUE;
1731 #ifndef DISABLE_REFLECTION_EMIT
1732 static gboolean
1733 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error)
1735 MONO_REQ_GC_UNSAFE_MODE;
1737 mono_error_init (error);
1738 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1740 rmb->ilgen = mb->ilgen;
1741 rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype, error);
1742 return_val_if_nok (error, FALSE);
1743 rmb->parameters = mb->parameters;
1744 rmb->generic_params = mb->generic_params;
1745 rmb->generic_container = mb->generic_container;
1746 rmb->opt_types = NULL;
1747 rmb->pinfo = mb->pinfo;
1748 rmb->attrs = mb->attrs;
1749 rmb->iattrs = mb->iattrs;
1750 rmb->call_conv = mb->call_conv;
1751 rmb->code = mb->code;
1752 rmb->type = mb->type;
1753 rmb->name = mb->name;
1754 rmb->table_idx = &mb->table_idx;
1755 rmb->init_locals = mb->init_locals;
1756 rmb->skip_visibility = FALSE;
1757 rmb->return_modreq = mb->return_modreq;
1758 rmb->return_modopt = mb->return_modopt;
1759 rmb->param_modreq = mb->param_modreq;
1760 rmb->param_modopt = mb->param_modopt;
1761 rmb->permissions = mb->permissions;
1762 rmb->mhandle = mb->mhandle;
1763 rmb->nrefs = 0;
1764 rmb->refs = NULL;
1766 if (mb->dll) {
1767 rmb->charset = mb->charset;
1768 rmb->extra_flags = mb->extra_flags;
1769 rmb->native_cc = mb->native_cc;
1770 rmb->dllentry = mb->dllentry;
1771 rmb->dll = mb->dll;
1774 return TRUE;
1777 static gboolean
1778 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error)
1780 MONO_REQ_GC_UNSAFE_MODE;
1782 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1784 mono_error_init (error);
1786 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1788 rmb->ilgen = mb->ilgen;
1789 rmb->rtype = mono_type_get_object_checked (mono_domain_get (), &mono_defaults.void_class->byval_arg, error);
1790 return_val_if_nok (error, FALSE);
1791 rmb->parameters = mb->parameters;
1792 rmb->generic_params = NULL;
1793 rmb->generic_container = NULL;
1794 rmb->opt_types = NULL;
1795 rmb->pinfo = mb->pinfo;
1796 rmb->attrs = mb->attrs;
1797 rmb->iattrs = mb->iattrs;
1798 rmb->call_conv = mb->call_conv;
1799 rmb->code = NULL;
1800 rmb->type = mb->type;
1801 rmb->name = mono_string_new (mono_domain_get (), name);
1802 rmb->table_idx = &mb->table_idx;
1803 rmb->init_locals = mb->init_locals;
1804 rmb->skip_visibility = FALSE;
1805 rmb->return_modreq = NULL;
1806 rmb->return_modopt = NULL;
1807 rmb->param_modreq = mb->param_modreq;
1808 rmb->param_modopt = mb->param_modopt;
1809 rmb->permissions = mb->permissions;
1810 rmb->mhandle = mb->mhandle;
1811 rmb->nrefs = 0;
1812 rmb->refs = NULL;
1814 return TRUE;
1817 static void
1818 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1820 MONO_REQ_GC_UNSAFE_MODE;
1822 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1824 rmb->ilgen = mb->ilgen;
1825 rmb->rtype = mb->rtype;
1826 rmb->parameters = mb->parameters;
1827 rmb->generic_params = NULL;
1828 rmb->generic_container = NULL;
1829 rmb->opt_types = NULL;
1830 rmb->pinfo = NULL;
1831 rmb->attrs = mb->attrs;
1832 rmb->iattrs = 0;
1833 rmb->call_conv = mb->call_conv;
1834 rmb->code = NULL;
1835 rmb->type = (MonoObject *) mb->owner;
1836 rmb->name = mb->name;
1837 rmb->table_idx = NULL;
1838 rmb->init_locals = mb->init_locals;
1839 rmb->skip_visibility = mb->skip_visibility;
1840 rmb->return_modreq = NULL;
1841 rmb->return_modopt = NULL;
1842 rmb->param_modreq = NULL;
1843 rmb->param_modopt = NULL;
1844 rmb->permissions = NULL;
1845 rmb->mhandle = mb->mhandle;
1846 rmb->nrefs = 0;
1847 rmb->refs = NULL;
1849 #endif
1851 static gboolean
1852 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
1854 MONO_REQ_GC_UNSAFE_MODE;
1856 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1857 MonoDynamicTable *table;
1858 guint32 *values;
1859 guint32 tok;
1860 MonoReflectionMethod *m;
1861 int i;
1863 mono_error_init (error);
1865 if (!mb->override_methods)
1866 return TRUE;
1868 for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
1869 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
1871 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1872 table->rows ++;
1873 alloc_table (table, table->rows);
1874 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1875 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1876 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1878 tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE, error);
1879 return_val_if_nok (error, FALSE);
1881 switch (mono_metadata_token_table (tok)) {
1882 case MONO_TABLE_MEMBERREF:
1883 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1884 break;
1885 case MONO_TABLE_METHOD:
1886 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1887 break;
1888 default:
1889 g_assert_not_reached ();
1891 values [MONO_METHODIMPL_DECLARATION] = tok;
1894 return TRUE;
1897 #ifndef DISABLE_REFLECTION_EMIT
1898 static gboolean
1899 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1901 MONO_REQ_GC_UNSAFE_MODE;
1903 MonoDynamicTable *table;
1904 guint32 *values;
1905 ReflectionMethodBuilder rmb;
1906 int i;
1908 mono_error_init (error);
1910 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error) ||
1911 !mono_image_basic_method (&rmb, assembly, error))
1912 return FALSE;
1914 mb->table_idx = *rmb.table_idx;
1916 if (mb->dll) { /* It's a P/Invoke method */
1917 guint32 moduleref;
1918 /* map CharSet values to on-disk values */
1919 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1920 int extra_flags = mb->extra_flags;
1921 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1922 table->rows ++;
1923 alloc_table (table, table->rows);
1924 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1926 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1927 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1928 if (mb->dllentry)
1929 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1930 else
1931 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1932 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1933 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1934 table = &assembly->tables [MONO_TABLE_MODULEREF];
1935 table->rows ++;
1936 alloc_table (table, table->rows);
1937 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1938 values [MONO_IMPLMAP_SCOPE] = table->rows;
1942 if (mb->generic_params) {
1943 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1944 table->rows += mono_array_length (mb->generic_params);
1945 alloc_table (table, table->rows);
1946 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1947 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1949 mono_image_get_generic_param_info (
1950 (MonoReflectionGenericParam *)mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1954 return TRUE;
1957 static gboolean
1958 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1960 MONO_REQ_GC_UNSAFE_MODE;
1962 ReflectionMethodBuilder rmb;
1964 if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
1965 return FALSE;
1967 if (!mono_image_basic_method (&rmb, assembly, error))
1968 return FALSE;
1970 mb->table_idx = *rmb.table_idx;
1972 return TRUE;
1974 #endif
1976 static char*
1977 type_get_fully_qualified_name (MonoType *type)
1979 MONO_REQ_GC_NEUTRAL_MODE;
1981 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1984 static char*
1985 type_get_qualified_name (MonoType *type, MonoAssembly *ass)
1987 MONO_REQ_GC_UNSAFE_MODE;
1989 MonoClass *klass;
1990 MonoAssembly *ta;
1992 klass = mono_class_from_mono_type (type);
1993 if (!klass)
1994 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1995 ta = klass->image->assembly;
1996 if (assembly_is_dynamic (ta) || (ta == ass)) {
1997 if (klass->generic_class || klass->generic_container)
1998 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1999 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
2000 else
2001 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
2004 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
2007 #ifndef DISABLE_REFLECTION_EMIT
2008 /*field_image is the image to which the eventual custom mods have been encoded against*/
2009 static guint32
2010 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
2012 MONO_REQ_GC_NEUTRAL_MODE;
2014 SigBuffer buf;
2015 guint32 idx, i, token;
2017 if (!assembly->save)
2018 return 0;
2020 sigbuffer_init (&buf, 32);
2022 sigbuffer_add_value (&buf, 0x06);
2023 /* encode custom attributes before the type */
2024 if (type->num_mods) {
2025 for (i = 0; i < type->num_mods; ++i) {
2026 if (field_image) {
2027 MonoError error;
2028 MonoClass *klass = mono_class_get_checked (field_image, type->modifiers [i].token, &error);
2029 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2031 token = mono_image_typedef_or_ref (assembly, &klass->byval_arg);
2032 } else {
2033 token = type->modifiers [i].token;
2036 if (type->modifiers [i].required)
2037 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
2038 else
2039 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
2041 sigbuffer_add_value (&buf, token);
2044 encode_type (assembly, type, &buf);
2045 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2046 sigbuffer_free (&buf);
2047 return idx;
2049 #endif
2051 static guint32
2052 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb, MonoError *error)
2054 MONO_REQ_GC_UNSAFE_MODE;
2056 mono_error_init (error);
2058 SigBuffer buf;
2059 guint32 idx;
2060 guint32 typespec = 0;
2061 MonoType *type;
2062 MonoClass *klass;
2064 init_type_builder_generics (fb->type);
2066 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
2067 return_val_if_nok (error, 0);
2068 klass = mono_class_from_mono_type (type);
2070 sigbuffer_init (&buf, 32);
2072 sigbuffer_add_value (&buf, 0x06);
2073 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf, error);
2074 if (!is_ok (error))
2075 goto fail;
2076 /* encode custom attributes before the type */
2078 if (klass->generic_container)
2079 typespec = create_typespec (assembly, type);
2081 if (typespec) {
2082 MonoGenericClass *gclass;
2083 gclass = mono_metadata_lookup_generic_class (klass, klass->generic_container->context.class_inst, TRUE);
2084 encode_generic_class (assembly, gclass, &buf);
2085 } else {
2086 encode_type (assembly, type, &buf);
2088 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2089 sigbuffer_free (&buf);
2090 return idx;
2091 fail:
2092 sigbuffer_free (&buf);
2093 return 0;
2096 static guint32
2097 encode_constant (MonoDynamicImage *assembly, MonoObject *val, MonoTypeEnum *ret_type)
2099 MONO_REQ_GC_UNSAFE_MODE;
2101 char blob_size [64];
2102 char *b = blob_size;
2103 char *box_val;
2104 char* buf;
2105 guint32 idx = 0, len = 0, dummy = 0;
2107 buf = (char *)g_malloc (64);
2108 if (!val) {
2109 *ret_type = MONO_TYPE_CLASS;
2110 len = 4;
2111 box_val = (char*)&dummy;
2112 } else {
2113 box_val = ((char*)val) + sizeof (MonoObject);
2114 *ret_type = val->vtable->klass->byval_arg.type;
2116 handle_enum:
2117 switch (*ret_type) {
2118 case MONO_TYPE_BOOLEAN:
2119 case MONO_TYPE_U1:
2120 case MONO_TYPE_I1:
2121 len = 1;
2122 break;
2123 case MONO_TYPE_CHAR:
2124 case MONO_TYPE_U2:
2125 case MONO_TYPE_I2:
2126 len = 2;
2127 break;
2128 case MONO_TYPE_U4:
2129 case MONO_TYPE_I4:
2130 case MONO_TYPE_R4:
2131 len = 4;
2132 break;
2133 case MONO_TYPE_U8:
2134 case MONO_TYPE_I8:
2135 len = 8;
2136 break;
2137 case MONO_TYPE_R8:
2138 len = 8;
2139 break;
2140 case MONO_TYPE_VALUETYPE: {
2141 MonoClass *klass = val->vtable->klass;
2143 if (klass->enumtype) {
2144 *ret_type = mono_class_enum_basetype (klass)->type;
2145 goto handle_enum;
2146 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
2147 len = 8;
2148 } else
2149 g_error ("we can't encode valuetypes, we should have never reached this line");
2150 break;
2152 case MONO_TYPE_CLASS:
2153 break;
2154 case MONO_TYPE_STRING: {
2155 MonoString *str = (MonoString*)val;
2156 /* there is no signature */
2157 len = str->length * 2;
2158 mono_metadata_encode_value (len, b, &b);
2159 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2161 char *swapped = g_malloc (2 * mono_string_length (str));
2162 const char *p = (const char*)mono_string_chars (str);
2164 swap_with_size (swapped, p, 2, mono_string_length (str));
2165 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
2166 g_free (swapped);
2168 #else
2169 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
2170 #endif
2172 g_free (buf);
2173 return idx;
2175 case MONO_TYPE_GENERICINST:
2176 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
2177 goto handle_enum;
2178 default:
2179 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
2182 /* there is no signature */
2183 mono_metadata_encode_value (len, b, &b);
2184 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2185 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2186 swap_with_size (blob_size, box_val, len, 1);
2187 mono_image_add_stream_data (&assembly->blob, blob_size, len);
2188 #else
2189 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
2190 #endif
2192 g_free (buf);
2193 return idx;
2196 static guint32
2197 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo, MonoError *error)
2199 MONO_REQ_GC_UNSAFE_MODE;
2201 mono_error_init (error);
2203 char *str;
2204 SigBuffer buf;
2205 guint32 idx, len;
2207 sigbuffer_init (&buf, 32);
2209 sigbuffer_add_value (&buf, minfo->type);
2211 switch (minfo->type) {
2212 case MONO_NATIVE_BYVALTSTR:
2213 case MONO_NATIVE_BYVALARRAY:
2214 sigbuffer_add_value (&buf, minfo->count);
2215 break;
2216 case MONO_NATIVE_LPARRAY:
2217 if (minfo->eltype || minfo->has_size) {
2218 sigbuffer_add_value (&buf, minfo->eltype);
2219 if (minfo->has_size) {
2220 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
2221 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
2223 /* LAMESPEC: ElemMult is undocumented */
2224 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
2227 break;
2228 case MONO_NATIVE_SAFEARRAY:
2229 if (minfo->eltype)
2230 sigbuffer_add_value (&buf, minfo->eltype);
2231 break;
2232 case MONO_NATIVE_CUSTOM:
2233 if (minfo->guid) {
2234 str = mono_string_to_utf8 (minfo->guid);
2235 len = strlen (str);
2236 sigbuffer_add_value (&buf, len);
2237 sigbuffer_add_mem (&buf, str, len);
2238 g_free (str);
2239 } else {
2240 sigbuffer_add_value (&buf, 0);
2242 /* native type name */
2243 sigbuffer_add_value (&buf, 0);
2244 /* custom marshaler type name */
2245 if (minfo->marshaltype || minfo->marshaltyperef) {
2246 if (minfo->marshaltyperef) {
2247 MonoType *marshaltype = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, error);
2248 if (!is_ok (error)) {
2249 sigbuffer_free (&buf);
2250 return 0;
2252 str = type_get_fully_qualified_name (marshaltype);
2253 } else
2254 str = mono_string_to_utf8 (minfo->marshaltype);
2255 len = strlen (str);
2256 sigbuffer_add_value (&buf, len);
2257 sigbuffer_add_mem (&buf, str, len);
2258 g_free (str);
2259 } else {
2260 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
2261 sigbuffer_add_value (&buf, 0);
2263 if (minfo->mcookie) {
2264 str = mono_string_to_utf8 (minfo->mcookie);
2265 len = strlen (str);
2266 sigbuffer_add_value (&buf, len);
2267 sigbuffer_add_mem (&buf, str, len);
2268 g_free (str);
2269 } else {
2270 sigbuffer_add_value (&buf, 0);
2272 break;
2273 default:
2274 break;
2276 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2277 sigbuffer_free (&buf);
2278 return idx;
2281 static void
2282 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly, MonoError *error)
2284 MONO_REQ_GC_UNSAFE_MODE;
2286 mono_error_init (error);
2288 MonoDynamicTable *table;
2289 guint32 *values;
2291 /* maybe this fixup should be done in the C# code */
2292 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
2293 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
2294 table = &assembly->tables [MONO_TABLE_FIELD];
2295 fb->table_idx = table->next_idx ++;
2296 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
2297 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
2298 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
2299 values [MONO_FIELD_FLAGS] = fb->attrs;
2300 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb, error);
2301 return_if_nok (error);
2304 if (fb->offset != -1) {
2305 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
2306 table->rows ++;
2307 alloc_table (table, table->rows);
2308 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
2309 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
2310 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
2312 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
2313 MonoTypeEnum field_type = (MonoTypeEnum)0;
2314 table = &assembly->tables [MONO_TABLE_CONSTANT];
2315 table->rows ++;
2316 alloc_table (table, table->rows);
2317 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2318 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
2319 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
2320 values [MONO_CONSTANT_TYPE] = field_type;
2321 values [MONO_CONSTANT_PADDING] = 0;
2323 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
2324 guint32 rva_idx;
2325 table = &assembly->tables [MONO_TABLE_FIELDRVA];
2326 table->rows ++;
2327 alloc_table (table, table->rows);
2328 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
2329 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
2331 * We store it in the code section because it's simpler for now.
2333 if (fb->rva_data) {
2334 if (mono_array_length (fb->rva_data) >= 10)
2335 stream_data_align (&assembly->code);
2336 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
2337 } else
2338 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
2339 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
2341 if (fb->marshal_info) {
2342 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
2343 table->rows ++;
2344 alloc_table (table, table->rows);
2345 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
2346 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
2347 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info, error);
2348 return_if_nok (error);
2352 static guint32
2353 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb, MonoError *error)
2355 MONO_REQ_GC_UNSAFE_MODE;
2357 mono_error_init (error);
2359 SigBuffer buf;
2360 guint32 nparams = 0;
2361 MonoReflectionMethodBuilder *mb = fb->get_method;
2362 MonoReflectionMethodBuilder *smb = fb->set_method;
2363 guint32 idx, i;
2365 if (mb && mb->parameters)
2366 nparams = mono_array_length (mb->parameters);
2367 if (!mb && smb && smb->parameters)
2368 nparams = mono_array_length (smb->parameters) - 1;
2369 sigbuffer_init (&buf, 32);
2370 if (fb->call_conv & 0x20)
2371 sigbuffer_add_byte (&buf, 0x28);
2372 else
2373 sigbuffer_add_byte (&buf, 0x08);
2374 sigbuffer_add_value (&buf, nparams);
2375 if (mb) {
2376 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf, error);
2377 if (!is_ok (error))
2378 goto fail;
2379 for (i = 0; i < nparams; ++i) {
2380 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2381 encode_reflection_type (assembly, pt, &buf, error);
2382 if (!is_ok (error))
2383 goto fail;
2385 } else if (smb && smb->parameters) {
2386 /* the property type is the last param */
2387 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf, error);
2388 if (!is_ok (error))
2389 goto fail;
2391 for (i = 0; i < nparams; ++i) {
2392 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2393 encode_reflection_type (assembly, pt, &buf, error);
2394 if (!is_ok (error))
2395 goto fail;
2397 } else {
2398 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf, error);
2399 if (!is_ok (error))
2400 goto fail;
2403 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2404 sigbuffer_free (&buf);
2405 return idx;
2406 fail:
2407 sigbuffer_free (&buf);
2408 return 0;
2411 static void
2412 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly, MonoError *error)
2414 MONO_REQ_GC_UNSAFE_MODE;
2416 mono_error_init (error);
2418 MonoDynamicTable *table;
2419 guint32 *values;
2420 guint num_methods = 0;
2421 guint32 semaidx;
2424 * we need to set things in the following tables:
2425 * PROPERTYMAP (info already filled in _get_type_info ())
2426 * PROPERTY (rows already preallocated in _get_type_info ())
2427 * METHOD (method info already done with the generic method code)
2428 * METHODSEMANTICS
2429 * CONSTANT
2431 table = &assembly->tables [MONO_TABLE_PROPERTY];
2432 pb->table_idx = table->next_idx ++;
2433 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2434 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2435 values [MONO_PROPERTY_FLAGS] = pb->attrs;
2436 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb, error);
2437 return_if_nok (error);
2440 /* FIXME: we still don't handle 'other' methods */
2441 if (pb->get_method) num_methods ++;
2442 if (pb->set_method) num_methods ++;
2444 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2445 table->rows += num_methods;
2446 alloc_table (table, table->rows);
2448 if (pb->get_method) {
2449 semaidx = table->next_idx ++;
2450 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2451 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2452 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2453 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2455 if (pb->set_method) {
2456 semaidx = table->next_idx ++;
2457 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2458 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2459 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2460 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2462 if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2463 MonoTypeEnum field_type = (MonoTypeEnum)0;
2464 table = &assembly->tables [MONO_TABLE_CONSTANT];
2465 table->rows ++;
2466 alloc_table (table, table->rows);
2467 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2468 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2469 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2470 values [MONO_CONSTANT_TYPE] = field_type;
2471 values [MONO_CONSTANT_PADDING] = 0;
2475 static void
2476 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly, MonoError *error)
2478 MONO_REQ_GC_UNSAFE_MODE;
2480 MonoDynamicTable *table;
2481 guint32 *values;
2482 guint num_methods = 0;
2483 guint32 semaidx;
2486 * we need to set things in the following tables:
2487 * EVENTMAP (info already filled in _get_type_info ())
2488 * EVENT (rows already preallocated in _get_type_info ())
2489 * METHOD (method info already done with the generic method code)
2490 * METHODSEMANTICS
2492 table = &assembly->tables [MONO_TABLE_EVENT];
2493 eb->table_idx = table->next_idx ++;
2494 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2495 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2496 values [MONO_EVENT_FLAGS] = eb->attrs;
2497 MonoType *ebtype = mono_reflection_type_get_handle (eb->type, error);
2498 return_if_nok (error);
2499 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, ebtype);
2502 * FIXME: we still don't handle 'other' methods
2504 if (eb->add_method) num_methods ++;
2505 if (eb->remove_method) num_methods ++;
2506 if (eb->raise_method) num_methods ++;
2508 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2509 table->rows += num_methods;
2510 alloc_table (table, table->rows);
2512 if (eb->add_method) {
2513 semaidx = table->next_idx ++;
2514 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2515 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2516 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2517 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2519 if (eb->remove_method) {
2520 semaidx = table->next_idx ++;
2521 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2522 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2523 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2524 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2526 if (eb->raise_method) {
2527 semaidx = table->next_idx ++;
2528 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2529 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2530 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2531 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2535 static void
2536 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly, MonoError *error)
2538 MONO_REQ_GC_UNSAFE_MODE;
2540 mono_error_init (error);
2542 MonoDynamicTable *table;
2543 guint32 num_constraints, i;
2544 guint32 *values;
2545 guint32 table_idx;
2547 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2548 num_constraints = gparam->iface_constraints ?
2549 mono_array_length (gparam->iface_constraints) : 0;
2550 table->rows += num_constraints;
2551 if (gparam->base_type)
2552 table->rows++;
2553 alloc_table (table, table->rows);
2555 if (gparam->base_type) {
2556 table_idx = table->next_idx ++;
2557 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2559 MonoType *gpbasetype = mono_reflection_type_get_handle (gparam->base_type, error);
2560 return_if_nok (error);
2561 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2562 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, gpbasetype);
2565 for (i = 0; i < num_constraints; i++) {
2566 MonoReflectionType *constraint = (MonoReflectionType *)mono_array_get (
2567 gparam->iface_constraints, gpointer, i);
2569 table_idx = table->next_idx ++;
2570 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2572 MonoType *constraint_type = mono_reflection_type_get_handle (constraint, error);
2573 return_if_nok (error);
2575 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2576 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, constraint_type);
2580 static void
2581 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2583 MONO_REQ_GC_UNSAFE_MODE;
2585 GenericParamTableEntry *entry;
2588 * The GenericParam table must be sorted according to the `owner' field.
2589 * We need to do this sorting prior to writing the GenericParamConstraint
2590 * table, since we have to use the final GenericParam table indices there
2591 * and they must also be sorted.
2594 entry = g_new0 (GenericParamTableEntry, 1);
2595 entry->owner = owner;
2596 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2597 MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam, MONO_ROOT_SOURCE_REFLECTION, "reflection generic parameter");
2598 entry->gparam = gparam;
2600 g_ptr_array_add (assembly->gen_params, entry);
2603 static gboolean
2604 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry, MonoError *error)
2606 MONO_REQ_GC_UNSAFE_MODE;
2608 MonoDynamicTable *table;
2609 MonoGenericParam *param;
2610 guint32 *values;
2611 guint32 table_idx;
2613 mono_error_init (error);
2615 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2616 table_idx = table->next_idx ++;
2617 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2619 MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam, error);
2620 return_val_if_nok (error, FALSE);
2622 param = gparam_type->data.generic_param;
2624 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2625 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2626 values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2627 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2629 if (!mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs, error))
2630 return FALSE;
2632 encode_constraints (entry->gparam, table_idx, assembly, error);
2633 return_val_if_nok (error, FALSE);
2635 return TRUE;
2638 static guint32
2639 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2641 MONO_REQ_GC_UNSAFE_MODE;
2643 MonoDynamicTable *table;
2644 guint32 token;
2645 guint32 *values;
2646 guint32 cols [MONO_ASSEMBLY_SIZE];
2647 const char *pubkey;
2648 guint32 publen;
2650 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2651 return token;
2653 if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
2654 table = &assembly->tables [MONO_TABLE_MODULEREF];
2655 token = table->next_idx ++;
2656 table->rows ++;
2657 alloc_table (table, table->rows);
2658 values = table->values + token * MONO_MODULEREF_SIZE;
2659 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2661 token <<= MONO_RESOLUTION_SCOPE_BITS;
2662 token |= MONO_RESOLUTION_SCOPE_MODULEREF;
2663 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2665 return token;
2668 if (assembly_is_dynamic (image->assembly))
2669 /* FIXME: */
2670 memset (cols, 0, sizeof (cols));
2671 else {
2672 /* image->assembly->image is the manifest module */
2673 image = image->assembly->image;
2674 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2677 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2678 token = table->next_idx ++;
2679 table->rows ++;
2680 alloc_table (table, table->rows);
2681 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2682 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2683 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2684 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2685 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2686 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2687 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2688 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2689 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2691 if (strcmp ("", image->assembly->aname.culture)) {
2692 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2693 image->assembly->aname.culture);
2696 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2697 guchar pubtoken [9];
2698 pubtoken [0] = 8;
2699 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2700 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2701 } else {
2702 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2704 token <<= MONO_RESOLUTION_SCOPE_BITS;
2705 token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
2706 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2707 return token;
2710 static guint32
2711 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2713 MONO_REQ_GC_NEUTRAL_MODE;
2715 MonoDynamicTable *table;
2716 guint32 *values;
2717 guint32 token;
2718 SigBuffer buf;
2720 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2721 return token;
2723 sigbuffer_init (&buf, 32);
2724 switch (type->type) {
2725 case MONO_TYPE_FNPTR:
2726 case MONO_TYPE_PTR:
2727 case MONO_TYPE_SZARRAY:
2728 case MONO_TYPE_ARRAY:
2729 case MONO_TYPE_VAR:
2730 case MONO_TYPE_MVAR:
2731 case MONO_TYPE_GENERICINST:
2732 encode_type (assembly, type, &buf);
2733 break;
2734 case MONO_TYPE_CLASS:
2735 case MONO_TYPE_VALUETYPE: {
2736 MonoClass *k = mono_class_from_mono_type (type);
2737 if (!k || !k->generic_container) {
2738 sigbuffer_free (&buf);
2739 return 0;
2741 encode_type (assembly, type, &buf);
2742 break;
2744 default:
2745 sigbuffer_free (&buf);
2746 return 0;
2749 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2750 if (assembly->save) {
2751 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2752 alloc_table (table, table->rows + 1);
2753 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2754 values [MONO_TYPESPEC_SIGNATURE] = token;
2756 sigbuffer_free (&buf);
2758 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2759 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2760 table->next_idx ++;
2761 return token;
2764 static guint32
2765 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2767 MONO_REQ_GC_UNSAFE_MODE;
2769 MonoDynamicTable *table;
2770 guint32 *values;
2771 guint32 token, scope, enclosing;
2772 MonoClass *klass;
2774 /* if the type requires a typespec, we must try that first*/
2775 if (try_typespec && (token = create_typespec (assembly, type)))
2776 return token;
2777 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2778 if (token)
2779 return token;
2780 klass = mono_class_from_mono_type (type);
2781 if (!klass)
2782 klass = mono_class_from_mono_type (type);
2785 * If it's in the same module and not a generic type parameter:
2787 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2788 (type->type != MONO_TYPE_MVAR)) {
2789 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
2790 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2791 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2792 return token;
2795 if (klass->nested_in) {
2796 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2797 /* get the typeref idx of the enclosing type */
2798 enclosing >>= MONO_TYPEDEFORREF_BITS;
2799 scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF;
2800 } else {
2801 scope = resolution_scope_from_image (assembly, klass->image);
2803 table = &assembly->tables [MONO_TABLE_TYPEREF];
2804 if (assembly->save) {
2805 alloc_table (table, table->rows + 1);
2806 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2807 values [MONO_TYPEREF_SCOPE] = scope;
2808 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2809 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2811 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2812 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2813 table->next_idx ++;
2814 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2815 return token;
2819 * Despite the name, we handle also TypeSpec (with the above helper).
2821 static guint32
2822 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2824 return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2827 #ifndef DISABLE_REFLECTION_EMIT
2828 static guint32
2829 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2831 MONO_REQ_GC_NEUTRAL_MODE;
2833 MonoDynamicTable *table;
2834 guint32 *values;
2835 guint32 token, pclass;
2837 switch (parent & MONO_TYPEDEFORREF_MASK) {
2838 case MONO_TYPEDEFORREF_TYPEREF:
2839 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2840 break;
2841 case MONO_TYPEDEFORREF_TYPESPEC:
2842 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2843 break;
2844 case MONO_TYPEDEFORREF_TYPEDEF:
2845 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2846 break;
2847 default:
2848 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2849 return 0;
2851 /* extract the index */
2852 parent >>= MONO_TYPEDEFORREF_BITS;
2854 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2856 if (assembly->save) {
2857 alloc_table (table, table->rows + 1);
2858 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2859 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2860 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2861 values [MONO_MEMBERREF_SIGNATURE] = sig;
2864 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2865 table->next_idx ++;
2867 return token;
2871 * Insert a memberef row into the metadata: the token that point to the memberref
2872 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2873 * mono_image_get_fieldref_token()).
2874 * The sig param is an index to an already built signature.
2876 static guint32
2877 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2879 MONO_REQ_GC_NEUTRAL_MODE;
2881 guint32 parent = mono_image_typedef_or_ref (assembly, type);
2882 return mono_image_add_memberef_row (assembly, parent, name, sig);
2886 static guint32
2887 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2889 MONO_REQ_GC_NEUTRAL_MODE;
2891 guint32 token;
2892 MonoMethodSignature *sig;
2894 create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2896 if (create_typespec) {
2897 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2898 if (token)
2899 return token;
2902 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2903 if (token && !create_typespec)
2904 return token;
2906 g_assert (!method->is_inflated);
2907 if (!token) {
2909 * A methodref signature can't contain an unmanaged calling convention.
2911 sig = mono_metadata_signature_dup (mono_method_signature (method));
2912 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2913 sig->call_convention = MONO_CALL_DEFAULT;
2914 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2915 method->name, method_encode_signature (assembly, sig));
2916 g_free (sig);
2917 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2920 if (create_typespec) {
2921 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2922 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2923 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2925 if (assembly->save) {
2926 guint32 *values;
2928 alloc_table (table, table->rows + 1);
2929 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2930 values [MONO_METHODSPEC_METHOD] = token;
2931 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2934 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2935 table->next_idx ++;
2936 /*methodspec and memberef tokens are diferent, */
2937 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2938 return token;
2940 return token;
2943 static guint32
2944 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method, MonoError *error)
2946 guint32 token, parent, sig;
2947 ReflectionMethodBuilder rmb;
2948 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2950 mono_error_init (error);
2951 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2952 if (token)
2953 return token;
2955 if (!reflection_methodbuilder_from_method_builder (&rmb, method, error))
2956 return 0;
2959 * A methodref signature can't contain an unmanaged calling convention.
2960 * Since some flags are encoded as part of call_conv, we need to check against it.
2962 if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2963 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2965 sig = method_builder_encode_signature (assembly, &rmb, error);
2966 return_val_if_nok (error, 0);
2968 if (tb->generic_params) {
2969 parent = create_generic_typespec (assembly, tb, error);
2970 return_val_if_nok (error, 0);
2971 } else {
2972 MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type, error);
2973 return_val_if_nok (error, 0);
2975 parent = mono_image_typedef_or_ref (assembly, t);
2978 char *name = mono_string_to_utf8 (method->name);
2980 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2981 g_free (name);
2983 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2985 return token;
2988 static guint32
2989 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2990 const gchar *name, guint32 sig)
2992 MonoDynamicTable *table;
2993 guint32 token;
2994 guint32 *values;
2996 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2998 if (assembly->save) {
2999 alloc_table (table, table->rows + 1);
3000 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3001 values [MONO_MEMBERREF_CLASS] = original;
3002 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3003 values [MONO_MEMBERREF_SIGNATURE] = sig;
3006 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3007 table->next_idx ++;
3009 return token;
3012 static guint32
3013 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
3015 SigBuffer buf;
3016 int i;
3017 guint32 nparams = mono_array_length (mb->generic_params);
3018 guint32 idx;
3020 if (!assembly->save)
3021 return 0;
3023 sigbuffer_init (&buf, 32);
3025 sigbuffer_add_value (&buf, 0xa);
3026 sigbuffer_add_value (&buf, nparams);
3028 for (i = 0; i < nparams; i++) {
3029 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
3030 sigbuffer_add_value (&buf, i);
3033 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3034 sigbuffer_free (&buf);
3035 return idx;
3038 static guint32
3039 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
3041 MonoDynamicTable *table;
3042 guint32 *values;
3043 guint32 token, mtoken = 0;
3045 mono_error_init (error);
3046 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
3047 if (token)
3048 return token;
3050 table = &assembly->tables [MONO_TABLE_METHODSPEC];
3052 mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
3053 if (!mono_error_ok (error))
3054 return 0;
3056 switch (mono_metadata_token_table (mtoken)) {
3057 case MONO_TABLE_MEMBERREF:
3058 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3059 break;
3060 case MONO_TABLE_METHOD:
3061 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3062 break;
3063 default:
3064 g_assert_not_reached ();
3067 if (assembly->save) {
3068 alloc_table (table, table->rows + 1);
3069 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3070 values [MONO_METHODSPEC_METHOD] = mtoken;
3071 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
3074 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3075 table->next_idx ++;
3077 mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
3078 return token;
3081 static guint32
3082 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec, MonoError *error)
3084 guint32 token;
3086 mono_error_init (error);
3088 if (mb->generic_params && create_methodspec)
3089 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb, error);
3091 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
3092 if (token)
3093 return token;
3095 token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
3096 if (!mono_error_ok (error))
3097 return 0;
3098 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
3099 return token;
3102 static guint32
3103 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb, MonoError *error)
3105 guint32 token, parent, sig;
3106 ReflectionMethodBuilder rmb;
3107 char *name;
3108 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
3110 mono_error_init (error);
3112 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
3113 if (token)
3114 return token;
3116 if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
3117 return 0;
3119 if (tb->generic_params) {
3120 parent = create_generic_typespec (assembly, tb, error);
3121 return_val_if_nok (error, 0);
3122 } else {
3123 MonoType * type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
3124 return_val_if_nok (error, 0);
3125 parent = mono_image_typedef_or_ref (assembly, type);
3128 name = mono_string_to_utf8 (rmb.name);
3129 sig = method_builder_encode_signature (assembly, &rmb, error);
3130 return_val_if_nok (error, 0);
3132 token = mono_image_add_memberef_row (assembly, parent, name, sig);
3134 g_free (name);
3135 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
3136 return token;
3138 #endif
3140 static gboolean
3141 is_field_on_inst (MonoClassField *field)
3143 return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
3147 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
3149 static MonoType*
3150 get_field_on_inst_generic_type (MonoClassField *field)
3152 MonoClass *klass, *gtd;
3153 MonoDynamicGenericClass *dgclass;
3154 int field_index;
3156 g_assert (is_field_on_inst (field));
3158 dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
3160 if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
3161 field_index = field - dgclass->fields;
3162 return dgclass->field_generic_types [field_index];
3165 klass = field->parent;
3166 gtd = klass->generic_class->container_class;
3168 if (field >= klass->fields && field - klass->fields < klass->field.count) {
3169 field_index = field - klass->fields;
3170 return gtd->fields [field_index].type;
3173 g_assert_not_reached ();
3174 return 0;
3177 #ifndef DISABLE_REFLECTION_EMIT
3178 static guint32
3179 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
3181 MonoType *type;
3182 guint32 token;
3184 g_assert (field);
3185 g_assert (field->parent);
3187 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3188 if (token)
3189 return token;
3191 if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
3192 int index = field - field->parent->fields;
3193 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
3194 } else {
3195 if (is_field_on_inst (field))
3196 type = get_field_on_inst_generic_type (field);
3197 else
3198 type = mono_field_get_type (field);
3200 token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
3201 mono_field_get_name (field),
3202 fieldref_encode_signature (assembly, field->parent->image, type));
3203 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
3204 return token;
3207 static guint32
3208 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f, MonoError *error)
3210 guint32 token;
3211 MonoClass *klass;
3212 MonoGenericClass *gclass;
3213 MonoType *type;
3214 char *name;
3216 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3217 if (token)
3218 return token;
3219 if (is_sre_field_builder (mono_object_class (f->fb))) {
3220 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
3221 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
3222 return_val_if_nok (error, 0);
3223 klass = mono_class_from_mono_type (type);
3224 gclass = type->data.generic_class;
3225 g_assert (gclass->is_dynamic);
3227 guint32 sig_token = field_encode_signature (assembly, fb, error);
3228 return_val_if_nok (error, 0);
3229 name = mono_string_to_utf8 (fb->name);
3230 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig_token);
3231 g_free (name);
3232 } else if (is_sr_mono_field (mono_object_class (f->fb))) {
3233 guint32 sig;
3234 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
3236 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
3237 return_val_if_nok (error, 0);
3238 klass = mono_class_from_mono_type (type);
3240 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
3241 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
3242 } else {
3243 char *name = mono_type_get_full_name (mono_object_class (f->fb));
3244 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
3247 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
3248 return token;
3251 static guint32
3252 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec, MonoError *error)
3254 guint32 sig, token;
3255 MonoClass *klass;
3256 MonoGenericClass *gclass;
3257 MonoType *type;
3259 mono_error_init (error);
3261 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
3263 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
3264 if (token)
3265 return token;
3267 if (is_sre_ctor_builder (mono_object_class (c->cb))) {
3268 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
3269 ReflectionMethodBuilder rmb;
3270 char *name;
3272 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
3273 return_val_if_nok (error, 0);
3274 klass = mono_class_from_mono_type (type);
3276 gclass = type->data.generic_class;
3277 g_assert (gclass->is_dynamic);
3279 if (!reflection_methodbuilder_from_ctor_builder (&rmb, cb, error))
3280 return 0;
3282 sig = method_builder_encode_signature (assembly, &rmb, error);
3283 return_val_if_nok (error, 0);
3285 name = mono_string_to_utf8 (rmb.name);
3287 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3288 g_free (name);
3289 } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
3290 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
3292 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
3293 return_val_if_nok (error, 0);
3294 klass = mono_class_from_mono_type (type);
3296 sig = method_encode_signature (assembly, mono_method_signature (mm));
3297 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3298 } else {
3299 char *name = mono_type_get_full_name (mono_object_class (c->cb));
3300 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3304 mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
3305 return token;
3308 static MonoMethod*
3309 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m, MonoError *error)
3311 MonoClass *klass;
3312 MonoGenericContext tmp_context;
3313 MonoType **type_argv;
3314 MonoGenericInst *ginst;
3315 MonoMethod *method, *inflated;
3316 int count, i;
3318 mono_error_init (error);
3320 init_type_builder_generics ((MonoObject*)m->inst);
3322 method = inflate_method (m->inst, (MonoObject*)m->mb, error);
3323 return_val_if_nok (error, NULL);
3325 klass = method->klass;
3327 if (m->method_args == NULL)
3328 return method;
3330 if (method->is_inflated)
3331 method = ((MonoMethodInflated *) method)->declaring;
3333 count = mono_array_length (m->method_args);
3335 type_argv = g_new0 (MonoType *, count);
3336 for (i = 0; i < count; i++) {
3337 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (m->method_args, gpointer, i);
3338 type_argv [i] = mono_reflection_type_get_handle (garg, error);
3339 return_val_if_nok (error, NULL);
3341 ginst = mono_metadata_get_generic_inst (count, type_argv);
3342 g_free (type_argv);
3344 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
3345 tmp_context.method_inst = ginst;
3347 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, error);
3348 mono_error_assert_ok (error);
3349 return inflated;
3352 static guint32
3353 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec, MonoError *error)
3355 guint32 sig, token = 0;
3356 MonoType *type;
3357 MonoClass *klass;
3359 mono_error_init (error);
3361 if (m->method_args) {
3362 MonoMethod *inflated;
3364 inflated = mono_reflection_method_on_tb_inst_get_handle (m, error);
3365 return_val_if_nok (error, 0);
3367 if (create_methodspec)
3368 token = mono_image_get_methodspec_token (assembly, inflated);
3369 else
3370 token = mono_image_get_inflated_method_token (assembly, inflated);
3371 return token;
3374 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
3375 if (token)
3376 return token;
3378 if (is_sre_method_builder (mono_object_class (m->mb))) {
3379 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
3380 MonoGenericClass *gclass;
3381 ReflectionMethodBuilder rmb;
3382 char *name;
3384 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
3385 return_val_if_nok (error, 0);
3386 klass = mono_class_from_mono_type (type);
3387 gclass = type->data.generic_class;
3388 g_assert (gclass->is_dynamic);
3390 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
3391 return 0;
3393 sig = method_builder_encode_signature (assembly, &rmb, error);
3394 return_val_if_nok (error, 0);
3396 name = mono_string_to_utf8 (rmb.name);
3398 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3399 g_free (name);
3400 } else if (is_sr_mono_method (mono_object_class (m->mb))) {
3401 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
3403 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
3404 return_val_if_nok (error, 0);
3405 klass = mono_class_from_mono_type (type);
3407 sig = method_encode_signature (assembly, mono_method_signature (mm));
3408 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3409 } else {
3410 char *name = mono_type_get_full_name (mono_object_class (m->mb));
3411 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3414 mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
3415 return token;
3418 static guint32
3419 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
3421 SigBuffer buf;
3422 int i;
3423 guint32 nparams = context->method_inst->type_argc;
3424 guint32 idx;
3426 if (!assembly->save)
3427 return 0;
3429 sigbuffer_init (&buf, 32);
3431 * FIXME: vararg, explicit_this, differenc call_conv values...
3433 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
3434 sigbuffer_add_value (&buf, nparams);
3436 for (i = 0; i < nparams; i++)
3437 encode_type (assembly, context->method_inst->type_argv [i], &buf);
3439 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3440 sigbuffer_free (&buf);
3441 return idx;
3444 static guint32
3445 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
3447 MonoDynamicTable *table;
3448 guint32 *values;
3449 guint32 token, mtoken = 0, sig;
3450 MonoMethodInflated *imethod;
3451 MonoMethod *declaring;
3453 table = &assembly->tables [MONO_TABLE_METHODSPEC];
3455 g_assert (method->is_inflated);
3456 imethod = (MonoMethodInflated *) method;
3457 declaring = imethod->declaring;
3459 sig = method_encode_signature (assembly, mono_method_signature (declaring));
3460 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3462 if (!mono_method_signature (declaring)->generic_param_count)
3463 return mtoken;
3465 switch (mono_metadata_token_table (mtoken)) {
3466 case MONO_TABLE_MEMBERREF:
3467 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3468 break;
3469 case MONO_TABLE_METHOD:
3470 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3471 break;
3472 default:
3473 g_assert_not_reached ();
3476 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3478 if (assembly->save) {
3479 alloc_table (table, table->rows + 1);
3480 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3481 values [MONO_METHODSPEC_METHOD] = mtoken;
3482 values [MONO_METHODSPEC_SIGNATURE] = sig;
3485 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3486 table->next_idx ++;
3488 return token;
3491 static guint32
3492 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3494 MonoMethodInflated *imethod;
3495 guint32 token;
3497 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3498 if (token)
3499 return token;
3501 g_assert (method->is_inflated);
3502 imethod = (MonoMethodInflated *) method;
3504 if (mono_method_signature (imethod->declaring)->generic_param_count) {
3505 token = method_encode_methodspec (assembly, method);
3506 } else {
3507 guint32 sig = method_encode_signature (
3508 assembly, mono_method_signature (imethod->declaring));
3509 token = mono_image_get_memberref_token (
3510 assembly, &method->klass->byval_arg, method->name, sig);
3513 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3514 return token;
3517 static guint32
3518 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3520 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3521 guint32 sig, token;
3523 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3524 token = mono_image_get_memberref_token (
3525 assembly, &m->klass->byval_arg, m->name, sig);
3527 return token;
3530 static guint32
3531 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error)
3533 MonoDynamicTable *table;
3534 MonoClass *klass;
3535 MonoType *type;
3536 guint32 *values;
3537 guint32 token;
3538 SigBuffer buf;
3539 int count, i;
3542 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3543 * ie. what we'd normally use as the generic type in a TypeSpec signature.
3544 * Because of this, we must not insert it into the `typeref' hash table.
3546 type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
3547 return_val_if_nok (error, 0);
3548 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3549 if (token)
3550 return token;
3552 sigbuffer_init (&buf, 32);
3554 g_assert (tb->generic_params);
3555 klass = mono_class_from_mono_type (type);
3557 if (tb->generic_container)
3558 mono_reflection_create_generic_class (tb);
3560 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3561 g_assert (klass->generic_container);
3562 sigbuffer_add_value (&buf, klass->byval_arg.type);
3563 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3565 count = mono_array_length (tb->generic_params);
3566 sigbuffer_add_value (&buf, count);
3567 for (i = 0; i < count; i++) {
3568 MonoReflectionGenericParam *gparam;
3570 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3571 MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, error);
3572 if (!is_ok (error))
3573 goto fail;
3575 encode_type (assembly, gparam_type, &buf);
3578 table = &assembly->tables [MONO_TABLE_TYPESPEC];
3580 if (assembly->save) {
3581 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3582 alloc_table (table, table->rows + 1);
3583 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3584 values [MONO_TYPESPEC_SIGNATURE] = token;
3586 sigbuffer_free (&buf);
3588 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3589 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3590 table->next_idx ++;
3591 return token;
3592 fail:
3593 sigbuffer_free (&buf);
3594 return 0;
3598 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3600 static MonoType*
3601 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt, MonoError *error)
3603 int i, count, len, pos;
3604 MonoType *t;
3606 mono_error_init (error);
3608 count = 0;
3609 if (modreq)
3610 count += mono_array_length (modreq);
3611 if (modopt)
3612 count += mono_array_length (modopt);
3614 if (count == 0)
3615 return mono_metadata_type_dup (NULL, type);
3617 len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3618 t = (MonoType *)g_malloc (len);
3619 memcpy (t, type, MONO_SIZEOF_TYPE);
3621 t->num_mods = count;
3622 pos = 0;
3623 if (modreq) {
3624 for (i = 0; i < mono_array_length (modreq); ++i) {
3625 MonoType *mod = mono_type_array_get_and_resolve (modreq, i, error);
3626 if (!is_ok (error))
3627 goto fail;
3628 t->modifiers [pos].required = 1;
3629 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3630 pos ++;
3633 if (modopt) {
3634 for (i = 0; i < mono_array_length (modopt); ++i) {
3635 MonoType *mod = mono_type_array_get_and_resolve (modopt, i, error);
3636 if (!is_ok (error))
3637 goto fail;
3638 t->modifiers [pos].required = 0;
3639 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3640 pos ++;
3644 return t;
3645 fail:
3646 g_free (t);
3647 return NULL;
3650 static void
3651 init_type_builder_generics (MonoObject *type)
3653 MonoReflectionTypeBuilder *tb;
3655 if (!is_sre_type_builder(mono_object_class (type)))
3656 return;
3657 tb = (MonoReflectionTypeBuilder *)type;
3659 if (tb && tb->generic_container)
3660 mono_reflection_create_generic_class (tb);
3663 static guint32
3664 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb, MonoError *error)
3666 MonoDynamicTable *table;
3667 MonoType *custom = NULL, *type;
3668 guint32 *values;
3669 guint32 token, pclass, parent, sig;
3670 gchar *name;
3672 mono_error_init (error);
3674 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3675 if (token)
3676 return token;
3678 MonoType *typeb = mono_reflection_type_get_handle (fb->typeb, error);
3679 return_val_if_nok (error, 0);
3680 /* FIXME: is this call necessary? */
3681 mono_class_from_mono_type (typeb);
3683 /*FIXME this is one more layer of ugliness due how types are created.*/
3684 init_type_builder_generics (fb->type);
3686 /* fb->type does not include the custom modifiers */
3687 /* FIXME: We should do this in one place when a fieldbuilder is created */
3688 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
3689 return_val_if_nok (error, 0);
3691 if (fb->modreq || fb->modopt) {
3692 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt, error);
3693 return_val_if_nok (error, 0);
3696 sig = fieldref_encode_signature (assembly, NULL, type);
3697 g_free (custom);
3699 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb, error);
3700 return_val_if_nok (error, 0);
3701 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3703 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3704 parent >>= MONO_TYPEDEFORREF_BITS;
3706 table = &assembly->tables [MONO_TABLE_MEMBERREF];
3708 name = mono_string_to_utf8 (fb->name);
3710 if (assembly->save) {
3711 alloc_table (table, table->rows + 1);
3712 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3713 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3714 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3715 values [MONO_MEMBERREF_SIGNATURE] = sig;
3718 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3719 table->next_idx ++;
3720 mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3721 g_free (name);
3722 return token;
3725 static guint32
3726 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error)
3728 SigBuffer buf;
3729 guint32 nargs;
3730 guint32 i, idx;
3732 mono_error_init (error);
3734 if (!assembly->save)
3735 return 0;
3737 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3738 g_assert (helper->type == 2);
3740 if (helper->arguments)
3741 nargs = mono_array_length (helper->arguments);
3742 else
3743 nargs = 0;
3745 sigbuffer_init (&buf, 32);
3747 /* Encode calling convention */
3748 /* Change Any to Standard */
3749 if ((helper->call_conv & 0x03) == 0x03)
3750 helper->call_conv = 0x01;
3751 /* explicit_this implies has_this */
3752 if (helper->call_conv & 0x40)
3753 helper->call_conv &= 0x20;
3755 if (helper->call_conv == 0) { /* Unmanaged */
3756 idx = helper->unmanaged_call_conv - 1;
3757 } else {
3758 /* Managed */
3759 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3760 if (helper->call_conv & 0x02) /* varargs */
3761 idx += 0x05;
3764 sigbuffer_add_byte (&buf, idx);
3765 sigbuffer_add_value (&buf, nargs);
3766 encode_reflection_type (assembly, helper->return_type, &buf, error);
3767 if (!is_ok (error))
3768 goto fail;
3769 for (i = 0; i < nargs; ++i) {
3770 MonoArray *modreqs = NULL;
3771 MonoArray *modopts = NULL;
3772 MonoReflectionType *pt;
3774 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3775 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3776 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3777 modopts = mono_array_get (helper->modopts, MonoArray*, i);
3779 encode_custom_modifiers (assembly, modreqs, modopts, &buf, error);
3780 if (!is_ok (error))
3781 goto fail;
3782 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3783 encode_reflection_type (assembly, pt, &buf, error);
3784 if (!is_ok (error))
3785 goto fail;
3787 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3788 sigbuffer_free (&buf);
3790 return idx;
3791 fail:
3792 sigbuffer_free (&buf);
3793 return 0;
3796 static guint32
3797 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error)
3799 guint32 idx;
3800 MonoDynamicTable *table;
3801 guint32 *values;
3803 mono_error_init (error);
3805 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3806 idx = table->next_idx ++;
3807 table->rows ++;
3808 alloc_table (table, table->rows);
3809 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3811 values [MONO_STAND_ALONE_SIGNATURE] =
3812 mono_reflection_encode_sighelper (assembly, helper, error);
3813 return_val_if_nok (error, 0);
3815 return idx;
3818 static int
3819 reflection_cc_to_file (int call_conv) {
3820 switch (call_conv & 0x3) {
3821 case 0:
3822 case 1: return MONO_CALL_DEFAULT;
3823 case 2: return MONO_CALL_VARARG;
3824 default:
3825 g_assert_not_reached ();
3827 return 0;
3829 #endif /* !DISABLE_REFLECTION_EMIT */
3831 typedef struct {
3832 MonoType *parent;
3833 MonoMethodSignature *sig;
3834 char *name;
3835 guint32 token;
3836 } ArrayMethod;
3838 #ifndef DISABLE_REFLECTION_EMIT
3839 static guint32
3840 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m, MonoError *error)
3842 guint32 nparams, i;
3843 GList *tmp;
3844 char *name = NULL;
3845 MonoMethodSignature *sig;
3846 ArrayMethod *am = NULL;
3847 MonoType *mtype;
3849 mono_error_init (error);
3851 nparams = mono_array_length (m->parameters);
3852 sig = (MonoMethodSignature *)g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3853 sig->hasthis = 1;
3854 sig->sentinelpos = -1;
3855 sig->call_convention = reflection_cc_to_file (m->call_conv);
3856 sig->param_count = nparams;
3857 if (m->ret) {
3858 sig->ret = mono_reflection_type_get_handle (m->ret, error);
3859 if (!is_ok (error))
3860 goto fail;
3861 } else
3862 sig->ret = &mono_defaults.void_class->byval_arg;
3864 mtype = mono_reflection_type_get_handle (m->parent, error);
3865 if (!is_ok (error))
3866 goto fail;
3868 for (i = 0; i < nparams; ++i) {
3869 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i, error);
3870 if (!is_ok (error))
3871 goto fail;
3874 name = mono_string_to_utf8 (m->name);
3875 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3876 am = (ArrayMethod *)tmp->data;
3877 if (strcmp (name, am->name) == 0 &&
3878 mono_metadata_type_equal (am->parent, mtype) &&
3879 mono_metadata_signature_equal (am->sig, sig)) {
3880 g_free (name);
3881 g_free (sig);
3882 m->table_idx = am->token & 0xffffff;
3883 return am->token;
3886 am = g_new0 (ArrayMethod, 1);
3887 am->name = name;
3888 am->sig = sig;
3889 am->parent = mtype;
3890 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3891 method_encode_signature (assembly, sig));
3892 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3893 m->table_idx = am->token & 0xffffff;
3894 return am->token;
3895 fail:
3896 g_free (am);
3897 g_free (name);
3898 g_free (sig);
3899 return 0;
3904 * Insert into the metadata tables all the info about the TypeBuilder tb.
3905 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3907 static gboolean
3908 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly, MonoError *error)
3910 MonoDynamicTable *table;
3911 guint *values;
3912 int i, is_object = 0, is_system = 0;
3913 char *n;
3915 mono_error_init (error);
3917 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3918 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3919 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3920 n = mono_string_to_utf8 (tb->name);
3921 if (strcmp (n, "Object") == 0)
3922 is_object++;
3923 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3924 g_free (n);
3925 n = mono_string_to_utf8 (tb->nspace);
3926 if (strcmp (n, "System") == 0)
3927 is_system++;
3928 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3929 g_free (n);
3930 if (tb->parent && !(is_system && is_object) &&
3931 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3932 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
3933 return_val_if_nok (error, FALSE);
3934 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, parent_type);
3935 } else {
3936 values [MONO_TYPEDEF_EXTENDS] = 0;
3938 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3939 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3942 * if we have explicitlayout or sequentiallayouts, output data in the
3943 * ClassLayout table.
3945 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3946 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3947 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3948 table->rows++;
3949 alloc_table (table, table->rows);
3950 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3951 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3952 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3953 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3956 /* handle interfaces */
3957 if (tb->interfaces) {
3958 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3959 i = table->rows;
3960 table->rows += mono_array_length (tb->interfaces);
3961 alloc_table (table, table->rows);
3962 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3963 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3964 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3965 MonoType *iface_type = mono_reflection_type_get_handle (iface, error);
3966 return_val_if_nok (error, FALSE);
3967 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3968 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface_type);
3969 values += MONO_INTERFACEIMPL_SIZE;
3973 /* handle fields */
3974 if (tb->fields) {
3975 table = &assembly->tables [MONO_TABLE_FIELD];
3976 table->rows += tb->num_fields;
3977 alloc_table (table, table->rows);
3978 for (i = 0; i < tb->num_fields; ++i) {
3979 mono_image_get_field_info (
3980 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly, error);
3981 return_val_if_nok (error, FALSE);
3985 /* handle constructors */
3986 if (tb->ctors) {
3987 table = &assembly->tables [MONO_TABLE_METHOD];
3988 table->rows += mono_array_length (tb->ctors);
3989 alloc_table (table, table->rows);
3990 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3991 if (!mono_image_get_ctor_info (domain,
3992 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i),
3993 assembly, error))
3994 return FALSE;
3998 /* handle methods */
3999 if (tb->methods) {
4000 table = &assembly->tables [MONO_TABLE_METHOD];
4001 table->rows += tb->num_methods;
4002 alloc_table (table, table->rows);
4003 for (i = 0; i < tb->num_methods; ++i) {
4004 if (!mono_image_get_method_info (
4005 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly, error))
4006 return FALSE;
4010 /* Do the same with properties etc.. */
4011 if (tb->events && mono_array_length (tb->events)) {
4012 table = &assembly->tables [MONO_TABLE_EVENT];
4013 table->rows += mono_array_length (tb->events);
4014 alloc_table (table, table->rows);
4015 table = &assembly->tables [MONO_TABLE_EVENTMAP];
4016 table->rows ++;
4017 alloc_table (table, table->rows);
4018 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
4019 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
4020 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
4021 for (i = 0; i < mono_array_length (tb->events); ++i) {
4022 mono_image_get_event_info (
4023 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly, error);
4024 return_val_if_nok (error, FALSE);
4027 if (tb->properties && mono_array_length (tb->properties)) {
4028 table = &assembly->tables [MONO_TABLE_PROPERTY];
4029 table->rows += mono_array_length (tb->properties);
4030 alloc_table (table, table->rows);
4031 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
4032 table->rows ++;
4033 alloc_table (table, table->rows);
4034 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
4035 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
4036 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
4037 for (i = 0; i < mono_array_length (tb->properties); ++i) {
4038 mono_image_get_property_info (
4039 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly, error);
4040 return_val_if_nok (error, FALSE);
4044 /* handle generic parameters */
4045 if (tb->generic_params) {
4046 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
4047 table->rows += mono_array_length (tb->generic_params);
4048 alloc_table (table, table->rows);
4049 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
4050 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
4052 mono_image_get_generic_param_info (
4053 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
4057 mono_image_add_decl_security (assembly,
4058 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
4060 if (tb->subtypes) {
4061 MonoDynamicTable *ntable;
4063 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4064 ntable->rows += mono_array_length (tb->subtypes);
4065 alloc_table (ntable, ntable->rows);
4066 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
4068 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4069 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
4071 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
4072 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
4073 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
4074 mono_string_to_utf8 (subtype->name), subtype->table_idx,
4075 mono_string_to_utf8 (tb->name), tb->table_idx,
4076 ntable->next_idx, ntable->rows);*/
4077 values += MONO_NESTED_CLASS_SIZE;
4078 ntable->next_idx++;
4082 return TRUE;
4084 #endif
4086 static void
4087 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
4089 int i;
4091 mono_ptr_array_append (*types, type);
4093 if (!type->subtypes)
4094 return;
4096 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
4097 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
4098 collect_types (types, subtype);
4102 static gint
4103 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
4105 if ((*type1)->table_idx < (*type2)->table_idx)
4106 return -1;
4107 else
4108 if ((*type1)->table_idx > (*type2)->table_idx)
4109 return 1;
4110 else
4111 return 0;
4114 static gboolean
4115 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo, MonoError *error) {
4116 int i;
4118 mono_error_init (error);
4119 if (!pinfo)
4120 return TRUE;
4121 for (i = 0; i < mono_array_length (pinfo); ++i) {
4122 MonoReflectionParamBuilder *pb;
4123 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
4124 if (!pb)
4125 continue;
4126 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs, error))
4127 return FALSE;
4130 return TRUE;
4133 static gboolean
4134 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error) {
4135 int i;
4137 mono_error_init (error);
4139 if (!mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs, error))
4140 return FALSE;
4141 if (tb->fields) {
4142 for (i = 0; i < tb->num_fields; ++i) {
4143 MonoReflectionFieldBuilder* fb;
4144 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
4145 if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4146 return FALSE;
4149 if (tb->events) {
4150 for (i = 0; i < mono_array_length (tb->events); ++i) {
4151 MonoReflectionEventBuilder* eb;
4152 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
4153 if (!mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs, error))
4154 return FALSE;
4157 if (tb->properties) {
4158 for (i = 0; i < mono_array_length (tb->properties); ++i) {
4159 MonoReflectionPropertyBuilder* pb;
4160 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
4161 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs, error))
4162 return FALSE;
4165 if (tb->ctors) {
4166 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
4167 MonoReflectionCtorBuilder* cb;
4168 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
4169 if (!mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs, error) ||
4170 !params_add_cattrs (assembly, cb->pinfo, error))
4171 return FALSE;
4175 if (tb->methods) {
4176 for (i = 0; i < tb->num_methods; ++i) {
4177 MonoReflectionMethodBuilder* mb;
4178 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
4179 if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4180 !params_add_cattrs (assembly, mb->pinfo, error))
4181 return FALSE;
4185 if (tb->subtypes) {
4186 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4187 if (!type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), error))
4188 return FALSE;
4192 return TRUE;
4195 static gboolean
4196 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb, MonoError *error)
4198 int i;
4200 mono_error_init (error);
4202 if (!mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs, error))
4203 return FALSE;
4205 if (moduleb->global_methods) {
4206 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4207 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4208 if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4209 !params_add_cattrs (assembly, mb->pinfo, error))
4210 return FALSE;
4214 if (moduleb->global_fields) {
4215 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
4216 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
4217 if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4218 return FALSE;
4222 if (moduleb->types) {
4223 for (i = 0; i < moduleb->num_types; ++i) {
4224 if (!type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i), error))
4225 return FALSE;
4229 return TRUE;
4232 static void
4233 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
4235 MonoDynamicTable *table;
4236 guint32 *values;
4237 char blob_size [6];
4238 guchar hash [20];
4239 char *b = blob_size;
4240 char *dir, *path;
4242 table = &assembly->tables [MONO_TABLE_FILE];
4243 table->rows++;
4244 alloc_table (table, table->rows);
4245 values = table->values + table->next_idx * MONO_FILE_SIZE;
4246 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
4247 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
4248 if (image_is_dynamic (module->image)) {
4249 /* This depends on the fact that the main module is emitted last */
4250 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
4251 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
4252 } else {
4253 dir = NULL;
4254 path = g_strdup (module->image->name);
4256 mono_sha1_get_digest_from_file (path, hash);
4257 g_free (dir);
4258 g_free (path);
4259 mono_metadata_encode_value (20, b, &b);
4260 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4261 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4262 table->next_idx ++;
4265 static void
4266 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
4268 MonoDynamicTable *table;
4269 int i;
4271 table = &assembly->tables [MONO_TABLE_MODULE];
4272 mb->table_idx = table->next_idx ++;
4273 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
4274 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
4275 i /= 16;
4276 ++i;
4277 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
4278 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
4279 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
4280 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
4283 static guint32
4284 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
4285 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4287 MonoDynamicTable *table;
4288 guint32 *values;
4289 guint32 visib, res;
4291 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
4292 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
4293 return 0;
4295 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4296 table->rows++;
4297 alloc_table (table, table->rows);
4298 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
4300 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
4301 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
4302 if (klass->nested_in)
4303 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4304 else
4305 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
4306 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4307 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4309 res = table->next_idx;
4311 table->next_idx ++;
4313 /* Emit nested types */
4314 if (klass->ext && klass->ext->nested_classes) {
4315 GList *tmp;
4317 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
4318 mono_image_fill_export_table_from_class (domain, (MonoClass *)tmp->data, module_index, table->next_idx - 1, assembly);
4321 return res;
4324 static void
4325 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
4326 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly,
4327 MonoError *error)
4329 MonoClass *klass;
4330 guint32 idx, i;
4332 mono_error_init (error);
4334 MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
4335 return_if_nok (error);
4337 klass = mono_class_from_mono_type (t);
4339 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
4341 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
4342 parent_index, assembly);
4345 * Emit nested types
4346 * We need to do this ourselves since klass->nested_classes is not set up.
4348 if (tb->subtypes) {
4349 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4350 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly, error);
4351 return_if_nok (error);
4356 static void
4357 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
4358 guint32 module_index, MonoDynamicImage *assembly)
4360 MonoImage *image = module->image;
4361 MonoTableInfo *t;
4362 guint32 i;
4364 t = &image->tables [MONO_TABLE_TYPEDEF];
4366 for (i = 0; i < t->rows; ++i) {
4367 MonoError error;
4368 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
4369 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4371 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
4372 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
4376 static void
4377 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
4379 MonoDynamicTable *table;
4380 guint32 *values;
4381 guint32 scope, scope_idx, impl, current_idx;
4382 gboolean forwarder = TRUE;
4383 gpointer iter = NULL;
4384 MonoClass *nested;
4386 if (klass->nested_in) {
4387 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4388 forwarder = FALSE;
4389 } else {
4390 scope = resolution_scope_from_image (assembly, klass->image);
4391 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
4392 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
4393 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
4396 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4398 table->rows++;
4399 alloc_table (table, table->rows);
4400 current_idx = table->next_idx;
4401 values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
4403 values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
4404 values [MONO_EXP_TYPE_TYPEDEF] = 0;
4405 values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
4406 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4407 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4409 table->next_idx++;
4411 while ((nested = mono_class_get_nested_types (klass, &iter)))
4412 add_exported_type (assemblyb, assembly, nested, current_idx);
4415 static void
4416 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
4418 MonoError error;
4419 MonoClass *klass;
4420 int i;
4422 if (!assemblyb->type_forwarders)
4423 return;
4425 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
4426 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
4427 MonoType *type;
4428 if (!t)
4429 continue;
4431 type = mono_reflection_type_get_handle (t, &error);
4432 mono_error_assert_ok (&error);
4433 g_assert (type);
4435 klass = mono_class_from_mono_type (type);
4437 add_exported_type (assemblyb, assembly, klass, 0);
4441 #define align_pointer(base,p)\
4442 do {\
4443 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
4444 if (__diff & 3)\
4445 (p) += 4 - (__diff & 3);\
4446 } while (0)
4448 static int
4449 compare_constants (const void *a, const void *b)
4451 const guint32 *a_values = (const guint32 *)a;
4452 const guint32 *b_values = (const guint32 *)b;
4453 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
4456 static int
4457 compare_semantics (const void *a, const void *b)
4459 const guint32 *a_values = (const guint32 *)a;
4460 const guint32 *b_values = (const guint32 *)b;
4461 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
4462 if (assoc)
4463 return assoc;
4464 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
4467 static int
4468 compare_custom_attrs (const void *a, const void *b)
4470 const guint32 *a_values = (const guint32 *)a;
4471 const guint32 *b_values = (const guint32 *)b;
4473 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
4476 static int
4477 compare_field_marshal (const void *a, const void *b)
4479 const guint32 *a_values = (const guint32 *)a;
4480 const guint32 *b_values = (const guint32 *)b;
4482 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
4485 static int
4486 compare_nested (const void *a, const void *b)
4488 const guint32 *a_values = (const guint32 *)a;
4489 const guint32 *b_values = (const guint32 *)b;
4491 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
4494 static int
4495 compare_genericparam (const void *a, const void *b)
4497 MonoError error;
4498 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
4499 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
4501 if ((*b_entry)->owner == (*a_entry)->owner) {
4502 MonoType *a_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam, &error);
4503 mono_error_assert_ok (&error);
4504 MonoType *b_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam, &error);
4505 mono_error_assert_ok (&error);
4506 return
4507 mono_type_get_generic_param_num (a_type) -
4508 mono_type_get_generic_param_num (b_type);
4509 } else
4510 return (*a_entry)->owner - (*b_entry)->owner;
4513 static int
4514 compare_declsecurity_attrs (const void *a, const void *b)
4516 const guint32 *a_values = (const guint32 *)a;
4517 const guint32 *b_values = (const guint32 *)b;
4519 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
4522 static int
4523 compare_interface_impl (const void *a, const void *b)
4525 const guint32 *a_values = (const guint32 *)a;
4526 const guint32 *b_values = (const guint32 *)b;
4528 int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
4529 if (klass)
4530 return klass;
4532 return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
4535 static void
4536 pad_heap (MonoDynamicStream *sh)
4538 if (sh->index & 3) {
4539 int sz = 4 - (sh->index & 3);
4540 memset (sh->data + sh->index, 0, sz);
4541 sh->index += sz;
4545 struct StreamDesc {
4546 const char *name;
4547 MonoDynamicStream *stream;
4551 * build_compressed_metadata() fills in the blob of data that represents the
4552 * raw metadata as it will be saved in the PE file. The five streams are output
4553 * and the metadata tables are comnpressed from the guint32 array representation,
4554 * to the compressed on-disk format.
4556 static gboolean
4557 build_compressed_metadata (MonoDynamicImage *assembly, MonoError *error)
4559 MonoDynamicTable *table;
4560 int i;
4561 guint64 valid_mask = 0;
4562 guint64 sorted_mask;
4563 guint32 heapt_size = 0;
4564 guint32 meta_size = 256; /* allow for header and other stuff */
4565 guint32 table_offset;
4566 guint32 ntables = 0;
4567 guint64 *int64val;
4568 guint32 *int32val;
4569 guint16 *int16val;
4570 MonoImage *meta;
4571 unsigned char *p;
4572 struct StreamDesc stream_desc [5];
4574 mono_error_init (error);
4576 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4577 for (i = 0; i < assembly->gen_params->len; i++) {
4578 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (assembly->gen_params, i);
4579 if (!write_generic_param_entry (assembly, entry, error))
4580 return FALSE;
4583 stream_desc [0].name = "#~";
4584 stream_desc [0].stream = &assembly->tstream;
4585 stream_desc [1].name = "#Strings";
4586 stream_desc [1].stream = &assembly->sheap;
4587 stream_desc [2].name = "#US";
4588 stream_desc [2].stream = &assembly->us;
4589 stream_desc [3].name = "#Blob";
4590 stream_desc [3].stream = &assembly->blob;
4591 stream_desc [4].name = "#GUID";
4592 stream_desc [4].stream = &assembly->guid;
4594 /* tables that are sorted */
4595 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4596 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4597 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4598 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4599 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4600 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4601 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4603 /* Compute table sizes */
4604 /* the MonoImage has already been created in mono_image_basic_init() */
4605 meta = &assembly->image;
4607 /* sizes should be multiple of 4 */
4608 pad_heap (&assembly->blob);
4609 pad_heap (&assembly->guid);
4610 pad_heap (&assembly->sheap);
4611 pad_heap (&assembly->us);
4613 /* Setup the info used by compute_sizes () */
4614 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4615 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4616 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4618 meta_size += assembly->blob.index;
4619 meta_size += assembly->guid.index;
4620 meta_size += assembly->sheap.index;
4621 meta_size += assembly->us.index;
4623 for (i=0; i < MONO_TABLE_NUM; ++i)
4624 meta->tables [i].rows = assembly->tables [i].rows;
4626 for (i = 0; i < MONO_TABLE_NUM; i++){
4627 if (meta->tables [i].rows == 0)
4628 continue;
4629 valid_mask |= (guint64)1 << i;
4630 ntables ++;
4631 meta->tables [i].row_size = mono_metadata_compute_size (
4632 meta, i, &meta->tables [i].size_bitfield);
4633 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4635 heapt_size += 24; /* #~ header size */
4636 heapt_size += ntables * 4;
4637 /* make multiple of 4 */
4638 heapt_size += 3;
4639 heapt_size &= ~3;
4640 meta_size += heapt_size;
4641 meta->raw_metadata = (char *)g_malloc0 (meta_size);
4642 p = (unsigned char*)meta->raw_metadata;
4643 /* the metadata signature */
4644 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4645 /* version numbers and 4 bytes reserved */
4646 int16val = (guint16*)p;
4647 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4648 *int16val = GUINT16_TO_LE (meta->md_version_minor);
4649 p += 8;
4650 /* version string */
4651 int32val = (guint32*)p;
4652 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4653 p += 4;
4654 memcpy (p, meta->version, strlen (meta->version));
4655 p += GUINT32_FROM_LE (*int32val);
4656 align_pointer (meta->raw_metadata, p);
4657 int16val = (guint16*)p;
4658 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4659 *int16val = GUINT16_TO_LE (5); /* number of streams */
4660 p += 4;
4663 * write the stream info.
4665 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4666 table_offset += 3; table_offset &= ~3;
4668 assembly->tstream.index = heapt_size;
4669 for (i = 0; i < 5; ++i) {
4670 int32val = (guint32*)p;
4671 stream_desc [i].stream->offset = table_offset;
4672 *int32val++ = GUINT32_TO_LE (table_offset);
4673 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4674 table_offset += GUINT32_FROM_LE (*int32val);
4675 table_offset += 3; table_offset &= ~3;
4676 p += 8;
4677 strcpy ((char*)p, stream_desc [i].name);
4678 p += strlen (stream_desc [i].name) + 1;
4679 align_pointer (meta->raw_metadata, p);
4682 * now copy the data, the table stream header and contents goes first.
4684 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4685 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4686 int32val = (guint32*)p;
4687 *int32val = GUINT32_TO_LE (0); /* reserved */
4688 p += 4;
4690 *p++ = 2; /* version */
4691 *p++ = 0;
4693 if (meta->idx_string_wide)
4694 *p |= 0x01;
4695 if (meta->idx_guid_wide)
4696 *p |= 0x02;
4697 if (meta->idx_blob_wide)
4698 *p |= 0x04;
4699 ++p;
4700 *p++ = 1; /* reserved */
4701 int64val = (guint64*)p;
4702 *int64val++ = GUINT64_TO_LE (valid_mask);
4703 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
4704 p += 16;
4705 int32val = (guint32*)p;
4706 for (i = 0; i < MONO_TABLE_NUM; i++){
4707 if (meta->tables [i].rows == 0)
4708 continue;
4709 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4711 p = (unsigned char*)int32val;
4713 /* sort the tables that still need sorting */
4714 table = &assembly->tables [MONO_TABLE_CONSTANT];
4715 if (table->rows)
4716 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4717 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4718 if (table->rows)
4719 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4720 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4721 if (table->rows)
4722 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4723 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4724 if (table->rows)
4725 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4726 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4727 if (table->rows)
4728 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4729 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4730 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4731 if (table->rows)
4732 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4733 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4734 if (table->rows)
4735 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4737 /* compress the tables */
4738 for (i = 0; i < MONO_TABLE_NUM; i++){
4739 int row, col;
4740 guint32 *values;
4741 guint32 bitfield = meta->tables [i].size_bitfield;
4742 if (!meta->tables [i].rows)
4743 continue;
4744 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4745 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4746 meta->tables [i].base = (char*)p;
4747 for (row = 1; row <= meta->tables [i].rows; ++row) {
4748 values = assembly->tables [i].values + row * assembly->tables [i].columns;
4749 for (col = 0; col < assembly->tables [i].columns; ++col) {
4750 switch (mono_metadata_table_size (bitfield, col)) {
4751 case 1:
4752 *p++ = values [col];
4753 break;
4754 case 2:
4755 *p++ = values [col] & 0xff;
4756 *p++ = (values [col] >> 8) & 0xff;
4757 break;
4758 case 4:
4759 *p++ = values [col] & 0xff;
4760 *p++ = (values [col] >> 8) & 0xff;
4761 *p++ = (values [col] >> 16) & 0xff;
4762 *p++ = (values [col] >> 24) & 0xff;
4763 break;
4764 default:
4765 g_assert_not_reached ();
4769 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4772 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4773 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4774 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4775 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4776 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4778 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4780 return TRUE;
4784 * Some tables in metadata need to be sorted according to some criteria, but
4785 * when methods and fields are first created with reflection, they may be assigned a token
4786 * that doesn't correspond to the final token they will get assigned after the sorting.
4787 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4788 * with the reflection objects that represent them. Once all the tables are set up, the
4789 * reflection objects will contains the correct table index. fixup_method() will fixup the
4790 * tokens for the method with ILGenerator @ilgen.
4792 static void
4793 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4795 guint32 code_idx = GPOINTER_TO_UINT (value);
4796 MonoReflectionILTokenInfo *iltoken;
4797 MonoReflectionFieldBuilder *field;
4798 MonoReflectionCtorBuilder *ctor;
4799 MonoReflectionMethodBuilder *method;
4800 MonoReflectionTypeBuilder *tb;
4801 MonoReflectionArrayMethod *am;
4802 guint32 i, idx = 0;
4803 unsigned char *target;
4805 for (i = 0; i < ilgen->num_token_fixups; ++i) {
4806 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4807 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4808 switch (target [3]) {
4809 case MONO_TABLE_FIELD:
4810 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4811 field = (MonoReflectionFieldBuilder *)iltoken->member;
4812 idx = field->table_idx;
4813 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4814 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4815 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4816 } else {
4817 g_assert_not_reached ();
4819 break;
4820 case MONO_TABLE_METHOD:
4821 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4822 method = (MonoReflectionMethodBuilder *)iltoken->member;
4823 idx = method->table_idx;
4824 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4825 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4826 idx = ctor->table_idx;
4827 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4828 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4829 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4830 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4831 } else {
4832 g_assert_not_reached ();
4834 break;
4835 case MONO_TABLE_TYPEDEF:
4836 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4837 g_assert_not_reached ();
4838 tb = (MonoReflectionTypeBuilder *)iltoken->member;
4839 idx = tb->table_idx;
4840 break;
4841 case MONO_TABLE_MEMBERREF:
4842 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4843 am = (MonoReflectionArrayMethod*)iltoken->member;
4844 idx = am->table_idx;
4845 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4846 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4847 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4848 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4849 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4850 g_assert (m->klass->generic_class || m->klass->generic_container);
4851 continue;
4852 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4853 continue;
4854 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4855 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4856 g_assert (is_field_on_inst (f));
4857 continue;
4858 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4859 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4860 continue;
4861 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4862 continue;
4863 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4864 continue;
4865 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4866 continue;
4867 } else {
4868 g_assert_not_reached ();
4870 break;
4871 case MONO_TABLE_METHODSPEC:
4872 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4873 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4874 g_assert (mono_method_signature (m)->generic_param_count);
4875 continue;
4876 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4877 continue;
4878 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4879 continue;
4880 } else {
4881 g_assert_not_reached ();
4883 break;
4884 default:
4885 g_error ("got unexpected table 0x%02x in fixup", target [3]);
4887 target [0] = idx & 0xff;
4888 target [1] = (idx >> 8) & 0xff;
4889 target [2] = (idx >> 16) & 0xff;
4894 * fixup_cattrs:
4896 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4897 * value is not known when the table is emitted.
4899 static void
4900 fixup_cattrs (MonoDynamicImage *assembly)
4902 MonoDynamicTable *table;
4903 guint32 *values;
4904 guint32 type, i, idx, token;
4905 MonoObject *ctor;
4907 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4909 for (i = 0; i < table->rows; ++i) {
4910 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4912 type = values [MONO_CUSTOM_ATTR_TYPE];
4913 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4914 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4915 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4916 ctor = (MonoObject *)mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4917 g_assert (ctor);
4919 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4920 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4921 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4922 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4923 } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4924 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4925 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4926 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4932 static void
4933 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4935 MonoDynamicTable *table;
4936 guint32 *values;
4938 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4939 table->rows++;
4940 alloc_table (table, table->rows);
4941 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4942 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4943 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4944 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4945 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4946 table->next_idx++;
4949 static void
4950 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4952 MonoDynamicTable *table;
4953 guint32 *values;
4954 char blob_size [6];
4955 guchar hash [20];
4956 char *b = blob_size;
4957 char *name, *sname;
4958 guint32 idx, offset;
4960 if (rsrc->filename) {
4961 name = mono_string_to_utf8 (rsrc->filename);
4962 sname = g_path_get_basename (name);
4964 table = &assembly->tables [MONO_TABLE_FILE];
4965 table->rows++;
4966 alloc_table (table, table->rows);
4967 values = table->values + table->next_idx * MONO_FILE_SIZE;
4968 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4969 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4970 g_free (sname);
4972 mono_sha1_get_digest_from_file (name, hash);
4973 mono_metadata_encode_value (20, b, &b);
4974 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4975 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4976 g_free (name);
4977 idx = table->next_idx++;
4978 rsrc->offset = 0;
4979 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4980 } else {
4981 char sizebuf [4];
4982 char *data;
4983 guint len;
4984 if (rsrc->data) {
4985 data = mono_array_addr (rsrc->data, char, 0);
4986 len = mono_array_length (rsrc->data);
4987 } else {
4988 data = NULL;
4989 len = 0;
4991 offset = len;
4992 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4993 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4994 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4995 mono_image_add_stream_data (&assembly->resources, data, len);
4997 if (!mb->is_main)
4999 * The entry should be emitted into the MANIFESTRESOURCE table of
5000 * the main module, but that needs to reference the FILE table
5001 * which isn't emitted yet.
5003 return;
5004 else
5005 idx = 0;
5008 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
5011 static void
5012 set_version_from_string (MonoString *version, guint32 *values)
5014 gchar *ver, *p, *str;
5015 guint32 i;
5017 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
5018 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
5019 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
5020 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
5021 if (!version)
5022 return;
5023 ver = str = mono_string_to_utf8 (version);
5024 for (i = 0; i < 4; ++i) {
5025 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
5026 switch (*p) {
5027 case '.':
5028 p++;
5029 break;
5030 case '*':
5031 /* handle Revision and Build */
5032 p++;
5033 break;
5035 ver = p;
5037 g_free (str);
5040 static guint32
5041 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
5042 gsize len;
5043 guint32 token = 0;
5044 char blob_size [6];
5045 char *b = blob_size;
5047 if (!pkey)
5048 return token;
5050 len = mono_array_length (pkey);
5051 mono_metadata_encode_value (len, b, &b);
5052 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
5053 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
5055 assembly->public_key = (guint8 *)g_malloc (len);
5056 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
5057 assembly->public_key_len = len;
5059 /* Special case: check for ECMA key (16 bytes) */
5060 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
5061 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
5062 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
5063 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
5064 /* minimum key size (in 2.0) is 384 bits */
5065 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
5066 } else {
5067 /* FIXME - verifier */
5068 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
5069 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
5071 assembly->strong_name = (char *)g_malloc0 (assembly->strong_name_size);
5073 return token;
5076 static void
5077 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5079 MonoDynamicTable *table;
5080 MonoDynamicImage *assembly;
5081 MonoReflectionAssemblyBuilder *assemblyb;
5082 MonoDomain *domain;
5083 guint32 *values;
5084 int i;
5085 guint32 module_index;
5087 mono_error_init (error);
5089 assemblyb = moduleb->assemblyb;
5090 assembly = moduleb->dynamic_image;
5091 domain = mono_object_domain (assemblyb);
5093 /* Emit ASSEMBLY table */
5094 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
5095 alloc_table (table, 1);
5096 values = table->values + MONO_ASSEMBLY_SIZE;
5097 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
5098 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
5099 if (assemblyb->culture) {
5100 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
5101 } else {
5102 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
5104 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
5105 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
5106 set_version_from_string (assemblyb->version, values);
5108 /* Emit FILE + EXPORTED_TYPE table */
5109 module_index = 0;
5110 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
5111 int j;
5112 MonoReflectionModuleBuilder *file_module =
5113 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
5114 if (file_module != moduleb) {
5115 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
5116 module_index ++;
5117 if (file_module->types) {
5118 for (j = 0; j < file_module->num_types; ++j) {
5119 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
5120 mono_image_fill_export_table (domain, tb, module_index, 0, assembly, error);
5121 return_if_nok (error);
5126 if (assemblyb->loaded_modules) {
5127 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
5128 MonoReflectionModule *file_module =
5129 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
5130 mono_image_fill_file_table (domain, file_module, assembly);
5131 module_index ++;
5132 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
5135 if (assemblyb->type_forwarders)
5136 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
5138 /* Emit MANIFESTRESOURCE table */
5139 module_index = 0;
5140 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
5141 int j;
5142 MonoReflectionModuleBuilder *file_module =
5143 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
5144 /* The table for the main module is emitted later */
5145 if (file_module != moduleb) {
5146 module_index ++;
5147 if (file_module->resources) {
5148 int len = mono_array_length (file_module->resources);
5149 for (j = 0; j < len; ++j) {
5150 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
5151 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
5158 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5161 * mono_image_build_metadata() will fill the info in all the needed metadata tables
5162 * for the modulebuilder @moduleb.
5163 * At the end of the process, method and field tokens are fixed up and the
5164 * on-disk compressed metadata representation is created.
5165 * Return TRUE on success, or FALSE on failure and sets @error
5167 gboolean
5168 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5170 MonoDynamicTable *table;
5171 MonoDynamicImage *assembly;
5172 MonoReflectionAssemblyBuilder *assemblyb;
5173 MonoDomain *domain;
5174 MonoPtrArray types;
5175 guint32 *values;
5176 int i, j;
5178 mono_error_init (error);
5180 assemblyb = moduleb->assemblyb;
5181 assembly = moduleb->dynamic_image;
5182 domain = mono_object_domain (assemblyb);
5184 if (assembly->text_rva)
5185 return TRUE;
5187 assembly->text_rva = START_TEXT_RVA;
5189 if (moduleb->is_main) {
5190 mono_image_emit_manifest (moduleb, error);
5191 return_val_if_nok (error, FALSE);
5194 table = &assembly->tables [MONO_TABLE_TYPEDEF];
5195 table->rows = 1; /* .<Module> */
5196 table->next_idx++;
5197 alloc_table (table, table->rows);
5199 * Set the first entry.
5201 values = table->values + table->columns;
5202 values [MONO_TYPEDEF_FLAGS] = 0;
5203 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
5204 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
5205 values [MONO_TYPEDEF_EXTENDS] = 0;
5206 values [MONO_TYPEDEF_FIELD_LIST] = 1;
5207 values [MONO_TYPEDEF_METHOD_LIST] = 1;
5210 * handle global methods
5211 * FIXME: test what to do when global methods are defined in multiple modules.
5213 if (moduleb->global_methods) {
5214 table = &assembly->tables [MONO_TABLE_METHOD];
5215 table->rows += mono_array_length (moduleb->global_methods);
5216 alloc_table (table, table->rows);
5217 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5218 if (!mono_image_get_method_info (
5219 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly, error))
5220 goto leave;
5223 if (moduleb->global_fields) {
5224 table = &assembly->tables [MONO_TABLE_FIELD];
5225 table->rows += mono_array_length (moduleb->global_fields);
5226 alloc_table (table, table->rows);
5227 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
5228 mono_image_get_field_info (
5229 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly,
5230 error);
5231 if (!is_ok (error))
5232 goto leave;
5236 table = &assembly->tables [MONO_TABLE_MODULE];
5237 alloc_table (table, 1);
5238 mono_image_fill_module_table (domain, moduleb, assembly);
5240 /* Collect all types into a list sorted by their table_idx */
5241 mono_ptr_array_init (types, moduleb->num_types, MONO_ROOT_SOURCE_REFLECTION, "dynamic module types list");
5243 if (moduleb->types)
5244 for (i = 0; i < moduleb->num_types; ++i) {
5245 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
5246 collect_types (&types, type);
5249 mono_ptr_array_sort (types, (int (*)(const void *, const void *))compare_types_by_table_idx);
5250 table = &assembly->tables [MONO_TABLE_TYPEDEF];
5251 table->rows += mono_ptr_array_size (types);
5252 alloc_table (table, table->rows);
5255 * Emit type names + namespaces at one place inside the string heap,
5256 * so load_class_names () needs to touch fewer pages.
5258 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5259 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5260 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
5262 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5263 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5264 string_heap_insert_mstring (&assembly->sheap, tb->name);
5267 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5268 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5269 if (!mono_image_get_type_info (domain, type, assembly, error))
5270 goto leave_types;
5274 * table->rows is already set above and in mono_image_fill_module_table.
5276 /* add all the custom attributes at the end, once all the indexes are stable */
5277 if (!mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs, error))
5278 goto leave_types;
5280 /* CAS assembly permissions */
5281 if (assemblyb->permissions_minimum)
5282 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
5283 if (assemblyb->permissions_optional)
5284 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
5285 if (assemblyb->permissions_refused)
5286 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
5288 if (!module_add_cattrs (assembly, moduleb, error))
5289 goto leave_types;
5291 /* fixup tokens */
5292 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
5294 /* Create the MethodImpl table. We do this after emitting all methods so we already know
5295 * the final tokens and don't need another fixup pass. */
5297 if (moduleb->global_methods) {
5298 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5299 MonoReflectionMethodBuilder *mb = mono_array_get (
5300 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
5301 if (!mono_image_add_methodimpl (assembly, mb, error))
5302 goto leave_types;
5306 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5307 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5308 if (type->methods) {
5309 for (j = 0; j < type->num_methods; ++j) {
5310 MonoReflectionMethodBuilder *mb = mono_array_get (
5311 type->methods, MonoReflectionMethodBuilder*, j);
5313 if (!mono_image_add_methodimpl (assembly, mb, error))
5314 goto leave_types;
5319 fixup_cattrs (assembly);
5321 leave_types:
5322 mono_ptr_array_destroy (types);
5323 leave:
5325 return mono_error_ok (error);
5328 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5330 gboolean
5331 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5333 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
5336 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5339 typedef struct {
5340 guint32 import_lookup_table;
5341 guint32 timestamp;
5342 guint32 forwarder;
5343 guint32 name_rva;
5344 guint32 import_address_table_rva;
5345 } MonoIDT;
5347 typedef struct {
5348 guint32 name_rva;
5349 guint32 flags;
5350 } MonoILT;
5352 #ifndef DISABLE_REFLECTION_EMIT
5355 * mono_image_insert_string:
5356 * @module: module builder object
5357 * @str: a string
5359 * Insert @str into the user string stream of @module.
5361 guint32
5362 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
5364 MonoDynamicImage *assembly;
5365 guint32 idx;
5366 char buf [16];
5367 char *b = buf;
5369 if (!module->dynamic_image)
5370 mono_image_module_basic_init (module);
5372 assembly = module->dynamic_image;
5374 if (assembly->save) {
5375 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
5376 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
5377 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
5379 char *swapped = g_malloc (2 * mono_string_length (str));
5380 const char *p = (const char*)mono_string_chars (str);
5382 swap_with_size (swapped, p, 2, mono_string_length (str));
5383 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
5384 g_free (swapped);
5386 #else
5387 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
5388 #endif
5389 mono_image_add_stream_data (&assembly->us, "", 1);
5390 } else {
5391 idx = assembly->us.index ++;
5394 register_dyn_token (assembly, MONO_TOKEN_STRING | idx, (MonoObject*)str);
5396 return MONO_TOKEN_STRING | idx;
5399 guint32
5400 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
5402 MonoClass *klass;
5403 guint32 token = 0;
5404 MonoMethodSignature *sig;
5406 mono_error_init (error);
5408 klass = obj->vtable->klass;
5409 if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
5410 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
5411 MonoMethodSignature *old;
5412 guint32 sig_token, parent;
5413 int nargs, i;
5415 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
5417 nargs = mono_array_length (opt_param_types);
5418 old = mono_method_signature (method);
5419 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
5421 sig->hasthis = old->hasthis;
5422 sig->explicit_this = old->explicit_this;
5423 sig->call_convention = old->call_convention;
5424 sig->generic_param_count = old->generic_param_count;
5425 sig->param_count = old->param_count + nargs;
5426 sig->sentinelpos = old->param_count;
5427 sig->ret = old->ret;
5429 for (i = 0; i < old->param_count; i++)
5430 sig->params [i] = old->params [i];
5432 for (i = 0; i < nargs; i++) {
5433 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5434 sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt, error);
5435 if (!is_ok (error)) goto fail;
5438 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
5439 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
5440 parent >>= MONO_TYPEDEFORREF_BITS;
5442 parent <<= MONO_MEMBERREF_PARENT_BITS;
5443 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
5445 sig_token = method_encode_signature (assembly, sig);
5446 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
5447 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
5448 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5449 ReflectionMethodBuilder rmb;
5450 guint32 parent, sig_token;
5451 int nopt_args, nparams, ngparams, i;
5453 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
5454 goto fail;
5456 rmb.opt_types = opt_param_types;
5457 nopt_args = mono_array_length (opt_param_types);
5459 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
5460 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
5461 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
5463 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
5464 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
5465 sig->call_convention = rmb.call_conv;
5466 sig->generic_param_count = ngparams;
5467 sig->param_count = nparams + nopt_args;
5468 sig->sentinelpos = nparams;
5469 sig->ret = mono_reflection_type_get_handle (rmb.rtype, error);
5470 if (!is_ok (error)) goto fail;
5472 for (i = 0; i < nparams; i++) {
5473 MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
5474 sig->params [i] = mono_reflection_type_get_handle (rt, error);
5475 if (!is_ok (error)) goto fail;
5478 for (i = 0; i < nopt_args; i++) {
5479 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5480 sig->params [nparams + i] = mono_reflection_type_get_handle (rt, error);
5481 if (!is_ok (error)) goto fail;
5484 sig_token = method_builder_encode_signature (assembly, &rmb, error);
5485 if (!is_ok (error))
5486 goto fail;
5488 parent = mono_image_create_token (assembly, obj, TRUE, TRUE, error);
5489 if (!mono_error_ok (error))
5490 goto fail;
5491 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
5493 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
5494 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
5496 char *name = mono_string_to_utf8 (rmb.name);
5497 token = mono_image_get_varargs_method_token (
5498 assembly, parent, name, sig_token);
5499 g_free (name);
5500 } else {
5501 g_error ("requested method token for %s\n", klass->name);
5504 g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
5505 register_dyn_token (assembly, token, obj);
5506 return token;
5507 fail:
5508 g_assert (!mono_error_ok (error));
5509 return 0;
5513 * mono_image_create_token:
5514 * @assembly: a dynamic assembly
5515 * @obj:
5516 * @register_token: Whenever to register the token in the assembly->tokens hash.
5518 * Get a token to insert in the IL code stream for the given MemberInfo.
5519 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
5520 * the table_idx-es were recomputed, so registering the token would overwrite an existing
5521 * entry.
5523 guint32
5524 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
5525 gboolean create_open_instance, gboolean register_token,
5526 MonoError *error)
5528 MonoClass *klass;
5529 guint32 token = 0;
5531 mono_error_init (error);
5533 klass = obj->vtable->klass;
5535 /* Check for user defined reflection objects */
5536 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
5537 if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0)) {
5538 mono_error_set_not_supported (error, "User defined subclasses of System.Type are not yet supported");
5539 return 0;
5542 if (strcmp (klass->name, "MethodBuilder") == 0) {
5543 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5544 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5546 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
5547 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5548 else {
5549 token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance, error);
5550 if (!mono_error_ok (error))
5551 return 0;
5553 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5554 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
5555 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
5556 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5558 if (tb->module->dynamic_image == assembly && !tb->generic_params)
5559 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5560 else {
5561 token = mono_image_get_ctorbuilder_token (assembly, mb, error);
5562 if (!mono_error_ok (error))
5563 return 0;
5565 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5566 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
5567 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
5568 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
5569 if (tb->generic_params) {
5570 token = mono_image_get_generic_field_token (assembly, fb, error);
5571 return_val_if_nok (error, 0);
5572 } else {
5573 if (tb->module->dynamic_image == assembly) {
5574 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
5575 } else {
5576 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
5579 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
5580 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
5581 if (create_open_instance && tb->generic_params) {
5582 MonoType *type;
5583 init_type_builder_generics (obj);
5584 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5585 return_val_if_nok (error, 0);
5586 token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
5587 token = mono_metadata_token_from_dor (token);
5588 } else if (tb->module->dynamic_image == assembly) {
5589 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
5590 } else {
5591 MonoType *type;
5592 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5593 return_val_if_nok (error, 0);
5594 token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
5596 } else if (strcmp (klass->name, "MonoType") == 0) {
5597 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5598 return_val_if_nok (error, 0);
5599 MonoClass *mc = mono_class_from_mono_type (type);
5600 token = mono_metadata_token_from_dor (
5601 mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
5602 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
5603 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5604 return_val_if_nok (error, 0);
5605 token = mono_metadata_token_from_dor (
5606 mono_image_typedef_or_ref (assembly, type));
5607 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
5608 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5609 return_val_if_nok (error, 0);
5610 token = mono_metadata_token_from_dor (
5611 mono_image_typedef_or_ref (assembly, type));
5612 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
5613 strcmp (klass->name, "MonoMethod") == 0 ||
5614 strcmp (klass->name, "MonoGenericMethod") == 0 ||
5615 strcmp (klass->name, "MonoGenericCMethod") == 0) {
5616 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
5617 if (m->method->is_inflated) {
5618 if (create_open_instance)
5619 token = mono_image_get_methodspec_token (assembly, m->method);
5620 else
5621 token = mono_image_get_inflated_method_token (assembly, m->method);
5622 } else if ((m->method->klass->image == &assembly->image) &&
5623 !m->method->klass->generic_class) {
5624 static guint32 method_table_idx = 0xffffff;
5625 if (m->method->klass->wastypebuilder) {
5626 /* we use the same token as the one that was assigned
5627 * to the Methodbuilder.
5628 * FIXME: do the equivalent for Fields.
5630 token = m->method->token;
5631 } else {
5633 * Each token should have a unique index, but the indexes are
5634 * assigned by managed code, so we don't know about them. An
5635 * easy solution is to count backwards...
5637 method_table_idx --;
5638 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5640 } else {
5641 token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5643 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5644 } else if (strcmp (klass->name, "MonoField") == 0) {
5645 MonoReflectionField *f = (MonoReflectionField *)obj;
5646 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5647 static guint32 field_table_idx = 0xffffff;
5648 field_table_idx --;
5649 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5650 } else {
5651 token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5653 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5654 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5655 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5656 token = mono_image_get_array_token (assembly, m, error);
5657 return_val_if_nok (error, 0);
5658 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5659 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5660 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s, error);
5661 return_val_if_nok (error, 0);
5662 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5663 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5664 return_val_if_nok (error, 0);
5665 token = mono_metadata_token_from_dor (
5666 mono_image_typedef_or_ref (assembly, type));
5667 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5668 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5669 token = mono_image_get_field_on_inst_token (assembly, f, error);
5670 return_val_if_nok (error, 0);
5671 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5672 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5673 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance, error);
5674 if (!mono_error_ok (error))
5675 return 0;
5676 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5677 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5678 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance, error);
5679 if (!mono_error_ok (error))
5680 return 0;
5681 } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5682 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5683 return_val_if_nok (error, 0);
5684 token = mono_metadata_token_from_dor (
5685 mono_image_typedef_or_ref (assembly, type));
5686 } else {
5687 g_error ("requested token for %s\n", klass->name);
5690 if (register_token)
5691 mono_image_register_token (assembly, token, obj);
5693 return token;
5697 * mono_image_register_token:
5699 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5700 * the Module.ResolveXXXToken () methods to work.
5702 void
5703 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5705 MonoObject *prev;
5707 dynamic_image_lock (assembly);
5708 prev = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5709 if (prev) {
5710 /* There could be multiple MethodInfo objects with the same token */
5711 //g_assert (prev == obj);
5712 } else {
5713 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5715 dynamic_image_unlock (assembly);
5718 static MonoDynamicImage*
5719 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5721 static const guchar entrycode [16] = {0xff, 0x25, 0};
5722 MonoDynamicImage *image;
5723 int i;
5725 const char *version;
5727 if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5728 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5729 else
5730 version = mono_get_runtime_info ()->runtime_version;
5732 #if HAVE_BOEHM_GC
5733 /* The MonoGHashTable's need GC tracking */
5734 image = (MonoDynamicImage *)GC_MALLOC (sizeof (MonoDynamicImage));
5735 #else
5736 image = g_new0 (MonoDynamicImage, 1);
5737 #endif
5739 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5741 /*g_print ("created image %p\n", image);*/
5742 /* keep in sync with image.c */
5743 image->image.name = assembly_name;
5744 image->image.assembly_name = image->image.name; /* they may be different */
5745 image->image.module_name = module_name;
5746 image->image.version = g_strdup (version);
5747 image->image.md_version_major = 1;
5748 image->image.md_version_minor = 1;
5749 image->image.dynamic = TRUE;
5751 image->image.references = g_new0 (MonoAssembly*, 1);
5752 image->image.references [0] = NULL;
5754 mono_image_init (&image->image);
5756 image->token_fixups = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module token fixups table");
5757 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5758 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5759 image->method_aux_hash = g_hash_table_new (NULL, NULL);
5760 image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5761 image->handleref = g_hash_table_new (NULL, NULL);
5762 image->handleref_managed = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module reference-to-token table");
5763 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module tokens table");
5764 image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module generic definitions table");
5765 image->methodspec = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module method specifications table");
5766 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5767 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5768 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5769 image->gen_params = g_ptr_array_new ();
5770 image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module remapped tokens table");
5772 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5773 string_heap_init (&image->sheap);
5774 mono_image_add_stream_data (&image->us, "", 1);
5775 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5776 /* import tables... */
5777 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5778 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5779 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5780 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5781 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5782 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5783 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5784 stream_data_align (&image->code);
5786 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5788 for (i=0; i < MONO_TABLE_NUM; ++i) {
5789 image->tables [i].next_idx = 1;
5790 image->tables [i].columns = table_sizes [i];
5793 image->image.assembly = (MonoAssembly*)assembly;
5794 image->run = assembly->run;
5795 image->save = assembly->save;
5796 image->pe_kind = 0x1; /* ILOnly */
5797 image->machine = 0x14c; /* I386 */
5799 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5801 dynamic_images_lock ();
5803 if (!dynamic_images)
5804 dynamic_images = g_ptr_array_new ();
5806 g_ptr_array_add (dynamic_images, image);
5808 dynamic_images_unlock ();
5810 return image;
5812 #endif
5814 static void
5815 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5817 g_free (key);
5820 static void
5821 release_hashtable (MonoGHashTable **hash)
5823 if (*hash) {
5824 mono_g_hash_table_destroy (*hash);
5825 *hash = NULL;
5829 void
5830 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5832 release_hashtable (&image->token_fixups);
5833 release_hashtable (&image->handleref_managed);
5834 release_hashtable (&image->tokens);
5835 release_hashtable (&image->remapped_tokens);
5836 release_hashtable (&image->generic_def_objects);
5837 release_hashtable (&image->methodspec);
5840 // Free dynamic image pass one: Free resources but not image itself
5841 void
5842 mono_dynamic_image_free (MonoDynamicImage *image)
5844 MonoDynamicImage *di = image;
5845 GList *list;
5846 int i;
5848 if (di->methodspec)
5849 mono_g_hash_table_destroy (di->methodspec);
5850 if (di->typespec)
5851 g_hash_table_destroy (di->typespec);
5852 if (di->typeref)
5853 g_hash_table_destroy (di->typeref);
5854 if (di->handleref)
5855 g_hash_table_destroy (di->handleref);
5856 if (di->handleref_managed)
5857 mono_g_hash_table_destroy (di->handleref_managed);
5858 if (di->tokens)
5859 mono_g_hash_table_destroy (di->tokens);
5860 if (di->remapped_tokens)
5861 mono_g_hash_table_destroy (di->remapped_tokens);
5862 if (di->generic_def_objects)
5863 mono_g_hash_table_destroy (di->generic_def_objects);
5864 if (di->blob_cache) {
5865 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5866 g_hash_table_destroy (di->blob_cache);
5868 if (di->standalonesig_cache)
5869 g_hash_table_destroy (di->standalonesig_cache);
5870 for (list = di->array_methods; list; list = list->next) {
5871 ArrayMethod *am = (ArrayMethod *)list->data;
5872 g_free (am->sig);
5873 g_free (am->name);
5874 g_free (am);
5876 g_list_free (di->array_methods);
5877 if (di->gen_params) {
5878 for (i = 0; i < di->gen_params->len; i++) {
5879 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (di->gen_params, i);
5880 mono_gc_deregister_root ((char*) &entry->gparam);
5881 g_free (entry);
5883 g_ptr_array_free (di->gen_params, TRUE);
5885 if (di->token_fixups)
5886 mono_g_hash_table_destroy (di->token_fixups);
5887 if (di->method_to_table_idx)
5888 g_hash_table_destroy (di->method_to_table_idx);
5889 if (di->field_to_table_idx)
5890 g_hash_table_destroy (di->field_to_table_idx);
5891 if (di->method_aux_hash)
5892 g_hash_table_destroy (di->method_aux_hash);
5893 if (di->vararg_aux_hash)
5894 g_hash_table_destroy (di->vararg_aux_hash);
5895 g_free (di->strong_name);
5896 g_free (di->win32_res);
5897 if (di->public_key)
5898 g_free (di->public_key);
5900 /*g_print ("string heap destroy for image %p\n", di);*/
5901 mono_dynamic_stream_reset (&di->sheap);
5902 mono_dynamic_stream_reset (&di->code);
5903 mono_dynamic_stream_reset (&di->resources);
5904 mono_dynamic_stream_reset (&di->us);
5905 mono_dynamic_stream_reset (&di->blob);
5906 mono_dynamic_stream_reset (&di->tstream);
5907 mono_dynamic_stream_reset (&di->guid);
5908 for (i = 0; i < MONO_TABLE_NUM; ++i) {
5909 g_free (di->tables [i].values);
5912 dynamic_images_lock ();
5914 if (dynamic_images)
5915 g_ptr_array_remove (dynamic_images, di);
5917 dynamic_images_unlock ();
5920 // Free dynamic image pass two: Free image itself (might never get called in some debug modes)
5921 void
5922 mono_dynamic_image_free_image (MonoDynamicImage *image)
5924 /* See create_dynamic_mono_image () */
5925 #if HAVE_BOEHM_GC
5926 /* Allocated using GC_MALLOC */
5927 #else
5928 g_free (image);
5929 #endif
5932 #ifndef DISABLE_REFLECTION_EMIT
5935 * mono_image_basic_init:
5936 * @assembly: an assembly builder object
5938 * Create the MonoImage that represents the assembly builder and setup some
5939 * of the helper hash table and the basic metadata streams.
5941 void
5942 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5944 MonoDynamicAssembly *assembly;
5945 MonoDynamicImage *image;
5946 MonoDomain *domain = mono_object_domain (assemblyb);
5948 if (assemblyb->dynamic_assembly)
5949 return;
5951 #if HAVE_BOEHM_GC
5952 /* assembly->assembly.image might be GC allocated */
5953 assembly = assemblyb->dynamic_assembly = (MonoDynamicAssembly *)GC_MALLOC (sizeof (MonoDynamicAssembly));
5954 #else
5955 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5956 #endif
5958 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5960 assembly->assembly.ref_count = 1;
5961 assembly->assembly.dynamic = TRUE;
5962 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5963 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5964 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5965 if (assemblyb->culture)
5966 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5967 else
5968 assembly->assembly.aname.culture = g_strdup ("");
5970 if (assemblyb->version) {
5971 char *vstr = mono_string_to_utf8 (assemblyb->version);
5972 char **version = g_strsplit (vstr, ".", 4);
5973 char **parts = version;
5974 assembly->assembly.aname.major = atoi (*parts++);
5975 assembly->assembly.aname.minor = atoi (*parts++);
5976 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5977 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5979 g_strfreev (version);
5980 g_free (vstr);
5981 } else {
5982 assembly->assembly.aname.major = 0;
5983 assembly->assembly.aname.minor = 0;
5984 assembly->assembly.aname.build = 0;
5985 assembly->assembly.aname.revision = 0;
5988 assembly->run = assemblyb->access != 2;
5989 assembly->save = assemblyb->access != 1;
5990 assembly->domain = domain;
5992 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5993 image->initial_image = TRUE;
5994 assembly->assembly.aname.name = image->image.name;
5995 assembly->assembly.image = &image->image;
5996 if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5997 /* -1 to correct for the trailing NULL byte */
5998 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5999 g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
6001 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);
6004 mono_domain_assemblies_lock (domain);
6005 domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
6006 mono_domain_assemblies_unlock (domain);
6008 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
6010 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
6012 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
6015 #endif /* !DISABLE_REFLECTION_EMIT */
6017 #ifndef DISABLE_REFLECTION_EMIT_SAVE
6019 static int
6020 calc_section_size (MonoDynamicImage *assembly)
6022 int nsections = 0;
6024 /* alignment constraints */
6025 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
6026 g_assert ((assembly->code.index % 4) == 0);
6027 assembly->meta_size += 3;
6028 assembly->meta_size &= ~3;
6029 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
6030 g_assert ((assembly->resources.index % 4) == 0);
6032 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
6033 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
6034 nsections++;
6036 if (assembly->win32_res) {
6037 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
6039 assembly->sections [MONO_SECTION_RSRC].size = res_size;
6040 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
6041 nsections++;
6044 assembly->sections [MONO_SECTION_RELOC].size = 12;
6045 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
6046 nsections++;
6048 return nsections;
6051 typedef struct {
6052 guint32 id;
6053 guint32 offset;
6054 GSList *children;
6055 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
6056 } ResTreeNode;
6058 static int
6059 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
6061 ResTreeNode *t1 = (ResTreeNode*)a;
6062 ResTreeNode *t2 = (ResTreeNode*)b;
6064 return t1->id - t2->id;
6068 * resource_tree_create:
6070 * Organize the resources into a resource tree.
6072 static ResTreeNode *
6073 resource_tree_create (MonoArray *win32_resources)
6075 ResTreeNode *tree, *res_node, *type_node, *lang_node;
6076 GSList *l;
6077 int i;
6079 tree = g_new0 (ResTreeNode, 1);
6081 for (i = 0; i < mono_array_length (win32_resources); ++i) {
6082 MonoReflectionWin32Resource *win32_res =
6083 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
6085 /* Create node */
6087 /* FIXME: BUG: this stores managed references in unmanaged memory */
6088 lang_node = g_new0 (ResTreeNode, 1);
6089 lang_node->id = win32_res->lang_id;
6090 lang_node->win32_res = win32_res;
6092 /* Create type node if neccesary */
6093 type_node = NULL;
6094 for (l = tree->children; l; l = l->next)
6095 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
6096 type_node = (ResTreeNode*)l->data;
6097 break;
6100 if (!type_node) {
6101 type_node = g_new0 (ResTreeNode, 1);
6102 type_node->id = win32_res->res_type;
6105 * The resource types have to be sorted otherwise
6106 * Windows Explorer can't display the version information.
6108 tree->children = g_slist_insert_sorted (tree->children,
6109 type_node, resource_tree_compare_by_id);
6112 /* Create res node if neccesary */
6113 res_node = NULL;
6114 for (l = type_node->children; l; l = l->next)
6115 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
6116 res_node = (ResTreeNode*)l->data;
6117 break;
6120 if (!res_node) {
6121 res_node = g_new0 (ResTreeNode, 1);
6122 res_node->id = win32_res->res_id;
6123 type_node->children = g_slist_append (type_node->children, res_node);
6126 res_node->children = g_slist_append (res_node->children, lang_node);
6129 return tree;
6133 * resource_tree_encode:
6135 * Encode the resource tree into the format used in the PE file.
6137 static void
6138 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
6140 char *entries;
6141 MonoPEResourceDir dir;
6142 MonoPEResourceDirEntry dir_entry;
6143 MonoPEResourceDataEntry data_entry;
6144 GSList *l;
6145 guint32 res_id_entries;
6148 * For the format of the resource directory, see the article
6149 * "An In-Depth Look into the Win32 Portable Executable File Format" by
6150 * Matt Pietrek
6153 memset (&dir, 0, sizeof (dir));
6154 memset (&dir_entry, 0, sizeof (dir_entry));
6155 memset (&data_entry, 0, sizeof (data_entry));
6157 g_assert (sizeof (dir) == 16);
6158 g_assert (sizeof (dir_entry) == 8);
6159 g_assert (sizeof (data_entry) == 16);
6161 node->offset = p - begin;
6163 /* IMAGE_RESOURCE_DIRECTORY */
6164 res_id_entries = g_slist_length (node->children);
6165 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
6167 memcpy (p, &dir, sizeof (dir));
6168 p += sizeof (dir);
6170 /* Reserve space for entries */
6171 entries = p;
6172 p += sizeof (dir_entry) * res_id_entries;
6174 /* Write children */
6175 for (l = node->children; l; l = l->next) {
6176 ResTreeNode *child = (ResTreeNode*)l->data;
6178 if (child->win32_res) {
6179 guint32 size;
6181 child->offset = p - begin;
6183 /* IMAGE_RESOURCE_DATA_ENTRY */
6184 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
6185 size = mono_array_length (child->win32_res->res_data);
6186 data_entry.rde_size = GUINT32_TO_LE (size);
6188 memcpy (p, &data_entry, sizeof (data_entry));
6189 p += sizeof (data_entry);
6191 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
6192 p += size;
6193 } else {
6194 resource_tree_encode (child, begin, p, &p);
6198 /* IMAGE_RESOURCE_ENTRY */
6199 for (l = node->children; l; l = l->next) {
6200 ResTreeNode *child = (ResTreeNode*)l->data;
6202 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
6203 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
6205 memcpy (entries, &dir_entry, sizeof (dir_entry));
6206 entries += sizeof (dir_entry);
6209 *endbuf = p;
6212 static void
6213 resource_tree_free (ResTreeNode * node)
6215 GSList * list;
6216 for (list = node->children; list; list = list->next)
6217 resource_tree_free ((ResTreeNode*)list->data);
6218 g_slist_free(node->children);
6219 g_free (node);
6222 static void
6223 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
6225 char *buf;
6226 char *p;
6227 guint32 size, i;
6228 MonoReflectionWin32Resource *win32_res;
6229 ResTreeNode *tree;
6231 if (!assemblyb->win32_resources)
6232 return;
6235 * Resources are stored in a three level tree inside the PE file.
6236 * - level one contains a node for each type of resource
6237 * - level two contains a node for each resource
6238 * - level three contains a node for each instance of a resource for a
6239 * specific language.
6242 tree = resource_tree_create (assemblyb->win32_resources);
6244 /* Estimate the size of the encoded tree */
6245 size = 0;
6246 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
6247 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
6248 size += mono_array_length (win32_res->res_data);
6250 /* Directory structure */
6251 size += mono_array_length (assemblyb->win32_resources) * 256;
6252 p = buf = (char *)g_malloc (size);
6254 resource_tree_encode (tree, p, p, &p);
6256 g_assert (p - buf <= size);
6258 assembly->win32_res = (char *)g_malloc (p - buf);
6259 assembly->win32_res_size = p - buf;
6260 memcpy (assembly->win32_res, buf, p - buf);
6262 g_free (buf);
6263 resource_tree_free (tree);
6266 static void
6267 fixup_resource_directory (char *res_section, char *p, guint32 rva)
6269 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
6270 int i;
6272 p += sizeof (MonoPEResourceDir);
6273 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
6274 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
6275 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
6276 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
6277 fixup_resource_directory (res_section, child, rva);
6278 } else {
6279 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
6280 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
6283 p += sizeof (MonoPEResourceDirEntry);
6287 static void
6288 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
6290 guint32 dummy;
6291 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
6292 g_error ("WriteFile returned %d\n", GetLastError ());
6296 * mono_image_create_pefile:
6297 * @mb: a module builder object
6299 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
6300 * assembly->pefile where it can be easily retrieved later in chunks.
6302 gboolean
6303 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6305 MonoMSDOSHeader *msdos;
6306 MonoDotNetHeader *header;
6307 MonoSectionTable *section;
6308 MonoCLIHeader *cli_header;
6309 guint32 size, image_size, virtual_base, text_offset;
6310 guint32 header_start, section_start, file_offset, virtual_offset;
6311 MonoDynamicImage *assembly;
6312 MonoReflectionAssemblyBuilder *assemblyb;
6313 MonoDynamicStream pefile_stream = {0};
6314 MonoDynamicStream *pefile = &pefile_stream;
6315 int i, nsections;
6316 guint32 *rva, value;
6317 guchar *p;
6318 static const unsigned char msheader[] = {
6319 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
6320 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6321 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6322 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
6323 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
6324 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
6325 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
6326 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
6329 mono_error_init (error);
6331 assemblyb = mb->assemblyb;
6333 mono_image_basic_init (assemblyb);
6334 assembly = mb->dynamic_image;
6336 assembly->pe_kind = assemblyb->pe_kind;
6337 assembly->machine = assemblyb->machine;
6338 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
6339 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
6341 if (!mono_image_build_metadata (mb, error))
6342 return FALSE;
6345 if (mb->is_main && assemblyb->resources) {
6346 int len = mono_array_length (assemblyb->resources);
6347 for (i = 0; i < len; ++i)
6348 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
6351 if (mb->resources) {
6352 int len = mono_array_length (mb->resources);
6353 for (i = 0; i < len; ++i)
6354 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
6357 if (!build_compressed_metadata (assembly, error))
6358 return FALSE;
6360 if (mb->is_main)
6361 assembly_add_win32_resources (assembly, assemblyb);
6363 nsections = calc_section_size (assembly);
6365 /* The DOS header and stub */
6366 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
6367 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
6369 /* the dotnet header */
6370 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
6372 /* the section tables */
6373 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
6375 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
6376 virtual_offset = VIRT_ALIGN;
6377 image_size = 0;
6379 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6380 if (!assembly->sections [i].size)
6381 continue;
6382 /* align offsets */
6383 file_offset += FILE_ALIGN - 1;
6384 file_offset &= ~(FILE_ALIGN - 1);
6385 virtual_offset += VIRT_ALIGN - 1;
6386 virtual_offset &= ~(VIRT_ALIGN - 1);
6388 assembly->sections [i].offset = file_offset;
6389 assembly->sections [i].rva = virtual_offset;
6391 file_offset += assembly->sections [i].size;
6392 virtual_offset += assembly->sections [i].size;
6393 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
6396 file_offset += FILE_ALIGN - 1;
6397 file_offset &= ~(FILE_ALIGN - 1);
6399 image_size += section_start + sizeof (MonoSectionTable) * nsections;
6401 /* back-patch info */
6402 msdos = (MonoMSDOSHeader*)pefile->data;
6403 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
6405 header = (MonoDotNetHeader*)(pefile->data + header_start);
6406 header->pesig [0] = 'P';
6407 header->pesig [1] = 'E';
6409 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
6410 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
6411 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
6412 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
6413 if (assemblyb->pekind == 1) {
6414 /* it's a dll */
6415 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
6416 } else {
6417 /* it's an exe */
6418 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
6421 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
6423 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
6424 header->pe.pe_major = 6;
6425 header->pe.pe_minor = 0;
6426 size = assembly->sections [MONO_SECTION_TEXT].size;
6427 size += FILE_ALIGN - 1;
6428 size &= ~(FILE_ALIGN - 1);
6429 header->pe.pe_code_size = GUINT32_FROM_LE(size);
6430 size = assembly->sections [MONO_SECTION_RSRC].size;
6431 size += FILE_ALIGN - 1;
6432 size &= ~(FILE_ALIGN - 1);
6433 header->pe.pe_data_size = GUINT32_FROM_LE(size);
6434 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
6435 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6436 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6437 /* pe_rva_entry_point always at the beginning of the text section */
6438 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6440 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
6441 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
6442 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
6443 header->nt.pe_os_major = GUINT16_FROM_LE (4);
6444 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
6445 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
6446 size = section_start;
6447 size += FILE_ALIGN - 1;
6448 size &= ~(FILE_ALIGN - 1);
6449 header->nt.pe_header_size = GUINT32_FROM_LE (size);
6450 size = image_size;
6451 size += VIRT_ALIGN - 1;
6452 size &= ~(VIRT_ALIGN - 1);
6453 header->nt.pe_image_size = GUINT32_FROM_LE (size);
6456 // Translate the PEFileKind value to the value expected by the Windows loader
6459 short kind;
6462 // PEFileKinds.Dll == 1
6463 // PEFileKinds.ConsoleApplication == 2
6464 // PEFileKinds.WindowApplication == 3
6466 // need to get:
6467 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
6468 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
6470 if (assemblyb->pekind == 3)
6471 kind = 2;
6472 else
6473 kind = 3;
6475 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
6477 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
6478 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
6479 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
6480 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
6481 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
6482 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
6484 /* fill data directory entries */
6486 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
6487 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6489 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
6490 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
6492 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
6493 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
6494 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
6495 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6496 /* patch entrypoint name */
6497 if (assemblyb->pekind == 1)
6498 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
6499 else
6500 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
6501 /* patch imported function RVA name */
6502 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
6503 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
6505 /* the import table */
6506 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
6507 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
6508 /* patch imported dll RVA name and other entries in the dir */
6509 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
6510 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
6511 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
6512 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6513 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
6514 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
6516 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
6517 value = (assembly->text_rva + assembly->imp_names_offset);
6518 *p++ = (value) & 0xff;
6519 *p++ = (value >> 8) & (0xff);
6520 *p++ = (value >> 16) & (0xff);
6521 *p++ = (value >> 24) & (0xff);
6523 /* the CLI header info */
6524 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
6525 cli_header->ch_size = GUINT32_FROM_LE (72);
6526 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
6527 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
6528 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
6529 if (assemblyb->entry_point) {
6530 guint32 table_idx = 0;
6531 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
6532 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
6533 table_idx = methodb->table_idx;
6534 } else {
6535 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
6537 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
6538 } else {
6539 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
6541 /* The embedded managed resources */
6542 text_offset = assembly->text_rva + assembly->code.index;
6543 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
6544 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
6545 text_offset += assembly->resources.index;
6546 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
6547 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
6548 text_offset += assembly->meta_size;
6549 if (assembly->strong_name_size) {
6550 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
6551 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
6552 text_offset += assembly->strong_name_size;
6555 /* write the section tables and section content */
6556 section = (MonoSectionTable*)(pefile->data + section_start);
6557 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6558 static const char section_names [][7] = {
6559 ".text", ".rsrc", ".reloc"
6561 if (!assembly->sections [i].size)
6562 continue;
6563 strcpy (section->st_name, section_names [i]);
6564 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
6565 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
6566 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
6567 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
6568 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
6569 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
6570 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
6571 section ++;
6574 checked_write_file (file, pefile->data, pefile->index);
6576 mono_dynamic_stream_reset (pefile);
6578 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6579 if (!assembly->sections [i].size)
6580 continue;
6582 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6583 g_error ("SetFilePointer returned %d\n", GetLastError ());
6585 switch (i) {
6586 case MONO_SECTION_TEXT:
6587 /* patch entry point */
6588 p = (guchar*)(assembly->code.data + 2);
6589 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
6590 *p++ = (value) & 0xff;
6591 *p++ = (value >> 8) & 0xff;
6592 *p++ = (value >> 16) & 0xff;
6593 *p++ = (value >> 24) & 0xff;
6595 checked_write_file (file, assembly->code.data, assembly->code.index);
6596 checked_write_file (file, assembly->resources.data, assembly->resources.index);
6597 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
6598 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
6601 g_free (assembly->image.raw_metadata);
6602 break;
6603 case MONO_SECTION_RELOC: {
6604 struct {
6605 guint32 page_rva;
6606 guint32 block_size;
6607 guint16 type_and_offset;
6608 guint16 term;
6609 } reloc;
6611 g_assert (sizeof (reloc) == 12);
6613 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
6614 reloc.block_size = GUINT32_FROM_LE (12);
6617 * the entrypoint is always at the start of the text section
6618 * 3 is IMAGE_REL_BASED_HIGHLOW
6619 * 2 is patch_size_rva - text_rva
6621 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
6622 reloc.term = 0;
6624 checked_write_file (file, &reloc, sizeof (reloc));
6626 break;
6628 case MONO_SECTION_RSRC:
6629 if (assembly->win32_res) {
6631 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
6632 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
6633 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
6635 break;
6636 default:
6637 g_assert_not_reached ();
6641 /* check that the file is properly padded */
6642 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6643 g_error ("SetFilePointer returned %d\n", GetLastError ());
6644 if (! SetEndOfFile (file))
6645 g_error ("SetEndOfFile returned %d\n", GetLastError ());
6647 mono_dynamic_stream_reset (&assembly->code);
6648 mono_dynamic_stream_reset (&assembly->us);
6649 mono_dynamic_stream_reset (&assembly->blob);
6650 mono_dynamic_stream_reset (&assembly->guid);
6651 mono_dynamic_stream_reset (&assembly->sheap);
6653 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
6654 g_hash_table_destroy (assembly->blob_cache);
6655 assembly->blob_cache = NULL;
6657 return TRUE;
6660 #else /* DISABLE_REFLECTION_EMIT_SAVE */
6662 gboolean
6663 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6665 g_assert_not_reached ();
6668 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
6670 #ifndef DISABLE_REFLECTION_EMIT
6672 MonoReflectionModule *
6673 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName, MonoError *error)
6675 char *name;
6676 MonoImage *image;
6677 MonoImageOpenStatus status;
6678 MonoDynamicAssembly *assembly;
6679 guint32 module_count;
6680 MonoImage **new_modules;
6681 gboolean *new_modules_loaded;
6683 mono_error_init (error);
6685 name = mono_string_to_utf8 (fileName);
6687 image = mono_image_open (name, &status);
6688 if (!image) {
6689 if (status == MONO_IMAGE_ERROR_ERRNO)
6690 mono_error_set_exception_instance (error, mono_get_exception_file_not_found (fileName));
6691 else
6692 mono_error_set_bad_image_name (error, name, NULL);
6693 g_free (name);
6694 return NULL;
6697 g_free (name);
6699 assembly = ab->dynamic_assembly;
6700 image->assembly = (MonoAssembly*)assembly;
6702 module_count = image->assembly->image->module_count;
6703 new_modules = g_new0 (MonoImage *, module_count + 1);
6704 new_modules_loaded = g_new0 (gboolean, module_count + 1);
6706 if (image->assembly->image->modules)
6707 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6708 if (image->assembly->image->modules_loaded)
6709 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6710 new_modules [module_count] = image;
6711 new_modules_loaded [module_count] = TRUE;
6712 mono_image_addref (image);
6714 g_free (image->assembly->image->modules);
6715 image->assembly->image->modules = new_modules;
6716 image->assembly->image->modules_loaded = new_modules_loaded;
6717 image->assembly->image->module_count ++;
6719 mono_assembly_load_references (image, &status);
6720 if (status) {
6721 mono_image_close (image);
6722 mono_error_set_exception_instance (error, mono_get_exception_file_not_found (fileName));
6723 return NULL;
6726 return mono_module_get_object_checked (mono_domain_get (), image, error);
6729 #endif /* DISABLE_REFLECTION_EMIT */
6732 * We need to return always the same object for MethodInfo, FieldInfo etc..
6733 * but we need to consider the reflected type.
6734 * type uses a different hash, since it uses custom hash/equal functions.
6737 typedef struct {
6738 gpointer item;
6739 MonoClass *refclass;
6740 } ReflectedEntry;
6742 static gboolean
6743 reflected_equal (gconstpointer a, gconstpointer b) {
6744 const ReflectedEntry *ea = (const ReflectedEntry *)a;
6745 const ReflectedEntry *eb = (const ReflectedEntry *)b;
6747 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6750 static guint
6751 reflected_hash (gconstpointer a) {
6752 const ReflectedEntry *ea = (const ReflectedEntry *)a;
6753 return mono_aligned_addr_hash (ea->item);
6756 #define CHECK_OBJECT(t,p,k) \
6757 do { \
6758 t _obj; \
6759 ReflectedEntry e; \
6760 e.item = (p); \
6761 e.refclass = (k); \
6762 mono_domain_lock (domain); \
6763 if (!domain->refobject_hash) \
6764 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection objects table"); \
6765 if ((_obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
6766 mono_domain_unlock (domain); \
6767 return _obj; \
6769 mono_domain_unlock (domain); \
6770 } while (0)
6772 #ifdef HAVE_BOEHM_GC
6773 /* ReflectedEntry doesn't need to be GC tracked */
6774 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6775 #define FREE_REFENTRY(entry) g_free ((entry))
6776 #define REFENTRY_REQUIRES_CLEANUP
6777 #else
6778 #define ALLOC_REFENTRY (ReflectedEntry *)mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6779 /* FIXME: */
6780 #define FREE_REFENTRY(entry)
6781 #endif
6783 #define CACHE_OBJECT(t,p,o,k) \
6784 do { \
6785 t _obj; \
6786 ReflectedEntry pe; \
6787 pe.item = (p); \
6788 pe.refclass = (k); \
6789 mono_domain_lock (domain); \
6790 if (!domain->refobject_hash) \
6791 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection objects table"); \
6792 _obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6793 if (!_obj) { \
6794 ReflectedEntry *e = ALLOC_REFENTRY; \
6795 e->item = (p); \
6796 e->refclass = (k); \
6797 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
6798 _obj = o; \
6800 mono_domain_unlock (domain); \
6801 return _obj; \
6802 } while (0)
6804 static void
6805 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6807 mono_domain_lock (domain);
6808 if (domain->refobject_hash) {
6809 ReflectedEntry pe;
6810 gpointer orig_pe, orig_value;
6812 pe.item = o;
6813 pe.refclass = klass;
6814 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6815 mono_g_hash_table_remove (domain->refobject_hash, &pe);
6816 FREE_REFENTRY (orig_pe);
6819 mono_domain_unlock (domain);
6822 #ifdef REFENTRY_REQUIRES_CLEANUP
6823 static void
6824 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6826 FREE_REFENTRY (key);
6828 #endif
6830 void
6831 mono_reflection_cleanup_domain (MonoDomain *domain)
6833 if (domain->refobject_hash) {
6834 /*let's avoid scanning the whole hashtable if not needed*/
6835 #ifdef REFENTRY_REQUIRES_CLEANUP
6836 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6837 #endif
6838 mono_g_hash_table_destroy (domain->refobject_hash);
6839 domain->refobject_hash = NULL;
6843 #ifndef DISABLE_REFLECTION_EMIT
6844 static gpointer
6845 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6847 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6850 static gpointer
6851 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6853 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6856 void
6857 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6859 MonoDynamicImage *image = moduleb->dynamic_image;
6860 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6861 if (!image) {
6862 MonoError error;
6863 int module_count;
6864 MonoImage **new_modules;
6865 MonoImage *ass;
6866 char *name, *fqname;
6868 * FIXME: we already created an image in mono_image_basic_init (), but
6869 * we don't know which module it belongs to, since that is only
6870 * determined at assembly save time.
6872 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6873 name = mono_string_to_utf8 (ab->name);
6874 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6875 if (!mono_error_ok (&error)) {
6876 g_free (name);
6877 mono_error_raise_exception (&error);
6879 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6881 moduleb->module.image = &image->image;
6882 moduleb->dynamic_image = image;
6883 register_module (mono_object_domain (moduleb), moduleb, image);
6885 /* register the module with the assembly */
6886 ass = ab->dynamic_assembly->assembly.image;
6887 module_count = ass->module_count;
6888 new_modules = g_new0 (MonoImage *, module_count + 1);
6890 if (ass->modules)
6891 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6892 new_modules [module_count] = &image->image;
6893 mono_image_addref (&image->image);
6895 g_free (ass->modules);
6896 ass->modules = new_modules;
6897 ass->module_count ++;
6901 void
6902 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6904 MonoDynamicImage *image = moduleb->dynamic_image;
6906 g_assert (type->type);
6907 image->wrappers_type = mono_class_from_mono_type (type->type);
6910 #endif
6913 * mono_assembly_get_object:
6914 * @domain: an app domain
6915 * @assembly: an assembly
6917 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6919 MonoReflectionAssembly*
6920 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6922 MonoError error;
6923 MonoReflectionAssembly *result;
6924 result = mono_assembly_get_object_checked (domain, assembly, &error);
6925 mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
6926 return result;
6929 * mono_assembly_get_object_checked:
6930 * @domain: an app domain
6931 * @assembly: an assembly
6933 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6935 MonoReflectionAssembly*
6936 mono_assembly_get_object_checked (MonoDomain *domain, MonoAssembly *assembly, MonoError *error)
6938 MonoReflectionAssembly *res;
6940 mono_error_init (error);
6942 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6943 res = (MonoReflectionAssembly *)mono_object_new_checked (domain, mono_class_get_mono_assembly_class (), error);
6944 if (!res)
6945 return NULL;
6946 res->assembly = assembly;
6948 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6953 MonoReflectionModule*
6954 mono_module_get_object (MonoDomain *domain, MonoImage *image)
6956 MonoError error;
6957 MonoReflectionModule *result;
6958 result = mono_module_get_object_checked (domain, image, &error);
6959 mono_error_raise_exception (&error);
6960 return result;
6963 MonoReflectionModule*
6964 mono_module_get_object_checked (MonoDomain *domain, MonoImage *image, MonoError *error)
6966 MonoReflectionModule *res;
6967 char* basename;
6969 mono_error_init (error);
6970 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6971 res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
6972 if (!res)
6973 return NULL;
6975 res->image = image;
6976 MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
6977 if (!assm_obj)
6978 return NULL;
6979 MONO_OBJECT_SETREF (res, assembly, assm_obj);
6981 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6982 basename = g_path_get_basename (image->name);
6983 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6984 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6986 g_free (basename);
6988 if (image->assembly->image == image) {
6989 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6990 } else {
6991 int i;
6992 res->token = 0;
6993 if (image->assembly->image->modules) {
6994 for (i = 0; i < image->assembly->image->module_count; i++) {
6995 if (image->assembly->image->modules [i] == image)
6996 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6998 g_assert (res->token);
7002 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
7005 MonoReflectionModule*
7006 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
7008 MonoError error;
7009 MonoReflectionModule *result;
7010 result = mono_module_file_get_object_checked (domain, image, table_index, &error);
7011 mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
7012 return result;
7015 MonoReflectionModule*
7016 mono_module_file_get_object_checked (MonoDomain *domain, MonoImage *image, int table_index, MonoError *error)
7018 MonoReflectionModule *res;
7019 MonoTableInfo *table;
7020 guint32 cols [MONO_FILE_SIZE];
7021 const char *name;
7022 guint32 i, name_idx;
7023 const char *val;
7025 mono_error_init (error);
7027 res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
7028 if (!res)
7029 return NULL;
7031 table = &image->tables [MONO_TABLE_FILE];
7032 g_assert (table_index < table->rows);
7033 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
7035 res->image = NULL;
7036 MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
7037 if (!assm_obj)
7038 return NULL;
7039 MONO_OBJECT_SETREF (res, assembly, assm_obj);
7040 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
7042 /* Check whenever the row has a corresponding row in the moduleref table */
7043 table = &image->tables [MONO_TABLE_MODULEREF];
7044 for (i = 0; i < table->rows; ++i) {
7045 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
7046 val = mono_metadata_string_heap (image, name_idx);
7047 if (strcmp (val, name) == 0)
7048 res->image = image->modules [i];
7051 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
7052 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
7053 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
7054 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
7055 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
7057 return res;
7060 static gboolean
7061 verify_safe_for_managed_space (MonoType *type)
7063 switch (type->type) {
7064 #ifdef DEBUG_HARDER
7065 case MONO_TYPE_ARRAY:
7066 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
7067 case MONO_TYPE_PTR:
7068 return verify_safe_for_managed_space (type->data.type);
7069 case MONO_TYPE_SZARRAY:
7070 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
7071 case MONO_TYPE_GENERICINST: {
7072 MonoGenericInst *inst = type->data.generic_class->inst;
7073 int i;
7074 if (!inst->is_open)
7075 break;
7076 for (i = 0; i < inst->type_argc; ++i)
7077 if (!verify_safe_for_managed_space (inst->type_argv [i]))
7078 return FALSE;
7079 return TRUE;
7081 #endif
7082 case MONO_TYPE_VAR:
7083 case MONO_TYPE_MVAR:
7084 return TRUE;
7085 default:
7086 return TRUE;
7090 static MonoType*
7091 mono_type_normalize (MonoType *type)
7093 int i;
7094 MonoGenericClass *gclass;
7095 MonoGenericInst *ginst;
7096 MonoClass *gtd;
7097 MonoGenericContainer *gcontainer;
7098 MonoType **argv = NULL;
7099 gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
7101 if (type->type != MONO_TYPE_GENERICINST)
7102 return type;
7104 gclass = type->data.generic_class;
7105 ginst = gclass->context.class_inst;
7106 if (!ginst->is_open)
7107 return type;
7109 gtd = gclass->container_class;
7110 gcontainer = gtd->generic_container;
7111 argv = g_newa (MonoType*, ginst->type_argc);
7113 for (i = 0; i < ginst->type_argc; ++i) {
7114 MonoType *t = ginst->type_argv [i], *norm;
7115 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
7116 is_denorm_gtd = FALSE;
7117 norm = mono_type_normalize (t);
7118 argv [i] = norm;
7119 if (norm != t)
7120 requires_rebind = TRUE;
7123 if (is_denorm_gtd)
7124 return type->byref == gtd->byval_arg.byref ? &gtd->byval_arg : &gtd->this_arg;
7126 if (requires_rebind) {
7127 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
7128 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
7131 return type;
7134 * mono_type_get_object:
7135 * @domain: an app domain
7136 * @type: a type
7138 * Return an System.MonoType object representing the type @type.
7140 MonoReflectionType*
7141 mono_type_get_object (MonoDomain *domain, MonoType *type)
7143 MonoError error;
7144 MonoReflectionType *ret = mono_type_get_object_checked (domain, type, &error);
7145 mono_error_raise_exception (&error);
7147 return ret;
7150 MonoReflectionType*
7151 mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *error)
7153 MonoType *norm_type;
7154 MonoReflectionType *res;
7155 MonoClass *klass;
7157 mono_error_init (error);
7159 klass = mono_class_from_mono_type (type);
7161 /*we must avoid using @type as it might have come
7162 * from a mono_metadata_type_dup and the caller
7163 * expects that is can be freed.
7164 * Using the right type from
7166 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
7168 /* void is very common */
7169 if (type->type == MONO_TYPE_VOID && domain->typeof_void)
7170 return (MonoReflectionType*)domain->typeof_void;
7173 * If the vtable of the given class was already created, we can use
7174 * the MonoType from there and avoid all locking and hash table lookups.
7176 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
7177 * that the resulting object is different.
7179 if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
7180 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
7181 if (vtable && vtable->type)
7182 return (MonoReflectionType *)vtable->type;
7185 mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
7186 mono_domain_lock (domain);
7187 if (!domain->type_hash)
7188 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
7189 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
7190 if ((res = (MonoReflectionType *)mono_g_hash_table_lookup (domain->type_hash, type))) {
7191 mono_domain_unlock (domain);
7192 mono_loader_unlock ();
7193 return res;
7196 /*Types must be normalized so a generic instance of the GTD get's the same inner type.
7197 * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
7198 * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
7199 * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
7200 * artifact of how generics are encoded and should be transparent to managed code so we
7201 * need to weed out this diference when retrieving managed System.Type objects.
7203 norm_type = mono_type_normalize (type);
7204 if (norm_type != type) {
7205 res = mono_type_get_object_checked (domain, norm_type, error);
7206 if (!mono_error_ok (error))
7207 return NULL;
7208 mono_g_hash_table_insert (domain->type_hash, type, res);
7209 mono_domain_unlock (domain);
7210 mono_loader_unlock ();
7211 return res;
7214 /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
7215 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
7216 g_assert (0);
7218 if (!verify_safe_for_managed_space (type)) {
7219 mono_domain_unlock (domain);
7220 mono_loader_unlock ();
7221 mono_error_set_generic_error (error, "System", "InvalidOperationException", "This type cannot be propagated to managed space");
7222 return NULL;
7225 if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
7226 gboolean is_type_done = TRUE;
7227 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
7228 * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
7229 * We can't simply close the types as this will interfere with other parts of the generics machinery.
7231 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
7232 MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
7234 if (gparam->owner && gparam->owner->is_method) {
7235 MonoMethod *method = gparam->owner->owner.method;
7236 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
7237 is_type_done = FALSE;
7238 } else if (gparam->owner && !gparam->owner->is_method) {
7239 MonoClass *klass = gparam->owner->owner.klass;
7240 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
7241 is_type_done = FALSE;
7245 /* g_assert_not_reached (); */
7246 /* should this be considered an error condition? */
7247 if (is_type_done && !type->byref) {
7248 mono_domain_unlock (domain);
7249 mono_loader_unlock ();
7250 return (MonoReflectionType *)mono_class_get_ref_info (klass);
7253 /* This is stored in vtables/JITted code so it has to be pinned */
7254 res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class, error);
7255 if (!mono_error_ok (error))
7256 return NULL;
7258 res->type = type;
7259 mono_g_hash_table_insert (domain->type_hash, type, res);
7261 if (type->type == MONO_TYPE_VOID)
7262 domain->typeof_void = (MonoObject*)res;
7264 mono_domain_unlock (domain);
7265 mono_loader_unlock ();
7266 return res;
7270 * mono_method_get_object:
7271 * @domain: an app domain
7272 * @method: a method
7273 * @refclass: the reflected type (can be NULL)
7275 * Return an System.Reflection.MonoMethod object representing the method @method.
7277 MonoReflectionMethod*
7278 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7280 MonoError error;
7281 MonoReflectionMethod *ret = NULL;
7282 ret = mono_method_get_object_checked (domain, method, refclass, &error);
7283 mono_error_raise_exception (&error);
7284 return ret;
7288 * mono_method_get_object_checked:
7289 * @domain: an app domain
7290 * @method: a method
7291 * @refclass: the reflected type (can be NULL)
7292 * @error: set on error.
7294 * Return an System.Reflection.MonoMethod object representing the method @method.
7295 * Returns NULL and sets @error on error.
7297 MonoReflectionMethod*
7298 mono_method_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
7301 * We use the same C representation for methods and constructors, but the type
7302 * name in C# is different.
7304 MonoReflectionType *rt;
7305 MonoClass *klass;
7306 MonoReflectionMethod *ret;
7308 mono_error_init (error);
7310 if (method->is_inflated) {
7311 MonoReflectionGenericMethod *gret;
7313 if (!refclass)
7314 refclass = method->klass;
7315 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7316 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
7317 klass = mono_class_get_mono_generic_cmethod_class ();
7318 } else {
7319 klass = mono_class_get_mono_generic_method_class ();
7321 gret = (MonoReflectionGenericMethod*)mono_object_new_checked (domain, klass, error);
7322 if (!mono_error_ok (error))
7323 goto leave;
7324 gret->method.method = method;
7326 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
7328 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7329 if (!mono_error_ok (error))
7330 goto leave;
7332 MONO_OBJECT_SETREF (gret, method.reftype, rt);
7334 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
7337 if (!refclass)
7338 refclass = method->klass;
7340 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7341 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
7342 klass = mono_class_get_mono_cmethod_class ();
7344 else {
7345 klass = mono_class_get_mono_method_class ();
7347 ret = (MonoReflectionMethod*)mono_object_new_checked (domain, klass, error);
7348 if (!mono_error_ok (error))
7349 goto leave;
7350 ret->method = method;
7352 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7353 if (!mono_error_ok (error))
7354 goto leave;
7356 MONO_OBJECT_SETREF (ret, reftype, rt);
7358 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
7360 leave:
7361 g_assert (!mono_error_ok (error));
7362 return NULL;
7366 * mono_method_clear_object:
7368 * Clear the cached reflection objects for the dynamic method METHOD.
7370 void
7371 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
7373 MonoClass *klass;
7374 g_assert (method_is_dynamic (method));
7376 klass = method->klass;
7377 while (klass) {
7378 clear_cached_object (domain, method, klass);
7379 klass = klass->parent;
7381 /* Added by mono_param_get_objects () */
7382 clear_cached_object (domain, &(method->signature), NULL);
7383 klass = method->klass;
7384 while (klass) {
7385 clear_cached_object (domain, &(method->signature), klass);
7386 klass = klass->parent;
7391 * mono_field_get_object:
7392 * @domain: an app domain
7393 * @klass: a type
7394 * @field: a field
7396 * Return an System.Reflection.MonoField object representing the field @field
7397 * in class @klass.
7399 MonoReflectionField*
7400 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
7402 MonoError error;
7403 MonoReflectionField *result;
7404 result = mono_field_get_object_checked (domain, klass, field, &error);
7405 mono_error_raise_exception (&error);
7406 return result;
7410 * mono_field_get_object_checked:
7411 * @domain: an app domain
7412 * @klass: a type
7413 * @field: a field
7414 * @error: set on error
7416 * Return an System.Reflection.MonoField object representing the field @field
7417 * in class @klass. On error, returns NULL and sets @error.
7419 MonoReflectionField*
7420 mono_field_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoClassField *field, MonoError *error)
7422 MonoReflectionType *rt;
7423 MonoReflectionField *res;
7425 mono_error_init (error);
7427 CHECK_OBJECT (MonoReflectionField *, field, klass);
7428 res = (MonoReflectionField *)mono_object_new_checked (domain, mono_class_get_mono_field_class (), error);
7429 if (!res)
7430 return NULL;
7431 res->klass = klass;
7432 res->field = field;
7433 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
7435 if (is_field_on_inst (field)) {
7436 res->attrs = get_field_on_inst_generic_type (field)->attrs;
7438 rt = mono_type_get_object_checked (domain, field->type, error);
7439 if (!mono_error_ok (error))
7440 return NULL;
7442 MONO_OBJECT_SETREF (res, type, rt);
7443 } else {
7444 if (field->type) {
7445 rt = mono_type_get_object_checked (domain, field->type, error);
7446 if (!mono_error_ok (error))
7447 return NULL;
7449 MONO_OBJECT_SETREF (res, type, rt);
7451 res->attrs = mono_field_get_flags (field);
7453 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
7457 * mono_property_get_object:
7458 * @domain: an app domain
7459 * @klass: a type
7460 * @property: a property
7462 * Return an System.Reflection.MonoProperty object representing the property @property
7463 * in class @klass.
7465 MonoReflectionProperty*
7466 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
7468 MonoError error;
7469 MonoReflectionProperty *result;
7470 result = mono_property_get_object_checked (domain, klass, property, &error);
7471 mono_error_raise_exception (&error);
7472 return result;
7476 * mono_property_get_object:
7477 * @domain: an app domain
7478 * @klass: a type
7479 * @property: a property
7480 * @error: set on error
7482 * Return an System.Reflection.MonoProperty object representing the property @property
7483 * in class @klass. On error returns NULL and sets @error.
7485 MonoReflectionProperty*
7486 mono_property_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoProperty *property, MonoError *error)
7488 MonoReflectionProperty *res;
7490 mono_error_init (error);
7492 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
7493 res = (MonoReflectionProperty *)mono_object_new_checked (domain, mono_class_get_mono_property_class (), error);
7494 if (!res)
7495 return NULL;
7496 res->klass = klass;
7497 res->property = property;
7498 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
7502 * mono_event_get_object:
7503 * @domain: an app domain
7504 * @klass: a type
7505 * @event: a event
7507 * Return an System.Reflection.MonoEvent object representing the event @event
7508 * in class @klass.
7510 MonoReflectionEvent*
7511 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
7513 MonoError error;
7514 MonoReflectionEvent *result;
7515 result = mono_event_get_object_checked (domain, klass, event, &error);
7516 mono_error_raise_exception (&error);
7517 return result;
7521 * mono_event_get_object_checked:
7522 * @domain: an app domain
7523 * @klass: a type
7524 * @event: a event
7525 * @error: set on error
7527 * Return an System.Reflection.MonoEvent object representing the event @event
7528 * in class @klass. On failure sets @error and returns NULL
7530 MonoReflectionEvent*
7531 mono_event_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoEvent *event, MonoError *error)
7533 MonoReflectionEvent *res;
7534 MonoReflectionMonoEvent *mono_event;
7536 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
7537 mono_event = (MonoReflectionMonoEvent *)mono_object_new_checked (domain, mono_class_get_mono_event_class (), error);
7538 if (!mono_event)
7539 return NULL;
7540 mono_event->klass = klass;
7541 mono_event->event = event;
7542 res = (MonoReflectionEvent*)mono_event;
7543 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
7547 * mono_get_reflection_missing_object:
7548 * @domain: Domain where the object lives
7550 * Returns the System.Reflection.Missing.Value singleton object
7551 * (of type System.Reflection.Missing).
7553 * Used as the value for ParameterInfo.DefaultValue when Optional
7554 * is present
7556 static MonoObject *
7557 mono_get_reflection_missing_object (MonoDomain *domain)
7559 MonoError error;
7560 MonoObject *obj;
7561 static MonoClassField *missing_value_field = NULL;
7563 if (!missing_value_field) {
7564 MonoClass *missing_klass;
7565 missing_klass = mono_class_get_missing_class ();
7566 mono_class_init (missing_klass);
7567 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
7568 g_assert (missing_value_field);
7570 obj = mono_field_get_value_object_checked (domain, missing_value_field, NULL, &error);
7571 mono_error_assert_ok (&error);
7572 return obj;
7575 static MonoObject*
7576 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
7578 if (!*dbnull)
7579 *dbnull = mono_get_dbnull_object (domain);
7580 return *dbnull;
7583 static MonoObject*
7584 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
7586 if (!*reflection_missing)
7587 *reflection_missing = mono_get_reflection_missing_object (domain);
7588 return *reflection_missing;
7592 * mono_param_get_objects:
7593 * @domain: an app domain
7594 * @method: a method
7596 * Return an System.Reflection.ParameterInfo array object representing the parameters
7597 * in the method @method.
7599 MonoArray*
7600 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
7602 static MonoClass *System_Reflection_ParameterInfo;
7603 static MonoClass *System_Reflection_ParameterInfo_array;
7604 MonoArray *res = NULL;
7605 MonoReflectionMethod *member = NULL;
7606 MonoReflectionParameter *param = NULL;
7607 char **names = NULL, **blobs = NULL;
7608 guint32 *types = NULL;
7609 MonoType *type = NULL;
7610 MonoObject *dbnull = NULL;
7611 MonoObject *missing = NULL;
7612 MonoMarshalSpec **mspecs = NULL;
7613 MonoMethodSignature *sig = NULL;
7614 MonoVTable *pinfo_vtable;
7615 MonoReflectionType *rt;
7616 int i;
7618 mono_error_init (error);
7620 if (!System_Reflection_ParameterInfo_array) {
7621 MonoClass *klass;
7623 klass = mono_class_get_mono_parameter_info_class ();
7625 mono_memory_barrier ();
7626 System_Reflection_ParameterInfo = klass;
7629 klass = mono_array_class_get (klass, 1);
7630 mono_memory_barrier ();
7631 System_Reflection_ParameterInfo_array = klass;
7634 sig = mono_method_signature_checked (method, error);
7635 if (!mono_error_ok (error))
7636 goto leave;
7638 if (!sig->param_count) {
7639 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0, error);
7640 if (!res)
7641 goto leave;
7643 return res;
7646 /* Note: the cache is based on the address of the signature into the method
7647 * since we already cache MethodInfos with the method as keys.
7649 CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
7651 member = mono_method_get_object_checked (domain, method, refclass, error);
7652 if (!member)
7653 goto leave;
7654 names = g_new (char *, sig->param_count);
7655 mono_method_get_param_names (method, (const char **) names);
7657 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
7658 mono_method_get_marshal_info (method, mspecs);
7660 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count, error);
7661 if (!res)
7662 goto leave;
7664 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
7665 for (i = 0; i < sig->param_count; ++i) {
7666 param = (MonoReflectionParameter *) mono_object_new_specific_checked (pinfo_vtable, error);
7667 if (!param)
7668 goto leave;
7670 rt = mono_type_get_object_checked (domain, sig->params [i], error);
7671 if (!rt)
7672 goto leave;
7674 MONO_OBJECT_SETREF (param, ClassImpl, rt);
7676 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
7678 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
7680 param->PositionImpl = i;
7681 param->AttrsImpl = sig->params [i]->attrs;
7683 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
7684 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7685 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7686 else
7687 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7688 } else {
7690 if (!blobs) {
7691 blobs = g_new0 (char *, sig->param_count);
7692 types = g_new0 (guint32, sig->param_count);
7693 get_default_param_value_blobs (method, blobs, types);
7696 /* Build MonoType for the type from the Constant Table */
7697 if (!type)
7698 type = g_new0 (MonoType, 1);
7699 type->type = (MonoTypeEnum)types [i];
7700 type->data.klass = NULL;
7701 if (types [i] == MONO_TYPE_CLASS)
7702 type->data.klass = mono_defaults.object_class;
7703 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
7704 /* For enums, types [i] contains the base type */
7706 type->type = MONO_TYPE_VALUETYPE;
7707 type->data.klass = mono_class_from_mono_type (sig->params [i]);
7708 } else
7709 type->data.klass = mono_class_from_mono_type (type);
7711 MonoObject *default_val_obj = mono_get_object_from_blob (domain, type, blobs [i], error);
7712 if (!is_ok (error))
7713 goto leave;
7714 MONO_OBJECT_SETREF (param, DefaultValueImpl, default_val_obj);
7716 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
7717 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
7718 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7719 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7720 else
7721 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7726 if (mspecs [i + 1]) {
7727 MonoReflectionMarshalAsAttribute* mobj;
7728 mobj = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1], error);
7729 if (!mobj)
7730 goto leave;
7731 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mobj);
7734 mono_array_setref (res, i, param);
7737 leave:
7738 g_free (names);
7739 g_free (blobs);
7740 g_free (types);
7741 g_free (type);
7743 if (sig) {
7744 for (i = sig->param_count; i >= 0; i--) {
7745 if (mspecs [i])
7746 mono_metadata_free_marshal_spec (mspecs [i]);
7749 g_free (mspecs);
7751 if (!is_ok (error))
7752 return NULL;
7754 CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
7757 MonoArray*
7758 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
7760 MonoError error;
7761 MonoArray *result = mono_param_get_objects_internal (domain, method, NULL, &error);
7762 mono_error_assert_ok (&error);
7763 return result;
7767 * mono_method_body_get_object:
7768 * @domain: an app domain
7769 * @method: a method
7771 * Return an System.Reflection.MethodBody object representing the method @method.
7773 MonoReflectionMethodBody*
7774 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
7776 MonoError error;
7777 MonoReflectionMethodBody *result = mono_method_body_get_object_checked (domain, method, &error);
7778 mono_error_cleanup (&error); /* FIXME better API that doesn't swallow the error */
7779 return result;
7783 * mono_method_body_get_object_checked:
7784 * @domain: an app domain
7785 * @method: a method
7786 * @error: set on error
7788 * Return an System.Reflection.MethodBody object representing the
7789 * method @method. On failure, returns NULL and sets @error.
7791 MonoReflectionMethodBody*
7792 mono_method_body_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoError *error)
7794 MonoReflectionMethodBody *ret;
7795 MonoMethodHeader *header;
7796 MonoImage *image;
7797 MonoReflectionType *rt;
7798 guint32 method_rva, local_var_sig_token;
7799 char *ptr;
7800 unsigned char format, flags;
7801 int i;
7803 mono_error_init (error);
7805 /* for compatibility with .net */
7806 if (method_is_dynamic (method)) {
7807 mono_error_set_generic_error (error, "System", "InvalidOperationException", "");
7808 return NULL;
7811 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
7813 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7814 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
7815 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
7816 (method->klass->image->raw_data && method->klass->image->raw_data [1] != 'Z') ||
7817 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
7818 return NULL;
7820 image = method->klass->image;
7821 header = mono_method_get_header_checked (method, error);
7822 return_val_if_nok (error, NULL);
7824 if (!image_is_dynamic (image)) {
7825 /* Obtain local vars signature token */
7826 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
7827 ptr = mono_image_rva_map (image, method_rva);
7828 flags = *(const unsigned char *) ptr;
7829 format = flags & METHOD_HEADER_FORMAT_MASK;
7830 switch (format){
7831 case METHOD_HEADER_TINY_FORMAT:
7832 local_var_sig_token = 0;
7833 break;
7834 case METHOD_HEADER_FAT_FORMAT:
7835 ptr += 2;
7836 ptr += 2;
7837 ptr += 4;
7838 local_var_sig_token = read32 (ptr);
7839 break;
7840 default:
7841 g_assert_not_reached ();
7843 } else
7844 local_var_sig_token = 0; //FIXME
7846 ret = (MonoReflectionMethodBody*)mono_object_new_checked (domain, mono_class_get_method_body_class (), error);
7847 if (!is_ok (error))
7848 goto fail;
7850 ret->init_locals = header->init_locals;
7851 ret->max_stack = header->max_stack;
7852 ret->local_var_sig_token = local_var_sig_token;
7853 MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
7854 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
7856 /* Locals */
7857 MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, mono_class_get_local_variable_info_class (), header->num_locals));
7858 for (i = 0; i < header->num_locals; ++i) {
7859 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new_checked (domain, mono_class_get_local_variable_info_class (), error);
7860 if (!is_ok (error))
7861 goto fail;
7863 rt = mono_type_get_object_checked (domain, header->locals [i], error);
7864 if (!is_ok (error))
7865 goto fail;
7867 MONO_OBJECT_SETREF (info, local_type, rt);
7869 info->is_pinned = header->locals [i]->pinned;
7870 info->local_index = i;
7871 mono_array_setref (ret->locals, i, info);
7874 /* Exceptions */
7875 MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, mono_class_get_exception_handling_clause_class (), header->num_clauses));
7876 for (i = 0; i < header->num_clauses; ++i) {
7877 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new_checked (domain, mono_class_get_exception_handling_clause_class (), error);
7878 if (!is_ok (error))
7879 goto fail;
7880 MonoExceptionClause *clause = &header->clauses [i];
7882 info->flags = clause->flags;
7883 info->try_offset = clause->try_offset;
7884 info->try_length = clause->try_len;
7885 info->handler_offset = clause->handler_offset;
7886 info->handler_length = clause->handler_len;
7887 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
7888 info->filter_offset = clause->data.filter_offset;
7889 else if (clause->data.catch_class) {
7890 rt = mono_type_get_object_checked (mono_domain_get (), &clause->data.catch_class->byval_arg, error);
7891 if (!is_ok (error))
7892 goto fail;
7894 MONO_OBJECT_SETREF (info, catch_type, rt);
7897 mono_array_setref (ret->clauses, i, info);
7900 mono_metadata_free_mh (header);
7901 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7902 return ret;
7904 fail:
7905 mono_metadata_free_mh (header);
7906 return NULL;
7910 * mono_get_dbnull_object:
7911 * @domain: Domain where the object lives
7913 * Returns the System.DBNull.Value singleton object
7915 * Used as the value for ParameterInfo.DefaultValue
7917 MonoObject *
7918 mono_get_dbnull_object (MonoDomain *domain)
7920 MonoError error;
7921 MonoObject *obj;
7922 static MonoClassField *dbnull_value_field = NULL;
7924 if (!dbnull_value_field) {
7925 MonoClass *dbnull_klass;
7926 dbnull_klass = mono_class_get_dbnull_class ();
7927 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7928 g_assert (dbnull_value_field);
7930 obj = mono_field_get_value_object_checked (domain, dbnull_value_field, NULL, &error);
7931 mono_error_assert_ok (&error);
7932 return obj;
7935 static void
7936 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7938 guint32 param_index, i, lastp, crow = 0;
7939 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7940 gint32 idx;
7942 MonoClass *klass = method->klass;
7943 MonoImage *image = klass->image;
7944 MonoMethodSignature *methodsig = mono_method_signature (method);
7946 MonoTableInfo *constt;
7947 MonoTableInfo *methodt;
7948 MonoTableInfo *paramt;
7950 if (!methodsig->param_count)
7951 return;
7953 mono_class_init (klass);
7955 if (image_is_dynamic (klass->image)) {
7956 MonoReflectionMethodAux *aux;
7957 if (method->is_inflated)
7958 method = ((MonoMethodInflated*)method)->declaring;
7959 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7960 if (aux && aux->param_defaults) {
7961 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7962 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7964 return;
7967 methodt = &klass->image->tables [MONO_TABLE_METHOD];
7968 paramt = &klass->image->tables [MONO_TABLE_PARAM];
7969 constt = &image->tables [MONO_TABLE_CONSTANT];
7971 idx = mono_method_get_index (method) - 1;
7972 g_assert (idx != -1);
7974 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7975 if (idx + 1 < methodt->rows)
7976 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7977 else
7978 lastp = paramt->rows + 1;
7980 for (i = param_index; i < lastp; ++i) {
7981 guint32 paramseq;
7983 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7984 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7986 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7987 continue;
7989 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7990 if (!crow) {
7991 continue;
7994 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7995 blobs [paramseq - 1] = (char *)mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7996 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7999 return;
8002 MonoObject *
8003 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob, MonoError *error)
8005 void *retval;
8006 MonoClass *klass;
8007 MonoObject *object;
8008 MonoType *basetype = type;
8010 mono_error_init (error);
8012 if (!blob)
8013 return NULL;
8015 klass = mono_class_from_mono_type (type);
8016 if (klass->valuetype) {
8017 object = mono_object_new_checked (domain, klass, error);
8018 return_val_if_nok (error, NULL);
8019 retval = ((gchar *) object + sizeof (MonoObject));
8020 if (klass->enumtype)
8021 basetype = mono_class_enum_basetype (klass);
8022 } else {
8023 retval = &object;
8026 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
8027 return object;
8028 else
8029 return NULL;
8032 static int
8033 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
8034 int found_sep;
8035 char *s;
8036 gboolean quoted = FALSE;
8038 memset (assembly, 0, sizeof (MonoAssemblyName));
8039 assembly->culture = "";
8040 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
8042 if (*p == '"') {
8043 quoted = TRUE;
8044 p++;
8046 assembly->name = p;
8047 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
8048 p++;
8049 if (quoted) {
8050 if (*p != '"')
8051 return 1;
8052 *p = 0;
8053 p++;
8055 if (*p != ',')
8056 return 1;
8057 *p = 0;
8058 /* Remove trailing whitespace */
8059 s = p - 1;
8060 while (*s && g_ascii_isspace (*s))
8061 *s-- = 0;
8062 p ++;
8063 while (g_ascii_isspace (*p))
8064 p++;
8065 while (*p) {
8066 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
8067 p += 8;
8068 assembly->major = strtoul (p, &s, 10);
8069 if (s == p || *s != '.')
8070 return 1;
8071 p = ++s;
8072 assembly->minor = strtoul (p, &s, 10);
8073 if (s == p || *s != '.')
8074 return 1;
8075 p = ++s;
8076 assembly->build = strtoul (p, &s, 10);
8077 if (s == p || *s != '.')
8078 return 1;
8079 p = ++s;
8080 assembly->revision = strtoul (p, &s, 10);
8081 if (s == p)
8082 return 1;
8083 p = s;
8084 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
8085 p += 8;
8086 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
8087 assembly->culture = "";
8088 p += 7;
8089 } else {
8090 assembly->culture = p;
8091 while (*p && *p != ',') {
8092 p++;
8095 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
8096 p += 15;
8097 if (strncmp (p, "null", 4) == 0) {
8098 p += 4;
8099 } else {
8100 int len;
8101 gchar *start = p;
8102 while (*p && *p != ',') {
8103 p++;
8105 len = (p - start + 1);
8106 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
8107 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
8108 g_strlcpy ((char*)assembly->public_key_token, start, len);
8110 } else {
8111 while (*p && *p != ',')
8112 p++;
8114 found_sep = 0;
8115 while (g_ascii_isspace (*p) || *p == ',') {
8116 *p++ = 0;
8117 found_sep = 1;
8118 continue;
8120 /* failed */
8121 if (!found_sep)
8122 return 1;
8125 return 0;
8129 * mono_reflection_parse_type:
8130 * @name: type name
8132 * Parse a type name as accepted by the GetType () method and output the info
8133 * extracted in the info structure.
8134 * the name param will be mangled, so, make a copy before passing it to this function.
8135 * The fields in info will be valid until the memory pointed to by name is valid.
8137 * See also mono_type_get_name () below.
8139 * Returns: 0 on parse error.
8141 static int
8142 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
8143 MonoTypeNameParse *info)
8145 char *start, *p, *w, *last_point, *startn;
8146 int in_modifiers = 0;
8147 int isbyref = 0, rank = 0, isptr = 0;
8149 start = p = w = name;
8151 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
8152 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
8153 info->name = info->name_space = NULL;
8154 info->nested = NULL;
8155 info->modifiers = NULL;
8156 info->type_arguments = NULL;
8158 /* last_point separates the namespace from the name */
8159 last_point = NULL;
8160 /* Skips spaces */
8161 while (*p == ' ') p++, start++, w++, name++;
8163 while (*p) {
8164 switch (*p) {
8165 case '+':
8166 *p = 0; /* NULL terminate the name */
8167 startn = p + 1;
8168 info->nested = g_list_append (info->nested, startn);
8169 /* we have parsed the nesting namespace + name */
8170 if (info->name)
8171 break;
8172 if (last_point) {
8173 info->name_space = start;
8174 *last_point = 0;
8175 info->name = last_point + 1;
8176 } else {
8177 info->name_space = (char *)"";
8178 info->name = start;
8180 break;
8181 case '.':
8182 last_point = p;
8183 break;
8184 case '\\':
8185 ++p;
8186 break;
8187 case '&':
8188 case '*':
8189 case '[':
8190 case ',':
8191 case ']':
8192 in_modifiers = 1;
8193 break;
8194 default:
8195 break;
8197 if (in_modifiers)
8198 break;
8199 // *w++ = *p++;
8200 p++;
8203 if (!info->name) {
8204 if (last_point) {
8205 info->name_space = start;
8206 *last_point = 0;
8207 info->name = last_point + 1;
8208 } else {
8209 info->name_space = (char *)"";
8210 info->name = start;
8213 while (*p) {
8214 switch (*p) {
8215 case '&':
8216 if (isbyref) /* only one level allowed by the spec */
8217 return 0;
8218 isbyref = 1;
8219 isptr = 0;
8220 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
8221 *p++ = 0;
8222 break;
8223 case '*':
8224 if (isbyref) /* pointer to ref not okay */
8225 return 0;
8226 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
8227 isptr = 1;
8228 *p++ = 0;
8229 break;
8230 case '[':
8231 if (isbyref) /* array of ref and generic ref are not okay */
8232 return 0;
8233 //Decide if it's an array of a generic argument list
8234 *p++ = 0;
8236 if (!*p) //XXX test
8237 return 0;
8238 if (*p == ',' || *p == '*' || *p == ']') { //array
8239 isptr = 0;
8240 rank = 1;
8241 while (*p) {
8242 if (*p == ']')
8243 break;
8244 if (*p == ',')
8245 rank++;
8246 else if (*p == '*') /* '*' means unknown lower bound */
8247 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
8248 else
8249 return 0;
8250 ++p;
8252 if (*p++ != ']')
8253 return 0;
8254 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
8255 } else {
8256 if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
8257 return 0;
8258 isptr = 0;
8259 info->type_arguments = g_ptr_array_new ();
8260 while (*p) {
8261 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
8262 gboolean fqname = FALSE;
8264 g_ptr_array_add (info->type_arguments, subinfo);
8266 while (*p == ' ') p++;
8267 if (*p == '[') {
8268 p++;
8269 fqname = TRUE;
8272 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
8273 return 0;
8275 /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
8276 if (fqname && (*p != ']')) {
8277 char *aname;
8279 if (*p != ',')
8280 return 0;
8281 *p++ = 0;
8283 aname = p;
8284 while (*p && (*p != ']'))
8285 p++;
8287 if (*p != ']')
8288 return 0;
8290 *p++ = 0;
8291 while (*aname) {
8292 if (g_ascii_isspace (*aname)) {
8293 ++aname;
8294 continue;
8296 break;
8298 if (!*aname ||
8299 !assembly_name_to_aname (&subinfo->assembly, aname))
8300 return 0;
8301 } else if (fqname && (*p == ']')) {
8302 *p++ = 0;
8304 if (*p == ']') {
8305 *p++ = 0;
8306 break;
8307 } else if (!*p) {
8308 return 0;
8310 *p++ = 0;
8313 break;
8314 case ']':
8315 if (is_recursed)
8316 goto end;
8317 return 0;
8318 case ',':
8319 if (is_recursed)
8320 goto end;
8321 *p++ = 0;
8322 while (*p) {
8323 if (g_ascii_isspace (*p)) {
8324 ++p;
8325 continue;
8327 break;
8329 if (!*p)
8330 return 0; /* missing assembly name */
8331 if (!assembly_name_to_aname (&info->assembly, p))
8332 return 0;
8333 break;
8334 default:
8335 return 0;
8337 if (info->assembly.name)
8338 break;
8340 // *w = 0; /* terminate class name */
8341 end:
8342 if (!info->name || !*info->name)
8343 return 0;
8344 if (endptr)
8345 *endptr = p;
8346 /* add other consistency checks */
8347 return 1;
8352 * mono_identifier_unescape_type_name_chars:
8353 * @identifier: the display name of a mono type
8355 * Returns:
8356 * The name in internal form, that is without escaping backslashes.
8358 * The string is modified in place!
8360 char*
8361 mono_identifier_unescape_type_name_chars(char* identifier)
8363 char *w, *r;
8364 if (!identifier)
8365 return NULL;
8366 for (w = r = identifier; *r != 0; r++)
8368 char c = *r;
8369 if (c == '\\') {
8370 r++;
8371 if (*r == 0)
8372 break;
8373 c = *r;
8375 *w = c;
8376 w++;
8378 if (w != r)
8379 *w = 0;
8380 return identifier;
8383 void
8384 mono_identifier_unescape_info (MonoTypeNameParse* info);
8386 static void
8387 unescape_each_type_argument(void* data, void* user_data)
8389 MonoTypeNameParse* info = (MonoTypeNameParse*)data;
8390 mono_identifier_unescape_info (info);
8393 static void
8394 unescape_each_nested_name (void* data, void* user_data)
8396 char* nested_name = (char*) data;
8397 mono_identifier_unescape_type_name_chars(nested_name);
8401 * mono_identifier_unescape_info:
8403 * @info: a parsed display form of an (optionally assembly qualified) full type name.
8405 * Returns: nothing.
8407 * Destructively updates the info by unescaping the identifiers that
8408 * comprise the type namespace, name, nested types (if any) and
8409 * generic type arguments (if any).
8411 * The resulting info has the names in internal form.
8414 void
8415 mono_identifier_unescape_info (MonoTypeNameParse *info)
8417 if (!info)
8418 return;
8419 mono_identifier_unescape_type_name_chars(info->name_space);
8420 mono_identifier_unescape_type_name_chars(info->name);
8421 // but don't escape info->assembly
8422 if (info->type_arguments)
8423 g_ptr_array_foreach(info->type_arguments, &unescape_each_type_argument, NULL);
8424 if (info->nested)
8425 g_list_foreach(info->nested, &unescape_each_nested_name, NULL);
8429 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
8431 int ok = _mono_reflection_parse_type (name, NULL, FALSE, info);
8432 if (ok) {
8433 mono_identifier_unescape_info (info);
8435 return ok;
8438 static MonoType*
8439 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase, MonoError *error)
8441 gboolean type_resolve = FALSE;
8442 MonoType *type;
8443 MonoImage *rootimage = image;
8445 mono_error_init (error);
8447 if (info->assembly.name) {
8448 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
8449 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
8451 * This could happen in the AOT compiler case when the search hook is not
8452 * installed.
8454 assembly = image->assembly;
8455 if (!assembly) {
8456 /* then we must load the assembly ourselve - see #60439 */
8457 assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
8458 if (!assembly)
8459 return NULL;
8461 image = assembly->image;
8462 } else if (!image) {
8463 image = mono_defaults.corlib;
8466 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve, error);
8467 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
8468 mono_error_cleanup (error);
8469 image = mono_defaults.corlib;
8470 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve, error);
8473 return type;
8477 * mono_reflection_get_type_internal:
8479 * Returns: may return NULL on success, sets error on failure.
8481 static MonoType*
8482 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8484 MonoClass *klass;
8485 GList *mod;
8486 int modval;
8487 gboolean bounded = FALSE;
8489 mono_error_init (error);
8490 if (!image)
8491 image = mono_defaults.corlib;
8493 if (!rootimage)
8494 rootimage = mono_defaults.corlib;
8496 if (ignorecase)
8497 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, error);
8498 else
8499 klass = mono_class_from_name_checked (image, info->name_space, info->name, error);
8501 if (!klass)
8502 return NULL;
8504 for (mod = info->nested; mod; mod = mod->next) {
8505 gpointer iter = NULL;
8506 MonoClass *parent;
8508 parent = klass;
8509 mono_class_init (parent);
8511 while ((klass = mono_class_get_nested_types (parent, &iter))) {
8512 char *lastp;
8513 char *nested_name, *nested_nspace;
8514 gboolean match = TRUE;
8516 lastp = strrchr ((const char *)mod->data, '.');
8517 if (lastp) {
8518 /* Nested classes can have namespaces */
8519 int nspace_len;
8521 nested_name = g_strdup (lastp + 1);
8522 nspace_len = lastp - (char*)mod->data;
8523 nested_nspace = (char *)g_malloc (nspace_len + 1);
8524 memcpy (nested_nspace, mod->data, nspace_len);
8525 nested_nspace [nspace_len] = '\0';
8527 } else {
8528 nested_name = (char *)mod->data;
8529 nested_nspace = NULL;
8532 if (nested_nspace) {
8533 if (ignorecase) {
8534 if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
8535 match = FALSE;
8536 } else {
8537 if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
8538 match = FALSE;
8541 if (match) {
8542 if (ignorecase) {
8543 if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
8544 match = FALSE;
8545 } else {
8546 if (strcmp (klass->name, nested_name) != 0)
8547 match = FALSE;
8550 if (lastp) {
8551 g_free (nested_name);
8552 g_free (nested_nspace);
8554 if (match)
8555 break;
8558 if (!klass)
8559 break;
8561 if (!klass)
8562 return NULL;
8564 if (info->type_arguments) {
8565 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
8566 MonoReflectionType *the_type;
8567 MonoType *instance;
8568 int i;
8570 for (i = 0; i < info->type_arguments->len; i++) {
8571 MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8573 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase, error);
8574 if (!type_args [i]) {
8575 g_free (type_args);
8576 return NULL;
8580 the_type = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
8581 if (!the_type)
8582 return NULL;
8584 instance = mono_reflection_bind_generic_parameters (
8585 the_type, info->type_arguments->len, type_args, error);
8587 g_free (type_args);
8588 if (!instance)
8589 return NULL;
8591 klass = mono_class_from_mono_type (instance);
8594 for (mod = info->modifiers; mod; mod = mod->next) {
8595 modval = GPOINTER_TO_UINT (mod->data);
8596 if (!modval) { /* byref: must be last modifier */
8597 return &klass->this_arg;
8598 } else if (modval == -1) {
8599 klass = mono_ptr_class_get (&klass->byval_arg);
8600 } else if (modval == -2) {
8601 bounded = TRUE;
8602 } else { /* array rank */
8603 klass = mono_bounded_array_class_get (klass, modval, bounded);
8607 return &klass->byval_arg;
8611 * mono_reflection_get_type:
8612 * @image: a metadata context
8613 * @info: type description structure
8614 * @ignorecase: flag for case-insensitive string compares
8615 * @type_resolve: whenever type resolve was already tried
8617 * Build a MonoType from the type description in @info.
8621 MonoType*
8622 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
8623 MonoError error;
8624 MonoType *result = mono_reflection_get_type_with_rootimage (image, image, info, ignorecase, type_resolve, &error);
8625 mono_error_cleanup (&error);
8626 return result;
8630 * mono_reflection_get_type_checked:
8631 * @image: a metadata context
8632 * @info: type description structure
8633 * @ignorecase: flag for case-insensitive string compares
8634 * @type_resolve: whenever type resolve was already tried
8635 * @error: set on error.
8637 * Build a MonoType from the type description in @info. On failure returns NULL and sets @error.
8640 MonoType*
8641 mono_reflection_get_type_checked (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error) {
8642 mono_error_init (error);
8643 return mono_reflection_get_type_with_rootimage (image, image, info, ignorecase, type_resolve, error);
8647 static MonoType*
8648 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8650 MonoReflectionAssemblyBuilder *abuilder;
8651 MonoType *type;
8652 int i;
8654 mono_error_init (error);
8655 g_assert (assembly_is_dynamic (assembly));
8656 abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object_checked (((MonoDynamicAssembly*)assembly)->domain, assembly, error);
8657 if (!abuilder)
8658 return NULL;
8660 /* Enumerate all modules */
8662 type = NULL;
8663 if (abuilder->modules) {
8664 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
8665 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
8666 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase, error);
8667 if (type)
8668 break;
8669 if (!mono_error_ok (error))
8670 return NULL;
8674 if (!type && abuilder->loaded_modules) {
8675 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
8676 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
8677 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase, error);
8678 if (type)
8679 break;
8680 if (!mono_error_ok (error))
8681 return NULL;
8685 return type;
8688 MonoType*
8689 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error)
8691 MonoType *type;
8692 MonoReflectionAssembly *assembly;
8693 GString *fullName;
8694 GList *mod;
8696 mono_error_init (error);
8698 if (image && image_is_dynamic (image))
8699 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase, error);
8700 else {
8701 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase, error);
8703 return_val_if_nok (error, NULL);
8705 if (type)
8706 return type;
8707 if (!mono_domain_has_type_resolve (mono_domain_get ()))
8708 return NULL;
8710 if (type_resolve) {
8711 if (*type_resolve)
8712 return NULL;
8713 else
8714 *type_resolve = TRUE;
8717 /* Reconstruct the type name */
8718 fullName = g_string_new ("");
8719 if (info->name_space && (info->name_space [0] != '\0'))
8720 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
8721 else
8722 g_string_printf (fullName, "%s", info->name);
8723 for (mod = info->nested; mod; mod = mod->next)
8724 g_string_append_printf (fullName, "+%s", (char*)mod->data);
8726 assembly = mono_domain_try_type_resolve_checked ( mono_domain_get (), fullName->str, NULL, error);
8727 if (!is_ok (error)) {
8728 g_string_free (fullName, TRUE);
8729 return NULL;
8732 if (assembly) {
8733 if (assembly_is_dynamic (assembly->assembly))
8734 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly,
8735 info, ignorecase, error);
8736 else
8737 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
8738 info, ignorecase, error);
8740 g_string_free (fullName, TRUE);
8741 return_val_if_nok (error, NULL);
8742 return type;
8745 void
8746 mono_reflection_free_type_info (MonoTypeNameParse *info)
8748 g_list_free (info->modifiers);
8749 g_list_free (info->nested);
8751 if (info->type_arguments) {
8752 int i;
8754 for (i = 0; i < info->type_arguments->len; i++) {
8755 MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8757 mono_reflection_free_type_info (subinfo);
8758 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
8759 g_free (subinfo);
8762 g_ptr_array_free (info->type_arguments, TRUE);
8767 * mono_reflection_type_from_name:
8768 * @name: type name.
8769 * @image: a metadata context (can be NULL).
8771 * Retrieves a MonoType from its @name. If the name is not fully qualified,
8772 * it defaults to get the type from @image or, if @image is NULL or loading
8773 * from it fails, uses corlib.
8776 MonoType*
8777 mono_reflection_type_from_name (char *name, MonoImage *image)
8779 MonoError error;
8780 MonoType *result = mono_reflection_type_from_name_checked (name, image, &error);
8781 mono_error_cleanup (&error);
8782 return result;
8786 * mono_reflection_type_from_name_checked:
8787 * @name: type name.
8788 * @image: a metadata context (can be NULL).
8789 * @error: set on errror.
8791 * Retrieves a MonoType from its @name. If the name is not fully qualified,
8792 * it defaults to get the type from @image or, if @image is NULL or loading
8793 * from it fails, uses corlib. On failure returns NULL and sets @error.
8796 MonoType*
8797 mono_reflection_type_from_name_checked (char *name, MonoImage *image, MonoError *error)
8799 MonoType *type = NULL;
8800 MonoTypeNameParse info;
8801 char *tmp;
8803 mono_error_init (error);
8804 /* Make a copy since parse_type modifies its argument */
8805 tmp = g_strdup (name);
8807 /*g_print ("requested type %s\n", str);*/
8808 if (mono_reflection_parse_type (tmp, &info)) {
8809 type = _mono_reflection_get_type_from_info (&info, image, FALSE, error);
8810 if (!is_ok (error)) {
8811 g_free (tmp);
8812 mono_reflection_free_type_info (&info);
8813 return NULL;
8817 g_free (tmp);
8818 mono_reflection_free_type_info (&info);
8819 return type;
8823 * mono_reflection_get_token:
8825 * Return the metadata token of OBJ which should be an object
8826 * representing a metadata element.
8828 guint32
8829 mono_reflection_get_token (MonoObject *obj)
8831 MonoError error;
8832 guint32 result = mono_reflection_get_token_checked (obj, &error);
8833 mono_error_assert_ok (&error);
8834 return result;
8838 * mono_reflection_get_token_checked:
8839 * @obj: the object
8840 * @error: set on error
8842 * Return the metadata token of @obj which should be an object
8843 * representing a metadata element. On failure sets @error.
8845 guint32
8846 mono_reflection_get_token_checked (MonoObject *obj, MonoError *error)
8848 MonoClass *klass;
8849 guint32 token = 0;
8851 mono_error_init (error);
8853 klass = obj->vtable->klass;
8855 if (strcmp (klass->name, "MethodBuilder") == 0) {
8856 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
8858 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8859 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
8860 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
8862 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8863 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
8864 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
8866 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
8867 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
8868 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
8869 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
8870 } else if (strcmp (klass->name, "MonoType") == 0) {
8871 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
8872 return_val_if_nok (error, 0);
8873 MonoClass *mc = mono_class_from_mono_type (type);
8874 if (!mono_class_init (mc)) {
8875 mono_error_set_exception_instance (error, mono_class_get_exception_for_failure (mc));
8876 return 0;
8879 token = mc->type_token;
8880 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
8881 strcmp (klass->name, "MonoMethod") == 0 ||
8882 strcmp (klass->name, "MonoGenericMethod") == 0 ||
8883 strcmp (klass->name, "MonoGenericCMethod") == 0) {
8884 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
8885 if (m->method->is_inflated) {
8886 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
8887 return inflated->declaring->token;
8888 } else {
8889 token = m->method->token;
8891 } else if (strcmp (klass->name, "MonoField") == 0) {
8892 MonoReflectionField *f = (MonoReflectionField*)obj;
8894 if (is_field_on_inst (f->field)) {
8895 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
8897 if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
8898 int field_index = f->field - dgclass->fields;
8899 MonoObject *obj;
8901 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
8902 obj = dgclass->field_objects [field_index];
8903 return mono_reflection_get_token_checked (obj, error);
8906 token = mono_class_get_field_token (f->field);
8907 } else if (strcmp (klass->name, "MonoProperty") == 0) {
8908 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
8910 token = mono_class_get_property_token (p->property);
8911 } else if (strcmp (klass->name, "MonoEvent") == 0) {
8912 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
8914 token = mono_class_get_event_token (p->event);
8915 } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
8916 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
8917 MonoClass *member_class = mono_object_class (p->MemberImpl);
8918 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
8920 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
8921 } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
8922 MonoReflectionModule *m = (MonoReflectionModule*)obj;
8924 token = m->token;
8925 } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
8926 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
8927 } else {
8928 mono_error_set_not_implemented (error, "MetadataToken is not supported for type '%s.%s'",
8929 klass->name_space, klass->name);
8930 return 0;
8933 return token;
8936 static MonoClass*
8937 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
8939 char *n;
8940 MonoType *t;
8941 int slen = mono_metadata_decode_value (p, &p);
8943 mono_error_init (error);
8945 n = (char *)g_memdup (p, slen + 1);
8946 n [slen] = 0;
8947 t = mono_reflection_type_from_name_checked (n, image, error);
8948 if (!t) {
8949 char *msg = g_strdup (mono_error_get_message (error));
8950 mono_error_cleanup (error);
8951 /* We don't free n, it's consumed by mono_error */
8952 mono_error_set_type_load_name (error, n, NULL, "Could not load enum type %s while decoding custom attribute: %s", n, msg);
8953 g_free (msg);
8954 return NULL;
8956 g_free (n);
8957 p += slen;
8958 *end = p;
8959 return mono_class_from_mono_type (t);
8962 static void*
8963 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
8965 int slen, type = t->type;
8966 MonoClass *tklass = t->data.klass;
8968 mono_error_init (error);
8970 handle_enum:
8971 switch (type) {
8972 case MONO_TYPE_U1:
8973 case MONO_TYPE_I1:
8974 case MONO_TYPE_BOOLEAN: {
8975 MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean));
8976 *bval = *p;
8977 *end = p + 1;
8978 return bval;
8980 case MONO_TYPE_CHAR:
8981 case MONO_TYPE_U2:
8982 case MONO_TYPE_I2: {
8983 guint16 *val = (guint16 *)g_malloc (sizeof (guint16));
8984 *val = read16 (p);
8985 *end = p + 2;
8986 return val;
8988 #if SIZEOF_VOID_P == 4
8989 case MONO_TYPE_U:
8990 case MONO_TYPE_I:
8991 #endif
8992 case MONO_TYPE_R4:
8993 case MONO_TYPE_U4:
8994 case MONO_TYPE_I4: {
8995 guint32 *val = (guint32 *)g_malloc (sizeof (guint32));
8996 *val = read32 (p);
8997 *end = p + 4;
8998 return val;
9000 #if SIZEOF_VOID_P == 8
9001 case MONO_TYPE_U: /* error out instead? this should probably not happen */
9002 case MONO_TYPE_I:
9003 #endif
9004 case MONO_TYPE_U8:
9005 case MONO_TYPE_I8: {
9006 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
9007 *val = read64 (p);
9008 *end = p + 8;
9009 return val;
9011 case MONO_TYPE_R8: {
9012 double *val = (double *)g_malloc (sizeof (double));
9013 readr8 (p, val);
9014 *end = p + 8;
9015 return val;
9017 case MONO_TYPE_VALUETYPE:
9018 if (t->data.klass->enumtype) {
9019 type = mono_class_enum_basetype (t->data.klass)->type;
9020 goto handle_enum;
9021 } else {
9022 MonoClass *k = t->data.klass;
9024 if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
9025 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
9026 *val = read64 (p);
9027 *end = p + 8;
9028 return val;
9031 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
9032 break;
9034 case MONO_TYPE_STRING:
9035 if (*p == (char)0xFF) {
9036 *end = p + 1;
9037 return NULL;
9039 slen = mono_metadata_decode_value (p, &p);
9040 *end = p + slen;
9041 return mono_string_new_len (mono_domain_get (), p, slen);
9042 case MONO_TYPE_CLASS: {
9043 MonoReflectionType *rt;
9044 char *n;
9045 MonoType *t;
9046 if (*p == (char)0xFF) {
9047 *end = p + 1;
9048 return NULL;
9050 handle_type:
9051 slen = mono_metadata_decode_value (p, &p);
9052 n = (char *)g_memdup (p, slen + 1);
9053 n [slen] = 0;
9054 t = mono_reflection_type_from_name_checked (n, image, error);
9055 if (!t) {
9056 char *msg = g_strdup (mono_error_get_message (error));
9057 mono_error_cleanup (error);
9058 /* We don't free n, it's consumed by mono_error */
9059 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute: %msg", n, msg);
9060 g_free (msg);
9061 return NULL;
9063 g_free (n);
9064 *end = p + slen;
9066 rt = mono_type_get_object_checked (mono_domain_get (), t, error);
9067 if (!mono_error_ok (error))
9068 return NULL;
9070 return rt;
9072 case MONO_TYPE_OBJECT: {
9073 char subt = *p++;
9074 MonoObject *obj;
9075 MonoClass *subc = NULL;
9076 void *val;
9078 if (subt == 0x50) {
9079 goto handle_type;
9080 } else if (subt == 0x0E) {
9081 type = MONO_TYPE_STRING;
9082 goto handle_enum;
9083 } else if (subt == 0x1D) {
9084 MonoType simple_type = {{0}};
9085 int etype = *p;
9086 p ++;
9088 type = MONO_TYPE_SZARRAY;
9089 if (etype == 0x50) {
9090 tklass = mono_defaults.systemtype_class;
9091 } else if (etype == 0x55) {
9092 tklass = load_cattr_enum_type (image, p, &p, error);
9093 if (!mono_error_ok (error))
9094 return NULL;
9095 } else {
9096 if (etype == 0x51)
9097 /* See Partition II, Appendix B3 */
9098 etype = MONO_TYPE_OBJECT;
9099 simple_type.type = (MonoTypeEnum)etype;
9100 tklass = mono_class_from_mono_type (&simple_type);
9102 goto handle_enum;
9103 } else if (subt == 0x55) {
9104 char *n;
9105 MonoType *t;
9106 slen = mono_metadata_decode_value (p, &p);
9107 n = (char *)g_memdup (p, slen + 1);
9108 n [slen] = 0;
9109 t = mono_reflection_type_from_name_checked (n, image, error);
9110 if (!t) {
9111 char *msg = g_strdup (mono_error_get_message (error));
9112 mono_error_cleanup (error);
9113 /* We don't free n, it's consumed by mono_error */
9114 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute: %s", n, msg);
9115 g_free (msg);
9116 return NULL;
9118 g_free (n);
9119 p += slen;
9120 subc = mono_class_from_mono_type (t);
9121 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
9122 MonoType simple_type = {{0}};
9123 simple_type.type = (MonoTypeEnum)subt;
9124 subc = mono_class_from_mono_type (&simple_type);
9125 } else {
9126 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
9128 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
9129 obj = NULL;
9130 if (mono_error_ok (error)) {
9131 obj = mono_object_new_checked (mono_domain_get (), subc, error);
9132 g_assert (!subc->has_references);
9133 if (mono_error_ok (error))
9134 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
9137 g_free (val);
9138 return obj;
9140 case MONO_TYPE_SZARRAY: {
9141 MonoArray *arr;
9142 guint32 i, alen, basetype;
9143 alen = read32 (p);
9144 p += 4;
9145 if (alen == 0xffffffff) {
9146 *end = p;
9147 return NULL;
9149 arr = mono_array_new (mono_domain_get(), tklass, alen);
9150 basetype = tklass->byval_arg.type;
9151 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
9152 basetype = mono_class_enum_basetype (tklass)->type;
9153 switch (basetype)
9155 case MONO_TYPE_U1:
9156 case MONO_TYPE_I1:
9157 case MONO_TYPE_BOOLEAN:
9158 for (i = 0; i < alen; i++) {
9159 MonoBoolean val = *p++;
9160 mono_array_set (arr, MonoBoolean, i, val);
9162 break;
9163 case MONO_TYPE_CHAR:
9164 case MONO_TYPE_U2:
9165 case MONO_TYPE_I2:
9166 for (i = 0; i < alen; i++) {
9167 guint16 val = read16 (p);
9168 mono_array_set (arr, guint16, i, val);
9169 p += 2;
9171 break;
9172 case MONO_TYPE_R4:
9173 case MONO_TYPE_U4:
9174 case MONO_TYPE_I4:
9175 for (i = 0; i < alen; i++) {
9176 guint32 val = read32 (p);
9177 mono_array_set (arr, guint32, i, val);
9178 p += 4;
9180 break;
9181 case MONO_TYPE_R8:
9182 for (i = 0; i < alen; i++) {
9183 double val;
9184 readr8 (p, &val);
9185 mono_array_set (arr, double, i, val);
9186 p += 8;
9188 break;
9189 case MONO_TYPE_U8:
9190 case MONO_TYPE_I8:
9191 for (i = 0; i < alen; i++) {
9192 guint64 val = read64 (p);
9193 mono_array_set (arr, guint64, i, val);
9194 p += 8;
9196 break;
9197 case MONO_TYPE_CLASS:
9198 case MONO_TYPE_OBJECT:
9199 case MONO_TYPE_STRING:
9200 case MONO_TYPE_SZARRAY:
9201 for (i = 0; i < alen; i++) {
9202 MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, &p, error);
9203 if (!mono_error_ok (error))
9204 return NULL;
9205 mono_array_setref (arr, i, item);
9207 break;
9208 default:
9209 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
9211 *end=p;
9212 return arr;
9214 default:
9215 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
9217 return NULL;
9220 static MonoObject*
9221 load_cattr_value_boxed (MonoDomain *domain, MonoImage *image, MonoType *t, const char* p, const char** end, MonoError *error)
9223 mono_error_init (error);
9225 gboolean is_ref = type_is_reference (t);
9227 void *val = load_cattr_value (image, t, p, end, error);
9228 if (!is_ok (error)) {
9229 if (is_ref)
9230 g_free (val);
9231 return NULL;
9234 if (is_ref)
9235 return (MonoObject*)val;
9237 MonoObject *boxed = mono_value_box_checked (domain, mono_class_from_mono_type (t), val, error);
9238 g_free (val);
9239 return boxed;
9242 static MonoObject*
9243 create_cattr_typed_arg (MonoType *t, MonoObject *val, MonoError *error)
9245 static MonoMethod *ctor;
9246 MonoObject *retval;
9247 void *params [2], *unboxed;
9249 mono_error_init (error);
9251 if (!ctor)
9252 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_typed_argument_class (), ".ctor", 2);
9254 params [0] = mono_type_get_object_checked (mono_domain_get (), t, error);
9255 return_val_if_nok (error, NULL);
9257 params [1] = val;
9258 retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_typed_argument_class (), error);
9259 return_val_if_nok (error, NULL);
9260 unboxed = mono_object_unbox (retval);
9262 mono_runtime_invoke_checked (ctor, unboxed, params, error);
9263 return_val_if_nok (error, NULL);
9265 return retval;
9268 static MonoObject*
9269 create_cattr_named_arg (void *minfo, MonoObject *typedarg, MonoError *error)
9271 static MonoMethod *ctor;
9272 MonoObject *retval;
9273 void *unboxed, *params [2];
9275 mono_error_init (error);
9277 if (!ctor)
9278 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_named_argument_class (), ".ctor", 2);
9280 params [0] = minfo;
9281 params [1] = typedarg;
9282 retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_named_argument_class (), error);
9283 return_val_if_nok (error, NULL);
9285 unboxed = mono_object_unbox (retval);
9287 mono_runtime_invoke_checked (ctor, unboxed, params, error);
9288 return_val_if_nok (error, NULL);
9290 return retval;
9293 static gboolean
9294 type_is_reference (MonoType *type)
9296 switch (type->type) {
9297 case MONO_TYPE_BOOLEAN:
9298 case MONO_TYPE_CHAR:
9299 case MONO_TYPE_U:
9300 case MONO_TYPE_I:
9301 case MONO_TYPE_U1:
9302 case MONO_TYPE_I1:
9303 case MONO_TYPE_U2:
9304 case MONO_TYPE_I2:
9305 case MONO_TYPE_U4:
9306 case MONO_TYPE_I4:
9307 case MONO_TYPE_U8:
9308 case MONO_TYPE_I8:
9309 case MONO_TYPE_R8:
9310 case MONO_TYPE_R4:
9311 case MONO_TYPE_VALUETYPE:
9312 return FALSE;
9313 default:
9314 return TRUE;
9318 static void
9319 free_param_data (MonoMethodSignature *sig, void **params) {
9320 int i;
9321 for (i = 0; i < sig->param_count; ++i) {
9322 if (!type_is_reference (sig->params [i]))
9323 g_free (params [i]);
9328 * Find the field index in the metadata FieldDef table.
9330 static guint32
9331 find_field_index (MonoClass *klass, MonoClassField *field) {
9332 int i;
9334 for (i = 0; i < klass->field.count; ++i) {
9335 if (field == &klass->fields [i])
9336 return klass->field.first + 1 + i;
9338 return 0;
9342 * Find the property index in the metadata Property table.
9344 static guint32
9345 find_property_index (MonoClass *klass, MonoProperty *property) {
9346 int i;
9348 for (i = 0; i < klass->ext->property.count; ++i) {
9349 if (property == &klass->ext->properties [i])
9350 return klass->ext->property.first + 1 + i;
9352 return 0;
9356 * Find the event index in the metadata Event table.
9358 static guint32
9359 find_event_index (MonoClass *klass, MonoEvent *event) {
9360 int i;
9362 for (i = 0; i < klass->ext->event.count; ++i) {
9363 if (event == &klass->ext->events [i])
9364 return klass->ext->event.first + 1 + i;
9366 return 0;
9369 static MonoObject*
9370 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
9372 const char *p = (const char*)data;
9373 const char *named;
9374 guint32 i, j, num_named;
9375 MonoObject *attr;
9376 void *params_buf [32];
9377 void **params = NULL;
9378 MonoMethodSignature *sig;
9379 MonoObject *exc = NULL;
9381 mono_error_init (error);
9383 mono_class_init (method->klass);
9385 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9386 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9387 return NULL;
9390 if (len == 0) {
9391 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9392 if (!mono_error_ok (error)) return NULL;
9394 mono_runtime_invoke_checked (method, attr, NULL, error);
9395 if (!mono_error_ok (error))
9396 return NULL;
9398 return attr;
9401 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9402 return NULL;
9404 /*g_print ("got attr %s\n", method->klass->name);*/
9406 sig = mono_method_signature (method);
9407 if (sig->param_count < 32) {
9408 params = params_buf;
9409 memset (params, 0, sizeof (void*) * sig->param_count);
9410 } else {
9411 /* Allocate using GC so it gets GC tracking */
9412 params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
9415 /* skip prolog */
9416 p += 2;
9417 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9418 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9419 if (!mono_error_ok (error))
9420 goto fail;
9423 named = p;
9424 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9425 if (!mono_error_ok (error)) goto fail;
9427 mono_runtime_try_invoke (method, attr, params, &exc, error);
9428 if (!mono_error_ok (error))
9429 goto fail;
9430 if (exc)
9431 goto fail;
9433 num_named = read16 (named);
9434 named += 2;
9435 for (j = 0; j < num_named; j++) {
9436 gint name_len;
9437 char *name, named_type, data_type;
9438 named_type = *named++;
9439 data_type = *named++; /* type of data */
9440 if (data_type == MONO_TYPE_SZARRAY)
9441 data_type = *named++;
9442 if (data_type == MONO_TYPE_ENUM) {
9443 gint type_len;
9444 char *type_name;
9445 type_len = mono_metadata_decode_blob_size (named, &named);
9446 type_name = (char *)g_malloc (type_len + 1);
9447 memcpy (type_name, named, type_len);
9448 type_name [type_len] = 0;
9449 named += type_len;
9450 /* FIXME: lookup the type and check type consistency */
9451 g_free (type_name);
9453 name_len = mono_metadata_decode_blob_size (named, &named);
9454 name = (char *)g_malloc (name_len + 1);
9455 memcpy (name, named, name_len);
9456 name [name_len] = 0;
9457 named += name_len;
9458 if (named_type == 0x53) {
9459 MonoClassField *field;
9460 void *val;
9462 /* how this fail is a blackbox */
9463 field = mono_class_get_field_from_name (mono_object_class (attr), name);
9464 if (!field) {
9465 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
9466 g_free (name);
9467 goto fail;
9470 val = load_cattr_value (image, field->type, named, &named, error);
9471 if (!mono_error_ok (error)) {
9472 g_free (name);
9473 if (!type_is_reference (field->type))
9474 g_free (val);
9475 goto fail;
9478 mono_field_set_value (attr, field, val);
9479 if (!type_is_reference (field->type))
9480 g_free (val);
9481 } else if (named_type == 0x54) {
9482 MonoProperty *prop;
9483 void *pparams [1];
9484 MonoType *prop_type;
9486 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
9488 if (!prop) {
9489 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
9490 g_free (name);
9491 goto fail;
9494 if (!prop->set) {
9495 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
9496 g_free (name);
9497 goto fail;
9500 /* can we have more that 1 arg in a custom attr named property? */
9501 prop_type = prop->get? mono_method_signature (prop->get)->ret :
9502 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9504 pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
9505 if (!mono_error_ok (error)) {
9506 g_free (name);
9507 if (!type_is_reference (prop_type))
9508 g_free (pparams [0]);
9509 goto fail;
9513 mono_property_set_value (prop, attr, pparams, NULL);
9514 if (!type_is_reference (prop_type))
9515 g_free (pparams [0]);
9517 g_free (name);
9520 free_param_data (method->signature, params);
9521 if (params != params_buf)
9522 mono_gc_free_fixed (params);
9524 return attr;
9526 fail:
9527 free_param_data (method->signature, params);
9528 if (params != params_buf)
9529 mono_gc_free_fixed (params);
9530 if (exc)
9531 mono_raise_exception ((MonoException*)exc);
9532 return NULL;
9536 * mono_reflection_create_custom_attr_data_args:
9538 * Create an array of typed and named arguments from the cattr blob given by DATA.
9539 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
9540 * NAMED_ARG_INFO will contain information about the named arguments.
9542 void
9543 mono_reflection_create_custom_attr_data_args (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoArray **typed_args, MonoArray **named_args, CattrNamedArg **named_arg_info, MonoError *error)
9545 MonoArray *typedargs, *namedargs;
9546 MonoClass *attrklass;
9547 MonoDomain *domain;
9548 const char *p = (const char*)data;
9549 const char *named;
9550 guint32 i, j, num_named;
9551 CattrNamedArg *arginfo = NULL;
9553 *typed_args = NULL;
9554 *named_args = NULL;
9555 *named_arg_info = NULL;
9557 mono_error_init (error);
9559 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9560 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9561 return;
9564 mono_class_init (method->klass);
9566 domain = mono_domain_get ();
9568 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9569 return;
9571 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
9573 /* skip prolog */
9574 p += 2;
9575 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9576 MonoObject *obj;
9578 obj = load_cattr_value_boxed (domain, image, mono_method_signature (method)->params [i], p, &p, error);
9579 return_if_nok (error);
9580 mono_array_setref (typedargs, i, obj);
9583 named = p;
9584 num_named = read16 (named);
9585 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
9586 named += 2;
9587 attrklass = method->klass;
9589 arginfo = g_new0 (CattrNamedArg, num_named);
9590 *named_arg_info = arginfo;
9592 for (j = 0; j < num_named; j++) {
9593 gint name_len;
9594 char *name, named_type, data_type;
9595 named_type = *named++;
9596 data_type = *named++; /* type of data */
9597 if (data_type == MONO_TYPE_SZARRAY)
9598 data_type = *named++;
9599 if (data_type == MONO_TYPE_ENUM) {
9600 gint type_len;
9601 char *type_name;
9602 type_len = mono_metadata_decode_blob_size (named, &named);
9603 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
9604 goto fail;
9606 type_name = (char *)g_malloc (type_len + 1);
9607 memcpy (type_name, named, type_len);
9608 type_name [type_len] = 0;
9609 named += type_len;
9610 /* FIXME: lookup the type and check type consistency */
9611 g_free (type_name);
9613 name_len = mono_metadata_decode_blob_size (named, &named);
9614 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
9615 goto fail;
9616 name = (char *)g_malloc (name_len + 1);
9617 memcpy (name, named, name_len);
9618 name [name_len] = 0;
9619 named += name_len;
9620 if (named_type == 0x53) {
9621 MonoObject *obj;
9622 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
9624 if (!field) {
9625 g_free (name);
9626 goto fail;
9629 arginfo [j].type = field->type;
9630 arginfo [j].field = field;
9632 obj = load_cattr_value_boxed (domain, image, field->type, named, &named, error);
9633 if (!is_ok (error)) {
9634 g_free (name);
9635 return;
9637 mono_array_setref (namedargs, j, obj);
9639 } else if (named_type == 0x54) {
9640 MonoObject *obj;
9641 MonoType *prop_type;
9642 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
9644 if (!prop || !prop->set) {
9645 g_free (name);
9646 goto fail;
9649 prop_type = prop->get? mono_method_signature (prop->get)->ret :
9650 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9652 arginfo [j].type = prop_type;
9653 arginfo [j].prop = prop;
9655 obj = load_cattr_value_boxed (domain, image, prop_type, named, &named, error);
9656 if (!is_ok (error)) {
9657 g_free (name);
9658 return;
9660 mono_array_setref (namedargs, j, obj);
9662 g_free (name);
9665 *typed_args = typedargs;
9666 *named_args = namedargs;
9667 return;
9668 fail:
9669 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9670 g_free (arginfo);
9671 *named_arg_info = NULL;
9674 void
9675 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
9677 MonoDomain *domain;
9678 MonoArray *typedargs, *namedargs;
9679 MonoImage *image;
9680 MonoMethod *method;
9681 CattrNamedArg *arginfo = NULL;
9682 MonoError error;
9683 int i;
9685 mono_error_init (&error);
9687 *ctor_args = NULL;
9688 *named_args = NULL;
9690 if (len == 0)
9691 return;
9693 image = assembly->assembly->image;
9694 method = ref_method->method;
9695 domain = mono_object_domain (ref_method);
9697 if (!mono_class_init (method->klass))
9698 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
9700 mono_reflection_create_custom_attr_data_args (image, method, (const guchar *)data, len, &typedargs, &namedargs, &arginfo, &error);
9701 if (!mono_error_ok (&error))
9702 goto leave;
9704 if (mono_loader_get_last_error ()) {
9705 mono_error_set_from_loader_error (&error);
9706 goto leave;
9709 if (!typedargs || !namedargs)
9710 goto leave;
9712 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9713 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
9714 MonoObject *typedarg;
9716 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj, &error);
9717 if (!is_ok (&error))
9718 goto leave;
9719 mono_array_setref (typedargs, i, typedarg);
9722 for (i = 0; i < mono_array_length (namedargs); ++i) {
9723 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
9724 MonoObject *typedarg, *namedarg, *minfo;
9726 if (arginfo [i].prop) {
9727 minfo = (MonoObject*)mono_property_get_object_checked (domain, NULL, arginfo [i].prop, &error);
9728 if (!minfo)
9729 goto leave;
9730 } else {
9731 minfo = (MonoObject*)mono_field_get_object_checked (domain, NULL, arginfo [i].field, &error);
9732 if (!mono_error_ok (&error))
9733 goto leave;
9736 typedarg = create_cattr_typed_arg (arginfo [i].type, obj, &error);
9737 if (!is_ok (&error))
9738 goto leave;
9739 namedarg = create_cattr_named_arg (minfo, typedarg, &error);
9740 if (!is_ok (&error))
9741 goto leave;
9743 mono_array_setref (namedargs, i, namedarg);
9746 *ctor_args = typedargs;
9747 *named_args = namedargs;
9748 leave:
9749 g_free (arginfo);
9750 mono_error_raise_exception (&error);
9754 static MonoObject*
9755 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr, MonoError *error)
9757 static MonoMethod *ctor;
9759 MonoDomain *domain;
9760 MonoObject *attr;
9761 void *params [4];
9763 mono_error_init (error);
9765 g_assert (image->assembly);
9767 if (!ctor)
9768 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
9770 domain = mono_domain_get ();
9771 attr = mono_object_new_checked (domain, mono_defaults.customattribute_data_class, error);
9772 return_val_if_nok (error, NULL);
9773 params [0] = mono_method_get_object_checked (domain, cattr->ctor, NULL, error);
9774 return_val_if_nok (error, NULL);
9775 params [1] = mono_assembly_get_object_checked (domain, image->assembly, error);
9776 return_val_if_nok (error, NULL);
9777 params [2] = (gpointer)&cattr->data;
9778 params [3] = &cattr->data_size;
9780 mono_runtime_invoke_checked (ctor, attr, params, error);
9781 return_val_if_nok (error, NULL);
9782 return attr;
9785 static MonoArray*
9786 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
9788 MonoArray *result;
9789 MonoObject *attr;
9790 int i, n;
9792 mono_error_init (error);
9794 n = 0;
9795 for (i = 0; i < cinfo->num_attrs; ++i) {
9796 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
9797 n ++;
9800 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
9801 n = 0;
9802 for (i = 0; i < cinfo->num_attrs; ++i) {
9803 if (!cinfo->attrs [i].ctor) {
9804 /* The cattr type is not finished yet */
9805 /* We should include the type name but cinfo doesn't contain it */
9806 mono_error_set_type_load_name (error, NULL, NULL, "");
9807 return NULL;
9809 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
9810 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
9811 if (!mono_error_ok (error))
9812 return result;
9813 mono_array_setref (result, n, attr);
9814 n ++;
9817 return result;
9820 MonoArray*
9821 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
9823 MonoError error;
9824 MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
9825 mono_error_assert_ok (&error); /*FIXME proper error handling*/
9827 return result;
9830 static MonoArray*
9831 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo, MonoError *error)
9833 MonoArray *result;
9834 MonoObject *attr;
9835 int i;
9837 mono_error_init (error);
9838 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
9839 for (i = 0; i < cinfo->num_attrs; ++i) {
9840 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i], error);
9841 return_val_if_nok (error, NULL);
9842 mono_array_setref (result, i, attr);
9844 return result;
9848 * mono_custom_attrs_from_index:
9850 * Returns: NULL if no attributes are found or if a loading error occurs.
9852 MonoCustomAttrInfo*
9853 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
9855 MonoError error;
9856 MonoCustomAttrInfo *result = mono_custom_attrs_from_index_checked (image, idx, &error);
9857 mono_error_cleanup (&error); /* FIXME a better public API that doesn't swallow the error. */
9858 return result;
9861 * mono_custom_attrs_from_index_checked:
9863 * Returns: NULL if no attributes are found. On error returns NULL and sets @error.
9865 MonoCustomAttrInfo*
9866 mono_custom_attrs_from_index_checked (MonoImage *image, guint32 idx, MonoError *error)
9868 guint32 mtoken, i, len;
9869 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
9870 MonoTableInfo *ca;
9871 MonoCustomAttrInfo *ainfo;
9872 GList *tmp, *list = NULL;
9873 const char *data;
9874 MonoCustomAttrEntry* attr;
9876 mono_error_init (error);
9878 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
9880 i = mono_metadata_custom_attrs_from_index (image, idx);
9881 if (!i)
9882 return NULL;
9883 i --;
9884 while (i < ca->rows) {
9885 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
9886 break;
9887 list = g_list_prepend (list, GUINT_TO_POINTER (i));
9888 ++i;
9890 len = g_list_length (list);
9891 if (!len)
9892 return NULL;
9893 ainfo = (MonoCustomAttrInfo *)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
9894 ainfo->num_attrs = len;
9895 ainfo->image = image;
9896 for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
9897 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
9898 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
9899 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
9900 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
9901 mtoken |= MONO_TOKEN_METHOD_DEF;
9902 break;
9903 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
9904 mtoken |= MONO_TOKEN_MEMBER_REF;
9905 break;
9906 default:
9907 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
9908 break;
9910 attr = &ainfo->attrs [i - 1];
9911 attr->ctor = mono_get_method_checked (image, mtoken, NULL, NULL, error);
9912 if (!attr->ctor) {
9913 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to %s", image->name, mtoken, mono_error_get_message (error));
9914 g_list_free (list);
9915 g_free (ainfo);
9916 return NULL;
9919 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
9920 /*FIXME raising an exception here doesn't make any sense*/
9921 g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
9922 g_list_free (list);
9923 g_free (ainfo);
9924 return NULL;
9926 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
9927 attr->data_size = mono_metadata_decode_value (data, &data);
9928 attr->data = (guchar*)data;
9930 g_list_free (list);
9932 return ainfo;
9935 MonoCustomAttrInfo*
9936 mono_custom_attrs_from_method (MonoMethod *method)
9938 MonoError error;
9939 MonoCustomAttrInfo* result = mono_custom_attrs_from_method_checked (method, &error);
9940 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9941 return result;
9944 MonoCustomAttrInfo*
9945 mono_custom_attrs_from_method_checked (MonoMethod *method, MonoError *error)
9947 guint32 idx;
9949 mono_error_init (error);
9952 * An instantiated method has the same cattrs as the generic method definition.
9954 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9955 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9957 if (method->is_inflated)
9958 method = ((MonoMethodInflated *) method)->declaring;
9960 if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
9961 return lookup_custom_attr (method->klass->image, method);
9963 if (!method->token)
9964 /* Synthetic methods */
9965 return NULL;
9967 idx = mono_method_get_index (method);
9968 idx <<= MONO_CUSTOM_ATTR_BITS;
9969 idx |= MONO_CUSTOM_ATTR_METHODDEF;
9970 return mono_custom_attrs_from_index_checked (method->klass->image, idx, error);
9973 MonoCustomAttrInfo*
9974 mono_custom_attrs_from_class (MonoClass *klass)
9976 MonoError error;
9977 MonoCustomAttrInfo *result = mono_custom_attrs_from_class_checked (klass, &error);
9978 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9979 return result;
9982 MonoCustomAttrInfo*
9983 mono_custom_attrs_from_class_checked (MonoClass *klass, MonoError *error)
9985 guint32 idx;
9987 mono_error_init (error);
9989 if (klass->generic_class)
9990 klass = klass->generic_class->container_class;
9992 if (image_is_dynamic (klass->image))
9993 return lookup_custom_attr (klass->image, klass);
9995 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
9996 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
9997 idx <<= MONO_CUSTOM_ATTR_BITS;
9998 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
9999 } else {
10000 idx = mono_metadata_token_index (klass->type_token);
10001 idx <<= MONO_CUSTOM_ATTR_BITS;
10002 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
10004 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10007 MonoCustomAttrInfo*
10008 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
10010 MonoError error;
10011 MonoCustomAttrInfo *result = mono_custom_attrs_from_assembly_checked (assembly, &error);
10012 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
10013 return result;
10016 MonoCustomAttrInfo*
10017 mono_custom_attrs_from_assembly_checked (MonoAssembly *assembly, MonoError *error)
10019 guint32 idx;
10021 mono_error_init (error);
10023 if (image_is_dynamic (assembly->image))
10024 return lookup_custom_attr (assembly->image, assembly);
10025 idx = 1; /* there is only one assembly */
10026 idx <<= MONO_CUSTOM_ATTR_BITS;
10027 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
10028 return mono_custom_attrs_from_index_checked (assembly->image, idx, error);
10031 static MonoCustomAttrInfo*
10032 mono_custom_attrs_from_module (MonoImage *image, MonoError *error)
10034 guint32 idx;
10036 if (image_is_dynamic (image))
10037 return lookup_custom_attr (image, image);
10038 idx = 1; /* there is only one module */
10039 idx <<= MONO_CUSTOM_ATTR_BITS;
10040 idx |= MONO_CUSTOM_ATTR_MODULE;
10041 return mono_custom_attrs_from_index_checked (image, idx, error);
10044 MonoCustomAttrInfo*
10045 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
10047 MonoError error;
10048 MonoCustomAttrInfo * result = mono_custom_attrs_from_property_checked (klass, property, &error);
10049 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
10050 return result;
10053 MonoCustomAttrInfo*
10054 mono_custom_attrs_from_property_checked (MonoClass *klass, MonoProperty *property, MonoError *error)
10056 guint32 idx;
10058 if (image_is_dynamic (klass->image)) {
10059 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
10060 return lookup_custom_attr (klass->image, property);
10062 idx = find_property_index (klass, property);
10063 idx <<= MONO_CUSTOM_ATTR_BITS;
10064 idx |= MONO_CUSTOM_ATTR_PROPERTY;
10065 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10068 MonoCustomAttrInfo*
10069 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
10071 MonoError error;
10072 MonoCustomAttrInfo * result = mono_custom_attrs_from_event_checked (klass, event, &error);
10073 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
10074 return result;
10077 MonoCustomAttrInfo*
10078 mono_custom_attrs_from_event_checked (MonoClass *klass, MonoEvent *event, MonoError *error)
10080 guint32 idx;
10082 if (image_is_dynamic (klass->image)) {
10083 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
10084 return lookup_custom_attr (klass->image, event);
10086 idx = find_event_index (klass, event);
10087 idx <<= MONO_CUSTOM_ATTR_BITS;
10088 idx |= MONO_CUSTOM_ATTR_EVENT;
10089 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10092 MonoCustomAttrInfo*
10093 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
10095 MonoError error;
10096 MonoCustomAttrInfo * result = mono_custom_attrs_from_field_checked (klass, field, &error);
10097 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
10098 return result;
10101 MonoCustomAttrInfo*
10102 mono_custom_attrs_from_field_checked (MonoClass *klass, MonoClassField *field, MonoError *error)
10104 guint32 idx;
10105 mono_error_init (error);
10107 if (image_is_dynamic (klass->image)) {
10108 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
10109 return lookup_custom_attr (klass->image, field);
10111 idx = find_field_index (klass, field);
10112 idx <<= MONO_CUSTOM_ATTR_BITS;
10113 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
10114 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10118 * mono_custom_attrs_from_param:
10119 * @method: handle to the method that we want to retrieve custom parameter information from
10120 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
10122 * The result must be released with mono_custom_attrs_free().
10124 * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
10126 MonoCustomAttrInfo*
10127 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
10129 MonoError error;
10130 MonoCustomAttrInfo *result = mono_custom_attrs_from_param_checked (method, param, &error);
10131 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
10132 return result;
10136 * mono_custom_attrs_from_param_checked:
10137 * @method: handle to the method that we want to retrieve custom parameter information from
10138 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
10139 * @error: set on error
10141 * The result must be released with mono_custom_attrs_free().
10143 * Returns: the custom attribute object for the specified parameter, or NULL if there are none. On failure returns NULL and sets @error.
10145 MonoCustomAttrInfo*
10146 mono_custom_attrs_from_param_checked (MonoMethod *method, guint32 param, MonoError *error)
10148 MonoTableInfo *ca;
10149 guint32 i, idx, method_index;
10150 guint32 param_list, param_last, param_pos, found;
10151 MonoImage *image;
10152 MonoReflectionMethodAux *aux;
10154 mono_error_init (error);
10157 * An instantiated method has the same cattrs as the generic method definition.
10159 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
10160 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
10162 if (method->is_inflated)
10163 method = ((MonoMethodInflated *) method)->declaring;
10165 if (image_is_dynamic (method->klass->image)) {
10166 MonoCustomAttrInfo *res, *ainfo;
10167 int size;
10169 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
10170 if (!aux || !aux->param_cattr)
10171 return NULL;
10173 /* Need to copy since it will be freed later */
10174 ainfo = aux->param_cattr [param];
10175 if (!ainfo)
10176 return NULL;
10177 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
10178 res = (MonoCustomAttrInfo *)g_malloc0 (size);
10179 memcpy (res, ainfo, size);
10180 return res;
10183 image = method->klass->image;
10184 method_index = mono_method_get_index (method);
10185 if (!method_index)
10186 return NULL;
10187 ca = &image->tables [MONO_TABLE_METHOD];
10189 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
10190 if (method_index == ca->rows) {
10191 ca = &image->tables [MONO_TABLE_PARAM];
10192 param_last = ca->rows + 1;
10193 } else {
10194 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
10195 ca = &image->tables [MONO_TABLE_PARAM];
10197 found = FALSE;
10198 for (i = param_list; i < param_last; ++i) {
10199 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
10200 if (param_pos == param) {
10201 found = TRUE;
10202 break;
10205 if (!found)
10206 return NULL;
10207 idx = i;
10208 idx <<= MONO_CUSTOM_ATTR_BITS;
10209 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
10210 return mono_custom_attrs_from_index_checked (image, idx, error);
10213 gboolean
10214 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
10216 int i;
10217 MonoClass *klass;
10218 for (i = 0; i < ainfo->num_attrs; ++i) {
10219 klass = ainfo->attrs [i].ctor->klass;
10220 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
10221 return TRUE;
10223 return FALSE;
10226 MonoObject*
10227 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
10229 MonoError error;
10230 MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
10231 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
10232 return res;
10235 MonoObject*
10236 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
10238 int i, attr_index;
10239 MonoClass *klass;
10240 MonoArray *attrs;
10242 mono_error_init (error);
10244 attr_index = -1;
10245 for (i = 0; i < ainfo->num_attrs; ++i) {
10246 klass = ainfo->attrs [i].ctor->klass;
10247 if (mono_class_has_parent (klass, attr_klass)) {
10248 attr_index = i;
10249 break;
10252 if (attr_index == -1)
10253 return NULL;
10255 attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
10256 if (!mono_error_ok (error))
10257 return NULL;
10258 return mono_array_get (attrs, MonoObject*, attr_index);
10262 * mono_reflection_get_custom_attrs_info:
10263 * @obj: a reflection object handle
10265 * Return the custom attribute info for attributes defined for the
10266 * reflection handle @obj. The objects.
10268 * FIXME this function leaks like a sieve for SRE objects.
10270 MonoCustomAttrInfo*
10271 mono_reflection_get_custom_attrs_info (MonoObject *obj)
10273 MonoError error;
10274 MonoCustomAttrInfo *result = mono_reflection_get_custom_attrs_info_checked (obj, &error);
10275 mono_error_assert_ok (&error);
10276 return result;
10280 * mono_reflection_get_custom_attrs_info_checked:
10281 * @obj: a reflection object handle
10282 * @error: set on error
10284 * Return the custom attribute info for attributes defined for the
10285 * reflection handle @obj. The objects.
10287 * On failure returns NULL and sets @error.
10289 * FIXME this function leaks like a sieve for SRE objects.
10291 MonoCustomAttrInfo*
10292 mono_reflection_get_custom_attrs_info_checked (MonoObject *obj, MonoError *error)
10294 MonoClass *klass;
10295 MonoCustomAttrInfo *cinfo = NULL;
10297 mono_error_init (error);
10299 klass = obj->vtable->klass;
10300 if (klass == mono_defaults.monotype_class) {
10301 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
10302 return_val_if_nok (error, NULL);
10303 klass = mono_class_from_mono_type (type);
10304 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
10305 cinfo = mono_custom_attrs_from_class_checked (klass, error);
10306 return_val_if_nok (error, NULL);
10307 } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
10308 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
10309 cinfo = mono_custom_attrs_from_assembly_checked (rassembly->assembly, error);
10310 return_val_if_nok (error, NULL);
10311 } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
10312 MonoReflectionModule *module = (MonoReflectionModule*)obj;
10313 cinfo = mono_custom_attrs_from_module (module->image, error);
10314 return_val_if_nok (error, NULL);
10315 } else if (strcmp ("MonoProperty", klass->name) == 0) {
10316 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
10317 cinfo = mono_custom_attrs_from_property_checked (rprop->property->parent, rprop->property, error);
10318 return_val_if_nok (error, NULL);
10319 } else if (strcmp ("MonoEvent", klass->name) == 0) {
10320 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
10321 cinfo = mono_custom_attrs_from_event_checked (revent->event->parent, revent->event, error);
10322 return_val_if_nok (error, NULL);
10323 } else if (strcmp ("MonoField", klass->name) == 0) {
10324 MonoReflectionField *rfield = (MonoReflectionField*)obj;
10325 cinfo = mono_custom_attrs_from_field_checked (rfield->field->parent, rfield->field, error);
10326 return_val_if_nok (error, NULL);
10327 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
10328 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
10329 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
10330 return_val_if_nok (error, NULL);
10331 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
10332 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
10333 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
10334 return_val_if_nok (error, NULL);
10335 } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
10336 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
10337 MonoClass *member_class = mono_object_class (param->MemberImpl);
10338 if (mono_class_is_reflection_method_or_constructor (member_class)) {
10339 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
10340 cinfo = mono_custom_attrs_from_param_checked (rmethod->method, param->PositionImpl + 1, error);
10341 return_val_if_nok (error, NULL);
10342 } else if (is_sr_mono_property (member_class)) {
10343 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
10344 MonoMethod *method;
10345 if (!(method = prop->property->get))
10346 method = prop->property->set;
10347 g_assert (method);
10349 cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10350 return_val_if_nok (error, NULL);
10352 #ifndef DISABLE_REFLECTION_EMIT
10353 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
10354 MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl, error);
10355 return_val_if_nok (error, NULL);
10356 cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10357 return_val_if_nok (error, NULL);
10358 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
10359 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
10360 MonoMethod *method = NULL;
10361 if (is_sre_ctor_builder (mono_object_class (c->cb)))
10362 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
10363 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
10364 method = ((MonoReflectionMethod *)c->cb)->method;
10365 else
10366 g_error ("mono_reflection_get_custom_attrs_info:: can't handle a CTBI with base_method of type %s", mono_type_get_full_name (member_class));
10368 cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10369 return_val_if_nok (error, NULL);
10371 #endif
10372 else {
10373 char *type_name = mono_type_get_full_name (member_class);
10374 mono_error_set_not_supported (error,
10375 "Custom attributes on a ParamInfo with member %s are not supported",
10376 type_name);
10377 g_free (type_name);
10378 return NULL;
10380 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
10381 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
10382 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
10383 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
10384 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
10385 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
10386 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
10387 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
10388 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
10389 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
10390 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
10391 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
10392 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
10393 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
10394 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
10395 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
10396 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
10397 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
10398 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
10399 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
10400 cinfo = mono_reflection_get_custom_attrs_info_checked ((MonoObject*)gclass->generic_type, error);
10401 return_val_if_nok (error, NULL);
10402 } else { /* handle other types here... */
10403 g_error ("get custom attrs not yet supported for %s", klass->name);
10406 return cinfo;
10410 * mono_reflection_get_custom_attrs_by_type:
10411 * @obj: a reflection object handle
10413 * Return an array with all the custom attributes defined of the
10414 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
10415 * of that type are returned. The objects are fully build. Return NULL if a loading error
10416 * occurs.
10418 MonoArray*
10419 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
10421 MonoArray *result;
10422 MonoCustomAttrInfo *cinfo;
10424 mono_error_init (error);
10426 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10427 return_val_if_nok (error, NULL);
10428 if (cinfo) {
10429 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
10430 if (!result)
10431 return NULL;
10432 if (!cinfo->cached)
10433 mono_custom_attrs_free (cinfo);
10434 } else {
10435 mono_loader_assert_no_error ();
10436 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
10439 return result;
10443 * mono_reflection_get_custom_attrs:
10444 * @obj: a reflection object handle
10446 * Return an array with all the custom attributes defined of the
10447 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
10448 * occurs.
10450 MonoArray*
10451 mono_reflection_get_custom_attrs (MonoObject *obj)
10453 MonoError error;
10455 return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
10459 * mono_reflection_get_custom_attrs_data:
10460 * @obj: a reflection obj handle
10462 * Returns an array of System.Reflection.CustomAttributeData,
10463 * which include information about attributes reflected on
10464 * types loaded using the Reflection Only methods
10466 MonoArray*
10467 mono_reflection_get_custom_attrs_data (MonoObject *obj)
10469 MonoError error;
10470 MonoArray* result;
10471 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
10472 mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
10473 return result;
10477 * mono_reflection_get_custom_attrs_data_checked:
10478 * @obj: a reflection obj handle
10479 * @error: set on error
10481 * Returns an array of System.Reflection.CustomAttributeData,
10482 * which include information about attributes reflected on
10483 * types loaded using the Reflection Only methods
10485 MonoArray*
10486 mono_reflection_get_custom_attrs_data_checked (MonoObject *obj, MonoError *error)
10488 MonoArray *result;
10489 MonoCustomAttrInfo *cinfo;
10491 mono_error_init (error);
10493 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10494 return_val_if_nok (error, NULL);
10495 if (cinfo) {
10496 result = mono_custom_attrs_data_construct (cinfo, error);
10497 return_val_if_nok (error, NULL);
10498 if (!cinfo->cached)
10499 mono_custom_attrs_free (cinfo);
10500 } else
10501 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
10503 if (mono_loader_get_last_error ())
10504 mono_error_set_from_loader_error (error);
10506 return result;
10509 static MonoReflectionType*
10510 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error)
10512 static MonoMethod *method_get_underlying_system_type = NULL;
10513 MonoReflectionType *rt;
10514 MonoMethod *usertype_method;
10516 mono_error_init (error);
10518 if (!method_get_underlying_system_type)
10519 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
10521 usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
10523 rt = (MonoReflectionType *) mono_runtime_invoke_checked (usertype_method, t, NULL, error);
10525 return rt;
10529 static gboolean
10530 is_corlib_type (MonoClass *klass)
10532 return klass->image == mono_defaults.corlib;
10535 #define check_corlib_type_cached(_class, _namespace, _name) do { \
10536 static MonoClass *cached_class; \
10537 if (cached_class) \
10538 return cached_class == _class; \
10539 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
10540 cached_class = _class; \
10541 return TRUE; \
10543 return FALSE; \
10544 } while (0) \
10547 #ifndef DISABLE_REFLECTION_EMIT
10548 static gboolean
10549 is_sre_array (MonoClass *klass)
10551 check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
10554 static gboolean
10555 is_sre_byref (MonoClass *klass)
10557 check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
10560 static gboolean
10561 is_sre_pointer (MonoClass *klass)
10563 check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
10566 static gboolean
10567 is_sre_generic_instance (MonoClass *klass)
10569 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericClass");
10572 static gboolean
10573 is_sre_type_builder (MonoClass *klass)
10575 check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
10578 static gboolean
10579 is_sre_method_builder (MonoClass *klass)
10581 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
10584 static gboolean
10585 is_sre_ctor_builder (MonoClass *klass)
10587 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
10590 static gboolean
10591 is_sre_field_builder (MonoClass *klass)
10593 check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
10596 static gboolean
10597 is_sre_method_on_tb_inst (MonoClass *klass)
10599 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
10602 static gboolean
10603 is_sre_ctor_on_tb_inst (MonoClass *klass)
10605 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
10608 MonoType*
10609 mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
10611 MonoClass *klass;
10612 mono_error_init (error);
10614 if (!ref)
10615 return NULL;
10616 if (ref->type)
10617 return ref->type;
10619 if (is_usertype (ref)) {
10620 ref = mono_reflection_type_get_underlying_system_type (ref, error);
10621 if (ref == NULL || is_usertype (ref) || !is_ok (error))
10622 return NULL;
10623 if (ref->type)
10624 return ref->type;
10627 klass = mono_object_class (ref);
10629 if (is_sre_array (klass)) {
10630 MonoType *res;
10631 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
10632 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type, error);
10633 return_val_if_nok (error, NULL);
10634 g_assert (base);
10635 if (sre_array->rank == 0) //single dimentional array
10636 res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
10637 else
10638 res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
10639 sre_array->type.type = res;
10640 return res;
10641 } else if (is_sre_byref (klass)) {
10642 MonoType *res;
10643 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
10644 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type, error);
10645 return_val_if_nok (error, NULL);
10646 g_assert (base);
10647 res = &mono_class_from_mono_type (base)->this_arg;
10648 sre_byref->type.type = res;
10649 return res;
10650 } else if (is_sre_pointer (klass)) {
10651 MonoType *res;
10652 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
10653 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type, error);
10654 return_val_if_nok (error, NULL);
10655 g_assert (base);
10656 res = &mono_ptr_class_get (base)->byval_arg;
10657 sre_pointer->type.type = res;
10658 return res;
10659 } else if (is_sre_generic_instance (klass)) {
10660 MonoType *res, **types;
10661 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
10662 int i, count;
10664 count = mono_array_length (gclass->type_arguments);
10665 types = g_new0 (MonoType*, count);
10666 for (i = 0; i < count; ++i) {
10667 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (gclass->type_arguments, gpointer, i);
10668 types [i] = mono_reflection_type_get_handle (t, error);
10669 if (!types[i] || !is_ok (error)) {
10670 g_free (types);
10671 return NULL;
10675 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types, error);
10676 g_free (types);
10677 g_assert (res);
10678 gclass->type.type = res;
10679 return res;
10682 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
10683 return NULL;
10686 void
10687 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
10689 MonoError error;
10690 mono_reflection_type_get_handle (type, &error);
10691 mono_error_set_pending_exception (&error);
10694 static gboolean
10695 reflection_register_with_runtime (MonoReflectionType *type, MonoError *error)
10697 MonoDomain *domain = mono_object_domain ((MonoObject*)type);
10698 MonoClass *klass;
10700 mono_error_init (error);
10702 MonoType *res = mono_reflection_type_get_handle (type, error);
10704 if (!res && is_ok (error)) {
10705 mono_error_set_argument (error, NULL, "Invalid generic instantiation, one or more arguments are not proper user types");
10707 return_val_if_nok (error, FALSE);
10709 klass = mono_class_from_mono_type (res);
10711 mono_loader_lock (); /*same locking as mono_type_get_object_checked */
10712 mono_domain_lock (domain);
10714 if (!image_is_dynamic (klass->image)) {
10715 mono_class_setup_supertypes (klass);
10716 } else {
10717 if (!domain->type_hash)
10718 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
10719 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
10720 mono_g_hash_table_insert (domain->type_hash, res, type);
10722 mono_domain_unlock (domain);
10723 mono_loader_unlock ();
10725 return TRUE;
10728 void
10729 mono_reflection_register_with_runtime (MonoReflectionType *type)
10731 MonoError error;
10732 (void) reflection_register_with_runtime (type, &error);
10733 mono_error_set_pending_exception (&error);
10737 * LOCKING: Assumes the loader lock is held.
10739 static MonoMethodSignature*
10740 parameters_to_signature (MonoImage *image, MonoArray *parameters, MonoError *error) {
10741 MonoMethodSignature *sig;
10742 int count, i;
10744 mono_error_init (error);
10746 count = parameters? mono_array_length (parameters): 0;
10748 sig = (MonoMethodSignature *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
10749 sig->param_count = count;
10750 sig->sentinelpos = -1; /* FIXME */
10751 for (i = 0; i < count; ++i) {
10752 sig->params [i] = mono_type_array_get_and_resolve (parameters, i, error);
10753 if (!is_ok (error)) {
10754 image_g_free (image, sig);
10755 return NULL;
10758 return sig;
10762 * LOCKING: Assumes the loader lock is held.
10764 static MonoMethodSignature*
10765 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor, MonoError *error) {
10766 MonoMethodSignature *sig;
10768 mono_error_init (error);
10770 sig = parameters_to_signature (image, ctor->parameters, error);
10771 return_val_if_nok (error, NULL);
10772 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10773 sig->ret = &mono_defaults.void_class->byval_arg;
10774 return sig;
10778 * LOCKING: Assumes the loader lock is held.
10780 static MonoMethodSignature*
10781 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method, MonoError *error) {
10782 MonoMethodSignature *sig;
10784 mono_error_init (error);
10786 sig = parameters_to_signature (image, method->parameters, error);
10787 return_val_if_nok (error, NULL);
10788 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10789 if (method->rtype) {
10790 sig->ret = mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype, error);
10791 if (!is_ok (error)) {
10792 image_g_free (image, sig);
10793 return NULL;
10795 } else {
10796 sig->ret = &mono_defaults.void_class->byval_arg;
10798 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
10799 return sig;
10802 static MonoMethodSignature*
10803 dynamic_method_to_signature (MonoReflectionDynamicMethod *method, MonoError *error) {
10804 MonoMethodSignature *sig;
10806 mono_error_init (error);
10808 sig = parameters_to_signature (NULL, method->parameters, error);
10809 return_val_if_nok (error, NULL);
10810 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10811 if (method->rtype) {
10812 sig->ret = mono_reflection_type_get_handle (method->rtype, error);
10813 if (!is_ok (error)) {
10814 g_free (sig);
10815 return NULL;
10817 } else {
10818 sig->ret = &mono_defaults.void_class->byval_arg;
10820 sig->generic_param_count = 0;
10821 return sig;
10824 static void
10825 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type, MonoError *error)
10827 mono_error_init (error);
10828 MonoClass *klass = mono_object_class (prop);
10829 if (strcmp (klass->name, "PropertyBuilder") == 0) {
10830 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
10831 *name = mono_string_to_utf8 (pb->name);
10832 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type, error);
10833 } else {
10834 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
10835 *name = g_strdup (p->property->name);
10836 if (p->property->get)
10837 *type = mono_method_signature (p->property->get)->ret;
10838 else
10839 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
10843 static void
10844 get_field_name_and_type (MonoObject *field, char **name, MonoType **type, MonoError *error)
10846 mono_error_init (error);
10847 MonoClass *klass = mono_object_class (field);
10848 if (strcmp (klass->name, "FieldBuilder") == 0) {
10849 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
10850 *name = mono_string_to_utf8 (fb->name);
10851 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
10852 } else {
10853 MonoReflectionField *f = (MonoReflectionField *)field;
10854 *name = g_strdup (mono_field_get_name (f->field));
10855 *type = f->field->type;
10859 #else /* DISABLE_REFLECTION_EMIT */
10861 void
10862 mono_reflection_register_with_runtime (MonoReflectionType *type)
10864 /* This is empty */
10867 static gboolean
10868 is_sre_type_builder (MonoClass *klass)
10870 return FALSE;
10873 static gboolean
10874 is_sre_generic_instance (MonoClass *klass)
10876 return FALSE;
10879 static void
10880 init_type_builder_generics (MonoObject *type)
10884 #endif /* !DISABLE_REFLECTION_EMIT */
10887 static gboolean
10888 is_sr_mono_field (MonoClass *klass)
10890 check_corlib_type_cached (klass, "System.Reflection", "MonoField");
10893 static gboolean
10894 is_sr_mono_property (MonoClass *klass)
10896 check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
10899 static gboolean
10900 is_sr_mono_method (MonoClass *klass)
10902 check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
10905 static gboolean
10906 is_sr_mono_cmethod (MonoClass *klass)
10908 check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
10911 static gboolean
10912 is_sr_mono_generic_method (MonoClass *klass)
10914 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericMethod");
10917 static gboolean
10918 is_sr_mono_generic_cmethod (MonoClass *klass)
10920 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericCMethod");
10923 gboolean
10924 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
10926 return is_sr_mono_method (klass) || is_sr_mono_cmethod (klass) || is_sr_mono_generic_method (klass) || is_sr_mono_generic_cmethod (klass);
10929 static gboolean
10930 is_usertype (MonoReflectionType *ref)
10932 MonoClass *klass = mono_object_class (ref);
10933 return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0;
10936 static MonoReflectionType*
10937 mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error)
10939 mono_error_init (error);
10940 if (!type || type->type)
10941 return type;
10943 if (is_usertype (type)) {
10944 type = mono_reflection_type_get_underlying_system_type (type, error);
10945 return_val_if_nok (error, NULL);
10946 if (is_usertype (type)) {
10947 mono_error_set_not_supported (error, "User defined subclasses of System.Type are not yet supported22");
10948 return NULL;
10952 return type;
10955 * encode_cattr_value:
10956 * Encode a value in a custom attribute stream of bytes.
10957 * The value to encode is either supplied as an object in argument val
10958 * (valuetypes are boxed), or as a pointer to the data in the
10959 * argument argval.
10960 * @type represents the type of the value
10961 * @buffer is the start of the buffer
10962 * @p the current position in the buffer
10963 * @buflen contains the size of the buffer and is used to return the new buffer size
10964 * if this needs to be realloced.
10965 * @retbuffer and @retp return the start and the position of the buffer
10966 * @error set on error.
10968 static void
10969 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval, MonoError *error)
10971 MonoTypeEnum simple_type;
10973 mono_error_init (error);
10974 if ((p-buffer) + 10 >= *buflen) {
10975 char *newbuf;
10976 *buflen *= 2;
10977 newbuf = (char *)g_realloc (buffer, *buflen);
10978 p = newbuf + (p-buffer);
10979 buffer = newbuf;
10981 if (!argval)
10982 argval = ((char*)arg + sizeof (MonoObject));
10983 simple_type = type->type;
10984 handle_enum:
10985 switch (simple_type) {
10986 case MONO_TYPE_BOOLEAN:
10987 case MONO_TYPE_U1:
10988 case MONO_TYPE_I1:
10989 *p++ = *argval;
10990 break;
10991 case MONO_TYPE_CHAR:
10992 case MONO_TYPE_U2:
10993 case MONO_TYPE_I2:
10994 swap_with_size (p, argval, 2, 1);
10995 p += 2;
10996 break;
10997 case MONO_TYPE_U4:
10998 case MONO_TYPE_I4:
10999 case MONO_TYPE_R4:
11000 swap_with_size (p, argval, 4, 1);
11001 p += 4;
11002 break;
11003 case MONO_TYPE_R8:
11004 swap_with_size (p, argval, 8, 1);
11005 p += 8;
11006 break;
11007 case MONO_TYPE_U8:
11008 case MONO_TYPE_I8:
11009 swap_with_size (p, argval, 8, 1);
11010 p += 8;
11011 break;
11012 case MONO_TYPE_VALUETYPE:
11013 if (type->data.klass->enumtype) {
11014 simple_type = mono_class_enum_basetype (type->data.klass)->type;
11015 goto handle_enum;
11016 } else {
11017 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
11019 break;
11020 case MONO_TYPE_STRING: {
11021 char *str;
11022 guint32 slen;
11023 if (!arg) {
11024 *p++ = 0xFF;
11025 break;
11027 str = mono_string_to_utf8 ((MonoString*)arg);
11028 slen = strlen (str);
11029 if ((p-buffer) + 10 + slen >= *buflen) {
11030 char *newbuf;
11031 *buflen *= 2;
11032 *buflen += slen;
11033 newbuf = (char *)g_realloc (buffer, *buflen);
11034 p = newbuf + (p-buffer);
11035 buffer = newbuf;
11037 mono_metadata_encode_value (slen, p, &p);
11038 memcpy (p, str, slen);
11039 p += slen;
11040 g_free (str);
11041 break;
11043 case MONO_TYPE_CLASS: {
11044 char *str;
11045 guint32 slen;
11046 MonoType *arg_type;
11047 if (!arg) {
11048 *p++ = 0xFF;
11049 break;
11051 handle_type:
11052 arg_type = mono_reflection_type_get_handle ((MonoReflectionType*)arg, error);
11053 return_if_nok (error);
11055 str = type_get_qualified_name (arg_type, NULL);
11056 slen = strlen (str);
11057 if ((p-buffer) + 10 + slen >= *buflen) {
11058 char *newbuf;
11059 *buflen *= 2;
11060 *buflen += slen;
11061 newbuf = (char *)g_realloc (buffer, *buflen);
11062 p = newbuf + (p-buffer);
11063 buffer = newbuf;
11065 mono_metadata_encode_value (slen, p, &p);
11066 memcpy (p, str, slen);
11067 p += slen;
11068 g_free (str);
11069 break;
11071 case MONO_TYPE_SZARRAY: {
11072 int len, i;
11073 MonoClass *eclass, *arg_eclass;
11075 if (!arg) {
11076 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
11077 break;
11079 len = mono_array_length ((MonoArray*)arg);
11080 *p++ = len & 0xff;
11081 *p++ = (len >> 8) & 0xff;
11082 *p++ = (len >> 16) & 0xff;
11083 *p++ = (len >> 24) & 0xff;
11084 *retp = p;
11085 *retbuffer = buffer;
11086 eclass = type->data.klass;
11087 arg_eclass = mono_object_class (arg)->element_class;
11089 if (!eclass) {
11090 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
11091 eclass = mono_defaults.object_class;
11093 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
11094 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
11095 int elsize = mono_class_array_element_size (arg_eclass);
11096 for (i = 0; i < len; ++i) {
11097 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr, error);
11098 return_if_nok (error);
11099 elptr += elsize;
11101 } else if (eclass->valuetype && arg_eclass->valuetype) {
11102 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
11103 int elsize = mono_class_array_element_size (eclass);
11104 for (i = 0; i < len; ++i) {
11105 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr, error);
11106 return_if_nok (error);
11107 elptr += elsize;
11109 } else {
11110 for (i = 0; i < len; ++i) {
11111 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL, error);
11112 return_if_nok (error);
11115 break;
11117 case MONO_TYPE_OBJECT: {
11118 MonoClass *klass;
11119 char *str;
11120 guint32 slen;
11123 * The parameter type is 'object' but the type of the actual
11124 * argument is not. So we have to add type information to the blob
11125 * too. This is completely undocumented in the spec.
11128 if (arg == NULL) {
11129 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
11130 *p++ = 0xFF;
11131 break;
11134 klass = mono_object_class (arg);
11136 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
11137 *p++ = 0x50;
11138 goto handle_type;
11139 } else if (klass->enumtype) {
11140 *p++ = 0x55;
11141 } else if (klass == mono_defaults.string_class) {
11142 simple_type = MONO_TYPE_STRING;
11143 *p++ = 0x0E;
11144 goto handle_enum;
11145 } else if (klass->rank == 1) {
11146 *p++ = 0x1D;
11147 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
11148 /* See Partition II, Appendix B3 */
11149 *p++ = 0x51;
11150 else
11151 *p++ = klass->element_class->byval_arg.type;
11152 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL, error);
11153 return_if_nok (error);
11154 break;
11155 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
11156 *p++ = simple_type = klass->byval_arg.type;
11157 goto handle_enum;
11158 } else {
11159 g_error ("unhandled type in custom attr");
11161 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
11162 slen = strlen (str);
11163 if ((p-buffer) + 10 + slen >= *buflen) {
11164 char *newbuf;
11165 *buflen *= 2;
11166 *buflen += slen;
11167 newbuf = (char *)g_realloc (buffer, *buflen);
11168 p = newbuf + (p-buffer);
11169 buffer = newbuf;
11171 mono_metadata_encode_value (slen, p, &p);
11172 memcpy (p, str, slen);
11173 p += slen;
11174 g_free (str);
11175 simple_type = mono_class_enum_basetype (klass)->type;
11176 goto handle_enum;
11178 default:
11179 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
11181 *retp = p;
11182 *retbuffer = buffer;
11185 static void
11186 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
11188 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
11189 char *str = type_get_qualified_name (type, NULL);
11190 int slen = strlen (str);
11192 *p++ = 0x55;
11194 * This seems to be optional...
11195 * *p++ = 0x80;
11197 mono_metadata_encode_value (slen, p, &p);
11198 memcpy (p, str, slen);
11199 p += slen;
11200 g_free (str);
11201 } else if (type->type == MONO_TYPE_OBJECT) {
11202 *p++ = 0x51;
11203 } else if (type->type == MONO_TYPE_CLASS) {
11204 /* it should be a type: encode_cattr_value () has the check */
11205 *p++ = 0x50;
11206 } else {
11207 mono_metadata_encode_value (type->type, p, &p);
11208 if (type->type == MONO_TYPE_SZARRAY)
11209 /* See the examples in Partition VI, Annex B */
11210 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
11213 *retp = p;
11216 #ifndef DISABLE_REFLECTION_EMIT
11217 static void
11218 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value, MonoError *error)
11220 int len;
11222 mono_error_init (error);
11224 /* Preallocate a large enough buffer */
11225 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
11226 char *str = type_get_qualified_name (type, NULL);
11227 len = strlen (str);
11228 g_free (str);
11229 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
11230 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
11231 len = strlen (str);
11232 g_free (str);
11233 } else {
11234 len = 0;
11236 len += strlen (name);
11238 if ((p-buffer) + 20 + len >= *buflen) {
11239 char *newbuf;
11240 *buflen *= 2;
11241 *buflen += len;
11242 newbuf = (char *)g_realloc (buffer, *buflen);
11243 p = newbuf + (p-buffer);
11244 buffer = newbuf;
11247 encode_field_or_prop_type (type, p, &p);
11249 len = strlen (name);
11250 mono_metadata_encode_value (len, p, &p);
11251 memcpy (p, name, len);
11252 p += len;
11253 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL, error);
11254 return_if_nok (error);
11255 *retp = p;
11256 *retbuffer = buffer;
11260 * mono_reflection_get_custom_attrs_blob:
11261 * @ctor: custom attribute constructor
11262 * @ctorArgs: arguments o the constructor
11263 * @properties:
11264 * @propValues:
11265 * @fields:
11266 * @fieldValues:
11268 * Creates the blob of data that needs to be saved in the metadata and that represents
11269 * the custom attributed described by @ctor, @ctorArgs etc.
11270 * Returns: a Byte array representing the blob of data.
11272 MonoArray*
11273 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
11275 MonoError error;
11276 MonoArray *result = mono_reflection_get_custom_attrs_blob_checked (assembly, ctor, ctorArgs, properties, propValues, fields, fieldValues, &error);
11277 mono_error_cleanup (&error); /* FIXME better API that doesn't swallow the error */
11278 return result;
11282 * mono_reflection_get_custom_attrs_blob_checked:
11283 * @ctor: custom attribute constructor
11284 * @ctorArgs: arguments o the constructor
11285 * @properties:
11286 * @propValues:
11287 * @fields:
11288 * @fieldValues:
11289 * @error: set on error
11291 * Creates the blob of data that needs to be saved in the metadata and that represents
11292 * the custom attributed described by @ctor, @ctorArgs etc.
11293 * Returns: a Byte array representing the blob of data. On failure returns NULL and sets @error.
11295 MonoArray*
11296 mono_reflection_get_custom_attrs_blob_checked (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues, MonoError *error)
11298 MonoArray *result = NULL;
11299 MonoMethodSignature *sig;
11300 MonoObject *arg;
11301 char *buffer, *p;
11302 guint32 buflen, i;
11304 mono_error_init (error);
11306 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
11307 /* sig is freed later so allocate it in the heap */
11308 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor, error);
11309 if (!is_ok (error)) {
11310 g_free (sig);
11311 return NULL;
11313 } else {
11314 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
11317 g_assert (mono_array_length (ctorArgs) == sig->param_count);
11318 buflen = 256;
11319 p = buffer = (char *)g_malloc (buflen);
11320 /* write the prolog */
11321 *p++ = 1;
11322 *p++ = 0;
11323 for (i = 0; i < sig->param_count; ++i) {
11324 arg = mono_array_get (ctorArgs, MonoObject*, i);
11325 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL, error);
11326 if (!is_ok (error)) goto leave;
11328 i = 0;
11329 if (properties)
11330 i += mono_array_length (properties);
11331 if (fields)
11332 i += mono_array_length (fields);
11333 *p++ = i & 0xff;
11334 *p++ = (i >> 8) & 0xff;
11335 if (properties) {
11336 MonoObject *prop;
11337 for (i = 0; i < mono_array_length (properties); ++i) {
11338 MonoType *ptype;
11339 char *pname;
11341 prop = (MonoObject *)mono_array_get (properties, gpointer, i);
11342 get_prop_name_and_type (prop, &pname, &ptype, error);
11343 if (!is_ok (error)) goto leave;
11344 *p++ = 0x54; /* PROPERTY signature */
11345 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i), error);
11346 g_free (pname);
11347 if (!is_ok (error)) goto leave;
11351 if (fields) {
11352 MonoObject *field;
11353 for (i = 0; i < mono_array_length (fields); ++i) {
11354 MonoType *ftype;
11355 char *fname;
11357 field = (MonoObject *)mono_array_get (fields, gpointer, i);
11358 get_field_name_and_type (field, &fname, &ftype, error);
11359 if (!is_ok (error)) goto leave;
11360 *p++ = 0x53; /* FIELD signature */
11361 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i), error);
11362 g_free (fname);
11363 if (!is_ok (error)) goto leave;
11367 g_assert (p - buffer <= buflen);
11368 buflen = p - buffer;
11369 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11370 p = mono_array_addr (result, char, 0);
11371 memcpy (p, buffer, buflen);
11372 leave:
11373 g_free (buffer);
11374 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
11375 g_free (sig);
11376 return result;
11380 * reflection_setup_internal_class:
11381 * @tb: a TypeBuilder object
11382 * @error: set on error
11384 * Creates a MonoClass that represents the TypeBuilder.
11385 * This is a trick that lets us simplify a lot of reflection code
11386 * (and will allow us to support Build and Run assemblies easier).
11388 * Returns TRUE on success. On failure, returns FALSE and sets @error.
11390 static gboolean
11391 reflection_setup_internal_class (MonoReflectionTypeBuilder *tb, MonoError *error)
11393 MonoClass *klass, *parent;
11395 mono_error_init (error);
11396 RESOLVE_TYPE (tb->parent, error);
11397 return_val_if_nok (error, FALSE);
11399 mono_loader_lock ();
11401 if (tb->parent) {
11402 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
11403 if (!is_ok (error)) {
11404 mono_loader_unlock ();
11405 return FALSE;
11407 /* check so we can compile corlib correctly */
11408 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
11409 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
11410 parent = parent_type->data.klass;
11411 } else {
11412 parent = mono_class_from_mono_type (parent_type);
11414 } else {
11415 parent = NULL;
11418 /* the type has already being created: it means we just have to change the parent */
11419 if (tb->type.type) {
11420 klass = mono_class_from_mono_type (tb->type.type);
11421 klass->parent = NULL;
11422 /* fool mono_class_setup_parent */
11423 klass->supertypes = NULL;
11424 mono_class_setup_parent (klass, parent);
11425 mono_class_setup_mono_type (klass);
11426 mono_loader_unlock ();
11427 return TRUE;
11430 klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
11432 klass->image = &tb->module->dynamic_image->image;
11434 klass->inited = 1; /* we lie to the runtime */
11435 klass->name = mono_string_to_utf8_image (klass->image, tb->name, error);
11436 if (!is_ok (error))
11437 goto failure;
11438 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, error);
11439 if (!is_ok (error))
11440 goto failure;
11441 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
11442 klass->flags = tb->attrs;
11444 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
11446 klass->element_class = klass;
11448 if (mono_class_get_ref_info (klass) == NULL) {
11450 mono_class_set_ref_info (klass, tb);
11452 /* Put into cache so mono_class_get_checked () will find it.
11453 Skip nested types as those should not be available on the global scope. */
11454 if (!tb->nesting_type)
11455 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
11458 We must register all types as we cannot rely on the name_cache hashtable since we find the class
11459 by performing a mono_class_get which does the full resolution.
11461 Working around this semantics would require us to write a lot of code for no clear advantage.
11463 mono_image_append_class_to_reflection_info_set (klass);
11464 } else {
11465 g_assert (mono_class_get_ref_info (klass) == tb);
11468 register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
11470 if (parent != NULL) {
11471 mono_class_setup_parent (klass, parent);
11472 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
11473 const char *old_n = klass->name;
11474 /* trick to get relative numbering right when compiling corlib */
11475 klass->name = "BuildingObject";
11476 mono_class_setup_parent (klass, mono_defaults.object_class);
11477 klass->name = old_n;
11480 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
11481 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
11482 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
11483 klass->instance_size = sizeof (MonoObject);
11484 klass->size_inited = 1;
11485 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11488 mono_class_setup_mono_type (klass);
11490 mono_class_setup_supertypes (klass);
11493 * FIXME: handle interfaces.
11496 tb->type.type = &klass->byval_arg;
11498 if (tb->nesting_type) {
11499 g_assert (tb->nesting_type->type);
11500 MonoType *nesting_type = mono_reflection_type_get_handle (tb->nesting_type, error);
11501 if (!is_ok (error)) goto failure;
11502 klass->nested_in = mono_class_from_mono_type (nesting_type);
11505 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
11507 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
11509 mono_loader_unlock ();
11510 return TRUE;
11512 failure:
11513 mono_loader_unlock ();
11514 return FALSE;
11518 * mono_reflection_setup_internal_class:
11519 * @tb: a TypeBuilder object
11521 * (icall)
11522 * Creates a MonoClass that represents the TypeBuilder.
11523 * This is a trick that lets us simplify a lot of reflection code
11524 * (and will allow us to support Build and Run assemblies easier).
11527 void
11528 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
11530 MonoError error;
11531 (void) reflection_setup_internal_class (tb, &error);
11532 mono_error_set_pending_exception (&error);
11536 * mono_reflection_setup_generic_class:
11537 * @tb: a TypeBuilder object
11539 * Setup the generic class before adding the first generic parameter.
11541 void
11542 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11547 * mono_reflection_create_generic_class:
11548 * @tb: a TypeBuilder object
11550 * Creates the generic class after all generic parameters have been added.
11552 void
11553 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
11555 MonoError error;
11556 MonoClass *klass;
11557 int count, i;
11559 klass = mono_class_from_mono_type (tb->type.type);
11561 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
11563 if (klass->generic_container || (count == 0))
11564 return;
11566 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
11568 klass->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11570 klass->generic_container->owner.klass = klass;
11571 klass->generic_container->type_argc = count;
11572 klass->generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
11574 klass->is_generic = 1;
11576 for (i = 0; i < count; i++) {
11577 MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)mono_array_get (tb->generic_params, gpointer, i);
11578 MonoType *param_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, &error);
11579 mono_error_raise_exception (&error); /* FIXME don't raise here */
11580 MonoGenericParamFull *param = (MonoGenericParamFull *) param_type->data.generic_param;
11581 klass->generic_container->type_params [i] = *param;
11582 /*Make sure we are a diferent type instance */
11583 klass->generic_container->type_params [i].param.owner = klass->generic_container;
11584 klass->generic_container->type_params [i].info.pklass = NULL;
11585 klass->generic_container->type_params [i].info.flags = gparam->attrs;
11587 g_assert (klass->generic_container->type_params [i].param.owner);
11590 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
11594 * reflection_create_internal_class:
11595 * @tb: a TypeBuilder object
11596 * @error: set on error
11598 * Actually create the MonoClass that is associated with the TypeBuilder.
11599 * On success returns TRUE, on failure returns FALSE and sets @error.
11602 static gboolean
11603 reflection_create_internal_class (MonoReflectionTypeBuilder *tb, MonoError *error)
11606 MonoClass *klass;
11608 mono_error_init (error);
11609 klass = mono_class_from_mono_type (tb->type.type);
11611 mono_loader_lock ();
11612 if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
11613 MonoReflectionFieldBuilder *fb;
11614 MonoClass *ec;
11615 MonoType *enum_basetype;
11617 g_assert (tb->fields != NULL);
11618 g_assert (mono_array_length (tb->fields) >= 1);
11620 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
11622 MonoType *field_type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
11623 if (!is_ok (error)) {
11624 mono_loader_unlock ();
11625 return FALSE;
11627 if (!mono_type_is_valid_enum_basetype (field_type)) {
11628 mono_loader_unlock ();
11629 return TRUE;
11632 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
11633 if (!is_ok (error)) {
11634 mono_loader_unlock ();
11635 return FALSE;
11637 klass->element_class = mono_class_from_mono_type (enum_basetype);
11638 if (!klass->element_class)
11639 klass->element_class = mono_class_from_mono_type (enum_basetype);
11642 * get the element_class from the current corlib.
11644 ec = default_class_from_mono_type (enum_basetype);
11645 klass->instance_size = ec->instance_size;
11646 klass->size_inited = 1;
11648 * this is almost safe to do with enums and it's needed to be able
11649 * to create objects of the enum type (for use in SetConstant).
11651 /* FIXME: Does this mean enums can't have method overrides ? */
11652 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11654 mono_loader_unlock ();
11655 return TRUE;
11659 * mono_reflection_create_internal_class:
11660 * @tb: a TypeBuilder object
11662 * (icall)
11663 * Actually create the MonoClass that is associated with the TypeBuilder.
11665 void
11666 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11668 MonoError error;
11669 (void) reflection_create_internal_class (tb, &error);
11670 mono_error_set_pending_exception (&error);
11673 static MonoMarshalSpec*
11674 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
11675 MonoReflectionMarshal *minfo, MonoError *error)
11677 MonoMarshalSpec *res;
11679 mono_error_init (error);
11681 res = image_g_new0 (image, MonoMarshalSpec, 1);
11682 res->native = (MonoMarshalNative)minfo->type;
11684 switch (minfo->type) {
11685 case MONO_NATIVE_LPARRAY:
11686 res->data.array_data.elem_type = (MonoMarshalNative)minfo->eltype;
11687 if (minfo->has_size) {
11688 res->data.array_data.param_num = minfo->param_num;
11689 res->data.array_data.num_elem = minfo->count;
11690 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
11692 else {
11693 res->data.array_data.param_num = -1;
11694 res->data.array_data.num_elem = -1;
11695 res->data.array_data.elem_mult = -1;
11697 break;
11699 case MONO_NATIVE_BYVALTSTR:
11700 case MONO_NATIVE_BYVALARRAY:
11701 res->data.array_data.num_elem = minfo->count;
11702 break;
11704 case MONO_NATIVE_CUSTOM:
11705 if (minfo->marshaltyperef) {
11706 MonoType *marshaltyperef = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, error);
11707 if (!is_ok (error)) {
11708 image_g_free (image, res);
11709 return NULL;
11711 res->data.custom_data.custom_name =
11712 type_get_fully_qualified_name (marshaltyperef);
11714 if (minfo->mcookie)
11715 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
11716 break;
11718 default:
11719 break;
11722 return res;
11724 #endif /* !DISABLE_REFLECTION_EMIT */
11726 MonoReflectionMarshalAsAttribute*
11727 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
11728 MonoMarshalSpec *spec, MonoError *error)
11730 MonoReflectionType *rt;
11731 MonoReflectionMarshalAsAttribute *minfo;
11732 MonoType *mtype;
11734 mono_error_init (error);
11736 minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new_checked (domain, mono_class_get_marshal_as_attribute_class (), error);
11737 if (!minfo)
11738 return NULL;
11739 minfo->utype = spec->native;
11741 switch (minfo->utype) {
11742 case MONO_NATIVE_LPARRAY:
11743 minfo->array_subtype = spec->data.array_data.elem_type;
11744 minfo->size_const = spec->data.array_data.num_elem;
11745 if (spec->data.array_data.param_num != -1)
11746 minfo->size_param_index = spec->data.array_data.param_num;
11747 break;
11749 case MONO_NATIVE_BYVALTSTR:
11750 case MONO_NATIVE_BYVALARRAY:
11751 minfo->size_const = spec->data.array_data.num_elem;
11752 break;
11754 case MONO_NATIVE_CUSTOM:
11755 if (spec->data.custom_data.custom_name) {
11756 mtype = mono_reflection_type_from_name_checked (spec->data.custom_data.custom_name, klass->image, error);
11757 return_val_if_nok (error, NULL);
11759 if (mtype) {
11760 rt = mono_type_get_object_checked (domain, mtype, error);
11761 if (!rt)
11762 return NULL;
11764 MONO_OBJECT_SETREF (minfo, marshal_type_ref, rt);
11767 MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
11769 if (spec->data.custom_data.cookie)
11770 MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
11771 break;
11773 default:
11774 break;
11777 return minfo;
11780 #ifndef DISABLE_REFLECTION_EMIT
11781 static MonoMethod*
11782 reflection_methodbuilder_to_mono_method (MonoClass *klass,
11783 ReflectionMethodBuilder *rmb,
11784 MonoMethodSignature *sig)
11786 MonoError error;
11787 MonoMethod *m;
11788 MonoMethodWrapper *wrapperm;
11789 MonoMarshalSpec **specs;
11790 MonoReflectionMethodAux *method_aux;
11791 MonoImage *image;
11792 gboolean dynamic;
11793 int i;
11795 mono_error_init (&error);
11797 * Methods created using a MethodBuilder should have their memory allocated
11798 * inside the image mempool, while dynamic methods should have their memory
11799 * malloc'd.
11801 dynamic = rmb->refs != NULL;
11802 image = dynamic ? NULL : klass->image;
11804 if (!dynamic)
11805 g_assert (!klass->generic_class);
11807 mono_loader_lock ();
11809 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
11810 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
11811 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
11812 else
11813 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
11815 wrapperm = (MonoMethodWrapper*)m;
11817 m->dynamic = dynamic;
11818 m->slot = -1;
11819 m->flags = rmb->attrs;
11820 m->iflags = rmb->iattrs;
11821 m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
11822 m->klass = klass;
11823 m->signature = sig;
11824 m->sre_method = TRUE;
11825 m->skip_visibility = rmb->skip_visibility;
11826 if (rmb->table_idx)
11827 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
11829 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
11830 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
11831 m->string_ctor = 1;
11833 m->signature->pinvoke = 1;
11834 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
11835 m->signature->pinvoke = 1;
11837 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11839 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
11840 g_assert (mono_error_ok (&error));
11841 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
11842 g_assert (mono_error_ok (&error));
11844 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
11846 if (image_is_dynamic (klass->image))
11847 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11849 mono_loader_unlock ();
11851 return m;
11852 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
11853 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
11854 MonoMethodHeader *header;
11855 guint32 code_size;
11856 gint32 max_stack, i;
11857 gint32 num_locals = 0;
11858 gint32 num_clauses = 0;
11859 guint8 *code;
11861 if (rmb->ilgen) {
11862 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
11863 code_size = rmb->ilgen->code_len;
11864 max_stack = rmb->ilgen->max_stack;
11865 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
11866 if (rmb->ilgen->ex_handlers)
11867 num_clauses = method_count_clauses (rmb->ilgen);
11868 } else {
11869 if (rmb->code) {
11870 code = mono_array_addr (rmb->code, guint8, 0);
11871 code_size = mono_array_length (rmb->code);
11872 /* we probably need to run a verifier on the code... */
11873 max_stack = 8;
11875 else {
11876 code = NULL;
11877 code_size = 0;
11878 max_stack = 8;
11882 header = (MonoMethodHeader *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
11883 header->code_size = code_size;
11884 header->code = (const unsigned char *)image_g_malloc (image, code_size);
11885 memcpy ((char*)header->code, code, code_size);
11886 header->max_stack = max_stack;
11887 header->init_locals = rmb->init_locals;
11888 header->num_locals = num_locals;
11890 for (i = 0; i < num_locals; ++i) {
11891 MonoReflectionLocalBuilder *lb =
11892 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
11894 header->locals [i] = image_g_new0 (image, MonoType, 1);
11895 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)lb->type, &error);
11896 mono_error_assert_ok (&error);
11897 memcpy (header->locals [i], type, MONO_SIZEOF_TYPE);
11900 header->num_clauses = num_clauses;
11901 if (num_clauses) {
11902 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
11903 rmb->ilgen, num_clauses, &error);
11904 mono_error_assert_ok (&error);
11907 wrapperm->header = header;
11910 if (rmb->generic_params) {
11911 int count = mono_array_length (rmb->generic_params);
11912 MonoGenericContainer *container = rmb->generic_container;
11914 g_assert (container);
11916 container->type_argc = count;
11917 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
11918 container->owner.method = m;
11919 container->is_anonymous = FALSE; // Method is now known, container is no longer anonymous
11921 m->is_generic = TRUE;
11922 mono_method_set_generic_container (m, container);
11924 for (i = 0; i < count; i++) {
11925 MonoReflectionGenericParam *gp =
11926 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
11927 MonoType *gp_type = mono_reflection_type_get_handle ((MonoReflectionType*)gp, &error);
11928 mono_error_assert_ok (&error);
11929 MonoGenericParamFull *param = (MonoGenericParamFull *) gp_type->data.generic_param;
11930 container->type_params [i] = *param;
11934 * The method signature might have pointers to generic parameters that belong to other methods.
11935 * This is a valid SRE case, but the resulting method signature must be encoded using the proper
11936 * generic parameters.
11938 for (i = 0; i < m->signature->param_count; ++i) {
11939 MonoType *t = m->signature->params [i];
11940 if (t->type == MONO_TYPE_MVAR) {
11941 MonoGenericParam *gparam = t->data.generic_param;
11942 if (gparam->num < count) {
11943 m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
11944 m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
11950 if (klass->generic_container) {
11951 container->parent = klass->generic_container;
11952 container->context.class_inst = klass->generic_container->context.class_inst;
11954 container->context.method_inst = mono_get_shared_generic_inst (container);
11957 if (rmb->refs) {
11958 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
11959 int i;
11960 void **data;
11962 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
11964 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
11965 data [0] = GUINT_TO_POINTER (rmb->nrefs);
11966 for (i = 0; i < rmb->nrefs; ++i)
11967 data [i + 1] = rmb->refs [i];
11970 method_aux = NULL;
11972 /* Parameter info */
11973 if (rmb->pinfo) {
11974 if (!method_aux)
11975 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11976 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
11977 for (i = 0; i <= m->signature->param_count; ++i) {
11978 MonoReflectionParamBuilder *pb;
11979 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11980 if ((i > 0) && (pb->attrs)) {
11981 /* Make a copy since it might point to a shared type structure */
11982 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
11983 m->signature->params [i - 1]->attrs = pb->attrs;
11986 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
11987 MonoDynamicImage *assembly;
11988 guint32 idx, len;
11989 MonoTypeEnum def_type;
11990 char *p;
11991 const char *p2;
11993 if (!method_aux->param_defaults) {
11994 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
11995 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
11997 assembly = (MonoDynamicImage*)klass->image;
11998 idx = encode_constant (assembly, pb->def_value, &def_type);
11999 /* Copy the data from the blob since it might get realloc-ed */
12000 p = assembly->blob.data + idx;
12001 len = mono_metadata_decode_blob_size (p, &p2);
12002 len += p2 - p;
12003 method_aux->param_defaults [i] = (uint8_t *)image_g_malloc (image, len);
12004 method_aux->param_default_types [i] = def_type;
12005 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
12008 if (pb->name) {
12009 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
12010 g_assert (mono_error_ok (&error));
12012 if (pb->cattrs) {
12013 if (!method_aux->param_cattr)
12014 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
12015 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
12021 /* Parameter marshalling */
12022 specs = NULL;
12023 if (rmb->pinfo)
12024 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
12025 MonoReflectionParamBuilder *pb;
12026 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
12027 if (pb->marshal_info) {
12028 if (specs == NULL)
12029 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
12030 specs [pb->position] =
12031 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info, &error);
12032 if (!is_ok (&error)) {
12033 mono_loader_unlock ();
12034 image_g_free (image, specs);
12035 mono_error_raise_exception (&error); /* FIXME don't raise here */
12040 if (specs != NULL) {
12041 if (!method_aux)
12042 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
12043 method_aux->param_marshall = specs;
12046 if (image_is_dynamic (klass->image) && method_aux)
12047 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
12049 mono_loader_unlock ();
12051 return m;
12054 static MonoMethod*
12055 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb, MonoError *error)
12057 ReflectionMethodBuilder rmb;
12058 MonoMethodSignature *sig;
12060 mono_loader_lock ();
12061 g_assert (klass->image != NULL);
12062 sig = ctor_builder_to_signature (klass->image, mb, error);
12063 mono_loader_unlock ();
12064 return_val_if_nok (error, NULL);
12066 if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
12067 return NULL;
12069 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
12070 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
12072 /* If we are in a generic class, we might be called multiple times from inflate_method */
12073 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
12074 /* ilgen is no longer needed */
12075 mb->ilgen = NULL;
12078 return mb->mhandle;
12081 static MonoMethod*
12082 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb, MonoError *error)
12084 ReflectionMethodBuilder rmb;
12085 MonoMethodSignature *sig;
12087 mono_error_init (error);
12089 mono_loader_lock ();
12090 g_assert (klass->image != NULL);
12091 sig = method_builder_to_signature (klass->image, mb, error);
12092 mono_loader_unlock ();
12093 return_val_if_nok (error, NULL);
12095 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
12096 return NULL;
12098 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
12099 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
12101 /* If we are in a generic class, we might be called multiple times from inflate_method */
12102 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
12103 /* ilgen is no longer needed */
12104 mb->ilgen = NULL;
12106 return mb->mhandle;
12109 static MonoClassField*
12110 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb, MonoError *error)
12112 MonoClassField *field;
12113 MonoType *custom;
12115 mono_error_init (error);
12117 field = g_new0 (MonoClassField, 1);
12119 field->name = mono_string_to_utf8_image (klass->image, fb->name, error);
12120 mono_error_assert_ok (error);
12121 if (fb->attrs || fb->modreq || fb->modopt) {
12122 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12123 if (!is_ok (error)) {
12124 g_free (field);
12125 return NULL;
12127 field->type = mono_metadata_type_dup (NULL, type);
12128 field->type->attrs = fb->attrs;
12130 g_assert (image_is_dynamic (klass->image));
12131 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt, error);
12132 g_free (field->type);
12133 if (!is_ok (error)) {
12134 g_free (field);
12135 return NULL;
12137 field->type = mono_metadata_type_dup (klass->image, custom);
12138 g_free (custom);
12139 } else {
12140 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12141 if (!is_ok (error)) {
12142 g_free (field);
12143 return NULL;
12146 if (fb->offset != -1)
12147 field->offset = fb->offset;
12148 field->parent = klass;
12149 mono_save_custom_attrs (klass->image, field, fb->cattrs);
12151 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
12153 return field;
12155 #endif
12158 * mono_reflection_bind_generic_parameters:
12159 * @type: a managed type object (which should be some kind of generic (instance? definition?))
12160 * @type_args: the number of type arguments to bind
12161 * @types: array of type arguments
12162 * @error: set on error
12164 * Given a managed type object for a generic type instance, binds each of its arguments to the specified types.
12165 * Returns the MonoType* for the resulting type instantiation. On failure returns NULL and sets @error.
12167 MonoType*
12168 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types, MonoError *error)
12170 MonoClass *klass;
12171 MonoReflectionTypeBuilder *tb = NULL;
12172 gboolean is_dynamic = FALSE;
12173 MonoClass *geninst;
12175 mono_error_init (error);
12177 mono_loader_lock ();
12179 if (is_sre_type_builder (mono_object_class (type))) {
12180 tb = (MonoReflectionTypeBuilder *) type;
12182 is_dynamic = TRUE;
12183 } else if (is_sre_generic_instance (mono_object_class (type))) {
12184 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
12185 MonoReflectionType *gtd = rgi->generic_type;
12187 if (is_sre_type_builder (mono_object_class (gtd))) {
12188 tb = (MonoReflectionTypeBuilder *)gtd;
12189 is_dynamic = TRUE;
12193 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
12194 if (tb && tb->generic_container)
12195 mono_reflection_create_generic_class (tb);
12197 MonoType *t = mono_reflection_type_get_handle (type, error);
12198 if (!is_ok (error)) {
12199 mono_loader_unlock ();
12200 return NULL;
12203 klass = mono_class_from_mono_type (t);
12204 if (!klass->generic_container) {
12205 mono_loader_unlock ();
12206 mono_error_set_type_load_class (error, klass, "Cannot bind generic parameters of a non-generic type");
12207 return NULL;
12210 if (klass->wastypebuilder) {
12211 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
12213 is_dynamic = TRUE;
12216 mono_loader_unlock ();
12218 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
12220 return &geninst->byval_arg;
12223 MonoClass*
12224 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
12226 MonoGenericClass *gclass;
12227 MonoGenericInst *inst;
12229 g_assert (klass->generic_container);
12231 inst = mono_metadata_get_generic_inst (type_argc, types);
12232 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
12234 return mono_generic_class_get_class (gclass);
12237 MonoReflectionMethod*
12238 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
12240 MonoError error;
12241 MonoClass *klass;
12242 MonoMethod *method, *inflated;
12243 MonoMethodInflated *imethod;
12244 MonoGenericContext tmp_context;
12245 MonoGenericInst *ginst;
12246 MonoType **type_argv;
12247 int count, i;
12249 /*FIXME but this no longer should happen*/
12250 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
12251 #ifndef DISABLE_REFLECTION_EMIT
12252 MonoReflectionMethodBuilder *mb = NULL;
12253 MonoType *tb;
12254 MonoClass *klass;
12256 mb = (MonoReflectionMethodBuilder *) rmethod;
12257 tb = mono_reflection_type_get_handle ((MonoReflectionType*)mb->type, &error);
12258 mono_error_raise_exception (&error); /* FIXME don't raise here */
12259 klass = mono_class_from_mono_type (tb);
12261 method = methodbuilder_to_mono_method (klass, mb, &error);
12262 if (!method)
12263 mono_error_raise_exception (&error); /* FIXME don't raise here */
12264 #else
12265 g_assert_not_reached ();
12266 method = NULL;
12267 #endif
12268 } else {
12269 method = rmethod->method;
12272 klass = method->klass;
12274 if (method->is_inflated)
12275 method = ((MonoMethodInflated *) method)->declaring;
12277 count = mono_method_signature (method)->generic_param_count;
12278 if (count != mono_array_length (types))
12279 return NULL;
12281 type_argv = g_new0 (MonoType *, count);
12282 for (i = 0; i < count; i++) {
12283 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (types, gpointer, i);
12284 type_argv [i] = mono_reflection_type_get_handle (garg, &error);
12285 if (!is_ok (&error)) {
12286 g_free (type_argv);
12287 mono_error_raise_exception (&error); /* FIXME don't raise here */
12290 ginst = mono_metadata_get_generic_inst (count, type_argv);
12291 g_free (type_argv);
12293 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
12294 tmp_context.method_inst = ginst;
12296 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
12297 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12298 imethod = (MonoMethodInflated *) inflated;
12300 /*FIXME but I think this is no longer necessary*/
12301 if (image_is_dynamic (method->klass->image)) {
12302 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
12304 * This table maps metadata structures representing inflated methods/fields
12305 * to the reflection objects representing their generic definitions.
12307 mono_image_lock ((MonoImage*)image);
12308 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
12309 mono_image_unlock ((MonoImage*)image);
12312 if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
12313 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
12315 MonoReflectionMethod *ret = mono_method_get_object_checked (mono_object_domain (rmethod), inflated, NULL, &error);
12316 mono_error_raise_exception (&error); /* FIXME don't raise here */
12317 return ret;
12320 #ifndef DISABLE_REFLECTION_EMIT
12322 static MonoMethod *
12323 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
12325 MonoMethodInflated *imethod;
12326 MonoGenericContext *context;
12327 int i;
12330 * With generic code sharing the klass might not be inflated.
12331 * This can happen because classes inflated with their own
12332 * type arguments are "normalized" to the uninflated class.
12334 if (!klass->generic_class)
12335 return method;
12337 context = mono_class_get_context (klass);
12339 if (klass->method.count && klass->methods) {
12340 /* Find the already created inflated method */
12341 for (i = 0; i < klass->method.count; ++i) {
12342 g_assert (klass->methods [i]->is_inflated);
12343 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
12344 break;
12346 g_assert (i < klass->method.count);
12347 imethod = (MonoMethodInflated*)klass->methods [i];
12348 } else {
12349 MonoError error;
12350 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
12351 mono_error_assert_ok (&error);
12354 if (method->is_generic && image_is_dynamic (method->klass->image)) {
12355 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
12357 mono_image_lock ((MonoImage*)image);
12358 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
12359 mono_image_unlock ((MonoImage*)image);
12361 return (MonoMethod *) imethod;
12364 static MonoMethod *
12365 inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error)
12367 MonoMethod *method;
12368 MonoClass *gklass;
12370 mono_error_init (error);
12372 MonoClass *type_class = mono_object_class (type);
12374 if (is_sre_generic_instance (type_class)) {
12375 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
12376 MonoType *generic_type = mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type, error);
12377 return_val_if_nok (error, NULL);
12378 gklass = mono_class_from_mono_type (generic_type);
12379 } else if (is_sre_type_builder (type_class)) {
12380 MonoType *t = mono_reflection_type_get_handle (type, error);
12381 return_val_if_nok (error, NULL);
12382 gklass = mono_class_from_mono_type (t);
12383 } else if (type->type) {
12384 gklass = mono_class_from_mono_type (type->type);
12385 gklass = mono_class_get_generic_type_definition (gklass);
12386 } else {
12387 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
12390 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
12391 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
12392 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
12393 else {
12394 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj, error);
12395 if (!method)
12396 return NULL;
12398 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder")) {
12399 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj, error);
12400 if (!method)
12401 return NULL;
12402 } else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
12403 method = ((MonoReflectionMethod *) obj)->method;
12404 else {
12405 method = NULL; /* prevent compiler warning */
12406 g_error ("can't handle type %s", obj->vtable->klass->name);
12409 MonoType *t = mono_reflection_type_get_handle (type, error);
12410 return_val_if_nok (error, NULL);
12411 return inflate_mono_method (mono_class_from_mono_type (t), method, obj);
12414 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
12415 static gboolean
12416 reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields, MonoError *error)
12418 MonoGenericClass *gclass;
12419 MonoDynamicGenericClass *dgclass;
12420 MonoClass *klass, *gklass;
12421 MonoType *gtype;
12422 int i;
12424 mono_error_init (error);
12426 gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type, error);
12427 return_val_if_nok (error, FALSE);
12428 klass = mono_class_from_mono_type (gtype);
12429 g_assert (gtype->type == MONO_TYPE_GENERICINST);
12430 gclass = gtype->data.generic_class;
12432 if (!gclass->is_dynamic)
12433 return TRUE;
12435 dgclass = (MonoDynamicGenericClass *) gclass;
12437 if (dgclass->initialized)
12438 return TRUE;
12440 gklass = gclass->container_class;
12441 mono_class_init (gklass);
12443 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
12445 dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
12446 dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
12447 dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
12449 for (i = 0; i < dgclass->count_fields; i++) {
12450 MonoObject *obj = (MonoObject *)mono_array_get (fields, gpointer, i);
12451 MonoClassField *field, *inflated_field = NULL;
12453 if (!strcmp (obj->vtable->klass->name, "FieldBuilder")) {
12454 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj, error);
12455 return_val_if_nok (error, FALSE);
12456 } else if (!strcmp (obj->vtable->klass->name, "MonoField"))
12457 field = ((MonoReflectionField *) obj)->field;
12458 else {
12459 field = NULL; /* prevent compiler warning */
12460 g_assert_not_reached ();
12463 dgclass->fields [i] = *field;
12464 dgclass->fields [i].parent = klass;
12465 dgclass->fields [i].type = mono_class_inflate_generic_type_checked (
12466 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass), error);
12467 mono_error_assert_ok (error); /* FIXME don't swallow the error */
12468 dgclass->field_generic_types [i] = field->type;
12469 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
12470 dgclass->field_objects [i] = obj;
12472 if (inflated_field) {
12473 g_free (inflated_field);
12474 } else {
12475 dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
12479 dgclass->initialized = TRUE;
12480 return TRUE;
12483 void
12484 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12486 MonoError error;
12487 (void) reflection_generic_class_initialize (type, fields, &error);
12488 mono_error_set_pending_exception (&error);
12491 void
12492 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12494 MonoDynamicGenericClass *dgclass;
12495 int i;
12497 g_assert (gclass->is_dynamic);
12499 dgclass = (MonoDynamicGenericClass *)gclass;
12501 for (i = 0; i < dgclass->count_fields; ++i) {
12502 MonoClassField *field = dgclass->fields + i;
12503 mono_metadata_free_type (field->type);
12504 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
12509 * fix_partial_generic_class:
12510 * @klass: a generic instantiation MonoClass
12511 * @error: set on error
12513 * Assumes that the generic container of @klass has its vtable
12514 * initialized, and updates the parent class, insterfaces, methods and
12515 * fields of @klass by inflating the types using the generic context.
12517 * On success returns TRUE, on failure returns FALSE and sets @error.
12520 static gboolean
12521 fix_partial_generic_class (MonoClass *klass, MonoError *error)
12523 MonoClass *gklass = klass->generic_class->container_class;
12524 MonoDynamicGenericClass *dgclass;
12525 int i;
12527 mono_error_init (error);
12529 if (klass->wastypebuilder)
12530 return TRUE;
12532 dgclass = (MonoDynamicGenericClass *) klass->generic_class;
12533 if (klass->parent != gklass->parent) {
12534 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, error);
12535 if (mono_error_ok (error)) {
12536 MonoClass *parent = mono_class_from_mono_type (parent_type);
12537 mono_metadata_free_type (parent_type);
12538 if (parent != klass->parent) {
12539 /*fool mono_class_setup_parent*/
12540 klass->supertypes = NULL;
12541 mono_class_setup_parent (klass, parent);
12543 } else {
12544 if (gklass->wastypebuilder)
12545 klass->wastypebuilder = TRUE;
12546 return FALSE;
12550 if (!dgclass->initialized)
12551 return TRUE;
12553 if (klass->method.count != gklass->method.count) {
12554 klass->method.count = gklass->method.count;
12555 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
12557 for (i = 0; i < klass->method.count; i++) {
12558 klass->methods [i] = mono_class_inflate_generic_method_full_checked (
12559 gklass->methods [i], klass, mono_class_get_context (klass), error);
12560 mono_error_assert_ok (error);
12564 if (klass->interface_count && klass->interface_count != gklass->interface_count) {
12565 klass->interface_count = gklass->interface_count;
12566 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
12567 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12569 for (i = 0; i < gklass->interface_count; ++i) {
12570 MonoType *iface_type = mono_class_inflate_generic_type_checked (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass), error);
12571 return_val_if_nok (error, FALSE);
12573 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
12574 mono_metadata_free_type (iface_type);
12576 if (!ensure_runtime_vtable (klass->interfaces [i], error))
12577 return FALSE;
12579 klass->interfaces_inited = 1;
12582 if (klass->field.count != gklass->field.count) {
12583 klass->field.count = gklass->field.count;
12584 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
12586 for (i = 0; i < klass->field.count; i++) {
12587 klass->fields [i] = gklass->fields [i];
12588 klass->fields [i].parent = klass;
12589 klass->fields [i].type = mono_class_inflate_generic_type_checked (gklass->fields [i].type, mono_class_get_context (klass), error);
12590 return_val_if_nok (error, FALSE);
12594 /*We can only finish with this klass once it's parent has as well*/
12595 if (gklass->wastypebuilder)
12596 klass->wastypebuilder = TRUE;
12597 return TRUE;
12601 * ensure_generic_class_runtime_vtable:
12602 * @klass a generic class
12603 * @error set on error
12605 * Ensures that the generic container of @klass has a vtable and
12606 * returns TRUE on success. On error returns FALSE and sets @error.
12608 static gboolean
12609 ensure_generic_class_runtime_vtable (MonoClass *klass, MonoError *error)
12611 MonoClass *gklass = klass->generic_class->container_class;
12613 mono_error_init (error);
12615 if (!ensure_runtime_vtable (gklass, error))
12616 return FALSE;
12618 return fix_partial_generic_class (klass, error);
12622 * ensure_runtime_vtable:
12623 * @klass the class
12624 * @error set on error
12626 * Ensures that @klass has a vtable and returns TRUE on success. On
12627 * error returns FALSE and sets @error.
12629 static gboolean
12630 ensure_runtime_vtable (MonoClass *klass, MonoError *error)
12632 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12633 int i, num, j;
12635 mono_error_init (error);
12637 if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
12638 return TRUE;
12639 if (klass->parent)
12640 if (!ensure_runtime_vtable (klass->parent, error))
12641 return FALSE;
12643 if (tb) {
12644 num = tb->ctors? mono_array_length (tb->ctors): 0;
12645 num += tb->num_methods;
12646 klass->method.count = num;
12647 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
12648 num = tb->ctors? mono_array_length (tb->ctors): 0;
12649 for (i = 0; i < num; ++i) {
12650 MonoMethod *ctor = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), error);
12651 if (!ctor)
12652 return FALSE;
12653 klass->methods [i] = ctor;
12655 num = tb->num_methods;
12656 j = i;
12657 for (i = 0; i < num; ++i) {
12658 MonoMethod *meth = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), error);
12659 if (!meth)
12660 return FALSE;
12661 klass->methods [j++] = meth;
12664 if (tb->interfaces) {
12665 klass->interface_count = mono_array_length (tb->interfaces);
12666 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
12667 for (i = 0; i < klass->interface_count; ++i) {
12668 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i, error);
12669 return_val_if_nok (error, FALSE);
12670 klass->interfaces [i] = mono_class_from_mono_type (iface);
12671 if (!ensure_runtime_vtable (klass->interfaces [i], error))
12672 return FALSE;
12674 klass->interfaces_inited = 1;
12676 } else if (klass->generic_class){
12677 if (!ensure_generic_class_runtime_vtable (klass, error)) {
12678 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12679 return FALSE;
12683 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
12684 int slot_num = 0;
12685 for (i = 0; i < klass->method.count; ++i) {
12686 MonoMethod *im = klass->methods [i];
12687 if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
12688 im->slot = slot_num++;
12691 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12692 mono_class_setup_interface_offsets (klass);
12693 mono_class_setup_interface_id (klass);
12697 * The generic vtable is needed even if image->run is not set since some
12698 * runtime code like ves_icall_Type_GetMethodsByName depends on
12699 * method->slot being defined.
12703 * tb->methods could not be freed since it is used for determining
12704 * overrides during dynamic vtable construction.
12707 return TRUE;
12710 static MonoMethod*
12711 mono_reflection_method_get_handle (MonoObject *method, MonoError *error)
12713 mono_error_init (error);
12714 MonoClass *klass = mono_object_class (method);
12715 if (is_sr_mono_method (klass) || is_sr_mono_generic_method (klass)) {
12716 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
12717 return sr_method->method;
12719 if (is_sre_method_builder (klass)) {
12720 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
12721 return mb->mhandle;
12723 if (is_sre_method_on_tb_inst (klass)) {
12724 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
12725 MonoMethod *result;
12726 /*FIXME move this to a proper method and unify with resolve_object*/
12727 if (m->method_args) {
12728 result = mono_reflection_method_on_tb_inst_get_handle (m, error);
12729 } else {
12730 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
12731 return_val_if_nok (error, NULL);
12732 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12733 MonoMethod *mono_method;
12735 if (is_sre_method_builder (mono_object_class (m->mb)))
12736 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12737 else if (is_sr_mono_method (mono_object_class (m->mb)))
12738 mono_method = ((MonoReflectionMethod *)m->mb)->method;
12739 else
12740 g_error ("resolve_object:: can't handle a MTBI with base_method of type %s", mono_type_get_full_name (mono_object_class (m->mb)));
12742 result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
12744 return result;
12747 g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
12748 return NULL;
12751 void
12752 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides, MonoError *error)
12754 MonoReflectionTypeBuilder *tb;
12755 int i, j, onum;
12756 MonoReflectionMethod *m;
12758 mono_error_init (error);
12759 *overrides = NULL;
12760 *num_overrides = 0;
12762 g_assert (image_is_dynamic (klass->image));
12764 if (!mono_class_get_ref_info (klass))
12765 return;
12767 g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
12769 tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
12771 onum = 0;
12772 if (tb->methods) {
12773 for (i = 0; i < tb->num_methods; ++i) {
12774 MonoReflectionMethodBuilder *mb =
12775 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12776 if (mb->override_methods)
12777 onum += mono_array_length (mb->override_methods);
12781 if (onum) {
12782 *overrides = g_new0 (MonoMethod*, onum * 2);
12784 onum = 0;
12785 for (i = 0; i < tb->num_methods; ++i) {
12786 MonoReflectionMethodBuilder *mb =
12787 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12788 if (mb->override_methods) {
12789 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
12790 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
12792 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m, error);
12793 return_if_nok (error);
12794 (*overrides) [onum * 2 + 1] = mb->mhandle;
12796 g_assert (mb->mhandle);
12798 onum ++;
12804 *num_overrides = onum;
12807 static void
12808 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
12810 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12811 MonoReflectionFieldBuilder *fb;
12812 MonoClassField *field;
12813 MonoImage *image = klass->image;
12814 const char *p, *p2;
12815 int i;
12816 guint32 len, idx, real_size = 0;
12818 klass->field.count = tb->num_fields;
12819 klass->field.first = 0;
12821 mono_error_init (error);
12823 if (tb->class_size) {
12824 if ((tb->packing_size & 0xffffff00) != 0) {
12825 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
12826 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
12827 return;
12829 klass->packing_size = tb->packing_size;
12830 real_size = klass->instance_size + tb->class_size;
12833 if (!klass->field.count) {
12834 klass->instance_size = MAX (klass->instance_size, real_size);
12835 return;
12838 klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
12839 mono_class_alloc_ext (klass);
12840 klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
12842 This is, guess what, a hack.
12843 The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
12844 On the static path no field class is resolved, only types are built. This is the right thing to do
12845 but we suck.
12846 Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
12848 klass->size_inited = 1;
12850 for (i = 0; i < klass->field.count; ++i) {
12851 MonoArray *rva_data;
12852 fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
12853 field = &klass->fields [i];
12854 field->name = mono_string_to_utf8_image (image, fb->name, error);
12855 if (!mono_error_ok (error))
12856 return;
12857 if (fb->attrs) {
12858 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12859 return_if_nok (error);
12860 field->type = mono_metadata_type_dup (klass->image, type);
12861 field->type->attrs = fb->attrs;
12862 } else {
12863 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12864 return_if_nok (error);
12867 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
12868 char *base = mono_array_addr (rva_data, char, 0);
12869 size_t size = mono_array_length (rva_data);
12870 char *data = (char *)mono_image_alloc (klass->image, size);
12871 memcpy (data, base, size);
12872 klass->ext->field_def_values [i].data = data;
12874 if (fb->offset != -1)
12875 field->offset = fb->offset;
12876 field->parent = klass;
12877 fb->handle = field;
12878 mono_save_custom_attrs (klass->image, field, fb->cattrs);
12880 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
12881 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
12883 if (fb->def_value) {
12884 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12885 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
12886 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
12887 /* Copy the data from the blob since it might get realloc-ed */
12888 p = assembly->blob.data + idx;
12889 len = mono_metadata_decode_blob_size (p, &p2);
12890 len += p2 - p;
12891 klass->ext->field_def_values [i].data = (const char *)mono_image_alloc (image, len);
12892 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
12896 klass->instance_size = MAX (klass->instance_size, real_size);
12897 mono_class_layout_fields (klass);
12900 static void
12901 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
12903 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12904 MonoReflectionPropertyBuilder *pb;
12905 MonoImage *image = klass->image;
12906 MonoProperty *properties;
12907 int i;
12909 mono_error_init (error);
12911 if (!klass->ext)
12912 klass->ext = image_g_new0 (image, MonoClassExt, 1);
12914 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
12915 klass->ext->property.first = 0;
12917 properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
12918 klass->ext->properties = properties;
12919 for (i = 0; i < klass->ext->property.count; ++i) {
12920 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
12921 properties [i].parent = klass;
12922 properties [i].attrs = pb->attrs;
12923 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
12924 if (!mono_error_ok (error))
12925 return;
12926 if (pb->get_method)
12927 properties [i].get = pb->get_method->mhandle;
12928 if (pb->set_method)
12929 properties [i].set = pb->set_method->mhandle;
12931 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
12932 if (pb->def_value) {
12933 guint32 len, idx;
12934 const char *p, *p2;
12935 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12936 if (!klass->ext->prop_def_values)
12937 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
12938 properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
12939 idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
12940 /* Copy the data from the blob since it might get realloc-ed */
12941 p = assembly->blob.data + idx;
12942 len = mono_metadata_decode_blob_size (p, &p2);
12943 len += p2 - p;
12944 klass->ext->prop_def_values [i].data = (const char *)mono_image_alloc (image, len);
12945 memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
12950 static MonoReflectionEvent *
12951 reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb, MonoError *error)
12953 mono_error_init (error);
12955 MonoEvent *event = g_new0 (MonoEvent, 1);
12956 MonoClass *klass;
12958 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
12959 if (!is_ok (error)) {
12960 g_free (event);
12961 return NULL;
12963 klass = mono_class_from_mono_type (type);
12965 event->parent = klass;
12966 event->attrs = eb->attrs;
12967 event->name = mono_string_to_utf8 (eb->name);
12968 if (eb->add_method)
12969 event->add = eb->add_method->mhandle;
12970 if (eb->remove_method)
12971 event->remove = eb->remove_method->mhandle;
12972 if (eb->raise_method)
12973 event->raise = eb->raise_method->mhandle;
12975 #ifndef MONO_SMALL_CONFIG
12976 if (eb->other_methods) {
12977 int j;
12978 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
12979 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
12980 MonoReflectionMethodBuilder *mb =
12981 mono_array_get (eb->other_methods,
12982 MonoReflectionMethodBuilder*, j);
12983 event->other [j] = mb->mhandle;
12986 #endif
12988 MonoReflectionEvent *ev_obj = mono_event_get_object_checked (mono_object_domain (tb), klass, event, error);
12989 if (!is_ok (error)) {
12990 #ifndef MONO_SMALL_CONFIG
12991 g_free (event->other);
12992 #endif
12993 g_free (event);
12994 return NULL;
12996 return ev_obj;
12999 MonoReflectionEvent *
13000 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
13002 MonoError error;
13003 MonoReflectionEvent *result = reflection_event_builder_get_event_info (tb, eb, &error);
13004 mono_error_set_pending_exception (&error);
13005 return result;
13008 static void
13009 typebuilder_setup_events (MonoClass *klass, MonoError *error)
13011 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
13012 MonoReflectionEventBuilder *eb;
13013 MonoImage *image = klass->image;
13014 MonoEvent *events;
13015 int i;
13017 mono_error_init (error);
13019 if (!klass->ext)
13020 klass->ext = image_g_new0 (image, MonoClassExt, 1);
13022 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
13023 klass->ext->event.first = 0;
13025 events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
13026 klass->ext->events = events;
13027 for (i = 0; i < klass->ext->event.count; ++i) {
13028 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
13029 events [i].parent = klass;
13030 events [i].attrs = eb->attrs;
13031 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
13032 if (!mono_error_ok (error))
13033 return;
13034 if (eb->add_method)
13035 events [i].add = eb->add_method->mhandle;
13036 if (eb->remove_method)
13037 events [i].remove = eb->remove_method->mhandle;
13038 if (eb->raise_method)
13039 events [i].raise = eb->raise_method->mhandle;
13041 #ifndef MONO_SMALL_CONFIG
13042 if (eb->other_methods) {
13043 int j;
13044 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
13045 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
13046 MonoReflectionMethodBuilder *mb =
13047 mono_array_get (eb->other_methods,
13048 MonoReflectionMethodBuilder*, j);
13049 events [i].other [j] = mb->mhandle;
13052 #endif
13053 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
13057 struct remove_instantiations_user_data
13059 MonoClass *klass;
13060 MonoError *error;
13063 static gboolean
13064 remove_instantiations_of_and_ensure_contents (gpointer key,
13065 gpointer value,
13066 gpointer user_data)
13068 struct remove_instantiations_user_data *data = (struct remove_instantiations_user_data*)user_data;
13069 MonoType *type = (MonoType*)key;
13070 MonoClass *klass = data->klass;
13071 gboolean already_failed = !is_ok (data->error);
13072 MonoError lerror;
13073 MonoError *error = already_failed ? &lerror : data->error;
13075 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
13076 MonoClass *inst_klass = mono_class_from_mono_type (type);
13077 //Ensure it's safe to use it.
13078 if (!fix_partial_generic_class (inst_klass, error)) {
13079 mono_class_set_failure (inst_klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
13080 // Marked the class with failure, but since some other instantiation already failed,
13081 // just report that one, and swallow the error from this one.
13082 if (already_failed)
13083 mono_error_cleanup (error);
13085 return TRUE;
13086 } else
13087 return FALSE;
13090 static void
13091 check_array_for_usertypes (MonoArray *arr, MonoError *error)
13093 mono_error_init (error);
13094 int i;
13096 if (!arr)
13097 return;
13099 for (i = 0; i < mono_array_length (arr); ++i) {
13100 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i, error);
13101 if (!mono_error_ok (error))
13102 break;
13106 MonoReflectionType*
13107 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
13109 MonoError error;
13110 MonoClass *klass;
13111 MonoDomain* domain;
13112 MonoReflectionType* res;
13113 int i, j;
13115 mono_error_init (&error);
13117 domain = mono_object_domain (tb);
13118 klass = mono_class_from_mono_type (tb->type.type);
13121 * Check for user defined Type subclasses.
13123 RESOLVE_TYPE (tb->parent, &error);
13124 if (!is_ok (&error))
13125 goto failure_unlocked;
13126 check_array_for_usertypes (tb->interfaces, &error);
13127 if (!is_ok (&error))
13128 goto failure_unlocked;
13129 if (tb->fields) {
13130 for (i = 0; i < mono_array_length (tb->fields); ++i) {
13131 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
13132 if (fb) {
13133 RESOLVE_TYPE (fb->type, &error);
13134 if (!is_ok (&error))
13135 goto failure_unlocked;
13136 check_array_for_usertypes (fb->modreq, &error);
13137 if (!is_ok (&error))
13138 goto failure_unlocked;
13139 check_array_for_usertypes (fb->modopt, &error);
13140 if (!is_ok (&error))
13141 goto failure_unlocked;
13142 if (fb->marshal_info && fb->marshal_info->marshaltyperef) {
13143 RESOLVE_TYPE (fb->marshal_info->marshaltyperef, &error);
13144 if (!is_ok (&error))
13145 goto failure_unlocked;
13150 if (tb->methods) {
13151 for (i = 0; i < mono_array_length (tb->methods); ++i) {
13152 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)mono_array_get (tb->methods, gpointer, i);
13153 if (mb) {
13154 RESOLVE_TYPE (mb->rtype, &error);
13155 if (!is_ok (&error))
13156 goto failure_unlocked;
13157 check_array_for_usertypes (mb->return_modreq, &error);
13158 if (!is_ok (&error))
13159 goto failure_unlocked;
13160 check_array_for_usertypes (mb->return_modopt, &error);
13161 if (!is_ok (&error))
13162 goto failure_unlocked;
13163 check_array_for_usertypes (mb->parameters, &error);
13164 if (!is_ok (&error))
13165 goto failure_unlocked;
13166 if (mb->param_modreq)
13167 for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
13168 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
13169 if (!is_ok (&error))
13170 goto failure_unlocked;
13172 if (mb->param_modopt)
13173 for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
13174 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
13175 if (!is_ok (&error))
13176 goto failure_unlocked;
13181 if (tb->ctors) {
13182 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
13183 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)mono_array_get (tb->ctors, gpointer, i);
13184 if (mb) {
13185 check_array_for_usertypes (mb->parameters, &error);
13186 if (!is_ok (&error))
13187 goto failure_unlocked;
13188 if (mb->param_modreq)
13189 for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
13190 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
13191 if (!is_ok (&error))
13192 goto failure_unlocked;
13194 if (mb->param_modopt)
13195 for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
13196 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
13197 if (!is_ok (&error))
13198 goto failure_unlocked;
13204 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
13207 * we need to lock the domain because the lock will be taken inside
13208 * So, we need to keep the locking order correct.
13210 mono_loader_lock ();
13211 mono_domain_lock (domain);
13212 if (klass->wastypebuilder) {
13213 mono_domain_unlock (domain);
13214 mono_loader_unlock ();
13216 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
13217 mono_error_set_pending_exception (&error);
13219 return res;
13222 * Fields to set in klass:
13223 * the various flags: delegate/unicode/contextbound etc.
13225 klass->flags = tb->attrs;
13226 klass->has_cctor = 1;
13227 klass->has_finalize = 1;
13228 klass->has_finalize_inited = 1;
13230 mono_class_setup_parent (klass, klass->parent);
13231 /* fool mono_class_setup_supertypes */
13232 klass->supertypes = NULL;
13233 mono_class_setup_supertypes (klass);
13234 mono_class_setup_mono_type (klass);
13236 #if 0
13237 if (!((MonoDynamicImage*)klass->image)->run) {
13238 if (klass->generic_container) {
13239 /* FIXME: The code below can't handle generic classes */
13240 klass->wastypebuilder = TRUE;
13241 mono_loader_unlock ();
13242 mono_domain_unlock (domain);
13244 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
13245 mono_error_set_pending_exception (&error);
13247 return res;
13250 #endif
13252 /* enums are done right away */
13253 if (!klass->enumtype)
13254 if (!ensure_runtime_vtable (klass, &error))
13255 goto failure;
13257 if (tb->subtypes) {
13258 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
13259 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
13260 mono_class_alloc_ext (klass);
13261 MonoType *subtype = mono_reflection_type_get_handle ((MonoReflectionType*)subtb, &error);
13262 if (!is_ok (&error)) goto failure;
13263 klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, mono_class_from_mono_type (subtype));
13267 klass->nested_classes_inited = TRUE;
13269 /* fields and object layout */
13270 if (klass->parent) {
13271 if (!klass->parent->size_inited)
13272 mono_class_init (klass->parent);
13273 klass->instance_size = klass->parent->instance_size;
13274 klass->sizes.class_size = 0;
13275 klass->min_align = klass->parent->min_align;
13276 /* if the type has no fields we won't call the field_setup
13277 * routine which sets up klass->has_references.
13279 klass->has_references |= klass->parent->has_references;
13280 } else {
13281 klass->instance_size = sizeof (MonoObject);
13282 klass->min_align = 1;
13285 /* FIXME: handle packing_size and instance_size */
13286 typebuilder_setup_fields (klass, &error);
13287 if (!mono_error_ok (&error))
13288 goto failure;
13289 typebuilder_setup_properties (klass, &error);
13290 if (!mono_error_ok (&error))
13291 goto failure;
13293 typebuilder_setup_events (klass, &error);
13294 if (!mono_error_ok (&error))
13295 goto failure;
13297 klass->wastypebuilder = TRUE;
13300 * If we are a generic TypeBuilder, there might be instantiations in the type cache
13301 * which have type System.Reflection.MonoGenericClass, but after the type is created,
13302 * we want to return normal System.MonoType objects, so clear these out from the cache.
13304 * Together with this we must ensure the contents of all instances to match the created type.
13306 if (domain->type_hash && klass->generic_container) {
13307 struct remove_instantiations_user_data data;
13308 data.klass = klass;
13309 data.error = &error;
13310 mono_error_assert_ok (&error);
13311 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, &data);
13312 if (!is_ok (&error))
13313 goto failure;
13316 mono_domain_unlock (domain);
13317 mono_loader_unlock ();
13319 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
13320 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
13321 mono_error_set_type_load_class (&error, klass, "Not a valid enumeration");
13322 goto failure_unlocked;
13325 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
13326 if (!is_ok (&error))
13327 goto failure_unlocked;
13329 g_assert (res != (MonoReflectionType*)tb);
13331 return res;
13333 failure:
13334 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
13335 klass->wastypebuilder = TRUE;
13336 mono_domain_unlock (domain);
13337 mono_loader_unlock ();
13338 failure_unlocked:
13339 mono_error_set_pending_exception (&error);
13340 return NULL;
13343 static gboolean
13344 reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam, MonoError *error)
13346 MonoGenericParamFull *param;
13347 MonoImage *image;
13348 MonoClass *pklass;
13350 mono_error_init (error);
13352 image = &gparam->tbuilder->module->dynamic_image->image;
13354 param = mono_image_new0 (image, MonoGenericParamFull, 1);
13356 param->info.name = mono_string_to_utf8_image (image, gparam->name, error);
13357 mono_error_assert_ok (error);
13358 param->param.num = gparam->index;
13360 if (gparam->mbuilder) {
13361 if (!gparam->mbuilder->generic_container) {
13362 MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->mbuilder->type, error);
13363 return_val_if_nok (error, FALSE);
13365 MonoClass *klass = mono_class_from_mono_type (tb);
13366 gparam->mbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
13367 gparam->mbuilder->generic_container->is_method = TRUE;
13369 * Cannot set owner.method, since the MonoMethod is not created yet.
13370 * Set the image field instead, so type_in_image () works.
13372 gparam->mbuilder->generic_container->is_anonymous = TRUE;
13373 gparam->mbuilder->generic_container->owner.image = klass->image;
13375 param->param.owner = gparam->mbuilder->generic_container;
13376 } else if (gparam->tbuilder) {
13377 if (!gparam->tbuilder->generic_container) {
13378 MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder, error);
13379 return_val_if_nok (error, FALSE);
13380 MonoClass *klass = mono_class_from_mono_type (tb);
13381 gparam->tbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
13382 gparam->tbuilder->generic_container->owner.klass = klass;
13384 param->param.owner = gparam->tbuilder->generic_container;
13387 pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
13389 gparam->type.type = &pklass->byval_arg;
13391 mono_class_set_ref_info (pklass, gparam);
13392 mono_image_append_class_to_reflection_info_set (pklass);
13394 return TRUE;
13397 void
13398 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
13400 MonoError error;
13401 (void) reflection_initialize_generic_parameter (gparam, &error);
13402 mono_error_set_pending_exception (&error);
13406 MonoArray *
13407 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
13409 MonoError error;
13410 MonoReflectionModuleBuilder *module = sig->module;
13411 MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
13412 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
13413 guint32 buflen, i;
13414 MonoArray *result;
13415 SigBuffer buf;
13417 check_array_for_usertypes (sig->arguments, &error);
13418 mono_error_raise_exception (&error); /* FIXME: don't raise here */
13420 sigbuffer_init (&buf, 32);
13422 sigbuffer_add_value (&buf, 0x07);
13423 sigbuffer_add_value (&buf, na);
13424 if (assembly != NULL){
13425 for (i = 0; i < na; ++i) {
13426 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
13427 encode_reflection_type (assembly, type, &buf, &error);
13428 if (!is_ok (&error)) goto fail;
13432 buflen = buf.p - buf.buf;
13433 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
13434 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
13435 sigbuffer_free (&buf);
13436 return result;
13437 fail:
13438 sigbuffer_free (&buf);
13439 mono_error_raise_exception (&error); /* FIXME don't raise here */
13440 return NULL;
13443 MonoArray *
13444 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
13446 MonoError error;
13447 MonoDynamicImage *assembly = sig->module->dynamic_image;
13448 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
13449 guint32 buflen, i;
13450 MonoArray *result;
13451 SigBuffer buf;
13453 check_array_for_usertypes (sig->arguments, &error);
13454 mono_error_raise_exception (&error); /* FIXME: don't raise here */
13456 sigbuffer_init (&buf, 32);
13458 sigbuffer_add_value (&buf, 0x06);
13459 for (i = 0; i < na; ++i) {
13460 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
13461 encode_reflection_type (assembly, type, &buf, &error);
13462 if (!is_ok (&error))
13463 goto fail;
13466 buflen = buf.p - buf.buf;
13467 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
13468 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
13469 sigbuffer_free (&buf);
13471 return result;
13472 fail:
13473 sigbuffer_free (&buf);
13474 mono_error_raise_exception (&error); /* FIXME don't raise here */
13475 return NULL;
13478 typedef struct {
13479 MonoMethod *handle;
13480 MonoDomain *domain;
13481 } DynamicMethodReleaseData;
13484 * The runtime automatically clean up those after finalization.
13486 static MonoReferenceQueue *dynamic_method_queue;
13488 static void
13489 free_dynamic_method (void *dynamic_method)
13491 DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
13492 MonoDomain *domain = data->domain;
13493 MonoMethod *method = data->handle;
13494 guint32 dis_link;
13496 mono_domain_lock (domain);
13497 dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
13498 g_hash_table_remove (domain->method_to_dyn_method, method);
13499 mono_domain_unlock (domain);
13500 g_assert (dis_link);
13501 mono_gchandle_free (dis_link);
13503 mono_runtime_free_method (domain, method);
13504 g_free (data);
13507 static gboolean
13508 reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb, MonoError *error)
13510 MonoReferenceQueue *queue;
13511 MonoMethod *handle;
13512 DynamicMethodReleaseData *release_data;
13513 ReflectionMethodBuilder rmb;
13514 MonoMethodSignature *sig;
13515 MonoClass *klass;
13516 MonoDomain *domain;
13517 GSList *l;
13518 int i;
13520 mono_error_init (error);
13522 if (mono_runtime_is_shutting_down ()) {
13523 mono_error_set_generic_error (error, "System", "InvalidOperationException", "");
13524 return FALSE;
13527 if (!(queue = dynamic_method_queue)) {
13528 mono_loader_lock ();
13529 if (!(queue = dynamic_method_queue))
13530 queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
13531 mono_loader_unlock ();
13534 sig = dynamic_method_to_signature (mb, error);
13535 return_val_if_nok (error, FALSE);
13537 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
13540 * Resolve references.
13543 * Every second entry in the refs array is reserved for storing handle_class,
13544 * which is needed by the ldtoken implementation in the JIT.
13546 rmb.nrefs = mb->nrefs;
13547 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
13548 for (i = 0; i < mb->nrefs; i += 2) {
13549 MonoClass *handle_class;
13550 gpointer ref;
13551 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
13553 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
13554 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
13556 * The referenced DynamicMethod should already be created by the managed
13557 * code, except in the case of circular references. In that case, we store
13558 * method in the refs array, and fix it up later when the referenced
13559 * DynamicMethod is created.
13561 if (method->mhandle) {
13562 ref = method->mhandle;
13563 } else {
13564 /* FIXME: GC object stored in unmanaged memory */
13565 ref = method;
13567 /* FIXME: GC object stored in unmanaged memory */
13568 method->referenced_by = g_slist_append (method->referenced_by, mb);
13570 handle_class = mono_defaults.methodhandle_class;
13571 } else {
13572 MonoException *ex = NULL;
13573 ref = resolve_object (mb->module->image, obj, &handle_class, NULL, error);
13574 if (!is_ok (error)) {
13575 g_free (rmb.refs);
13576 return FALSE;
13578 if (!ref)
13579 ex = mono_get_exception_type_load (NULL, NULL);
13580 else if (mono_security_core_clr_enabled ())
13581 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
13583 if (ex) {
13584 g_free (rmb.refs);
13585 mono_error_set_exception_instance (error, ex);
13586 return FALSE;
13590 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
13591 rmb.refs [i + 1] = handle_class;
13594 if (mb->owner) {
13595 MonoType *owner_type = mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner, error);
13596 if (!is_ok (error)) {
13597 g_free (rmb.refs);
13598 return FALSE;
13600 klass = mono_class_from_mono_type (owner_type);
13601 } else {
13602 klass = mono_defaults.object_class;
13605 mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
13606 release_data = g_new (DynamicMethodReleaseData, 1);
13607 release_data->handle = handle;
13608 release_data->domain = mono_object_get_domain ((MonoObject*)mb);
13609 if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
13610 g_free (release_data);
13612 /* Fix up refs entries pointing at us */
13613 for (l = mb->referenced_by; l; l = l->next) {
13614 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
13615 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
13616 gpointer *data;
13618 g_assert (method->mhandle);
13620 data = (gpointer*)wrapper->method_data;
13621 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
13622 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
13623 data [i + 1] = mb->mhandle;
13626 g_slist_free (mb->referenced_by);
13628 g_free (rmb.refs);
13630 /* ilgen is no longer needed */
13631 mb->ilgen = NULL;
13633 domain = mono_domain_get ();
13634 mono_domain_lock (domain);
13635 if (!domain->method_to_dyn_method)
13636 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
13637 g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
13638 mono_domain_unlock (domain);
13640 return TRUE;
13643 void
13644 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
13646 MonoError error;
13647 (void) reflection_create_dynamic_method (mb, &error);
13648 mono_error_set_pending_exception (&error);
13651 #endif /* DISABLE_REFLECTION_EMIT */
13655 * mono_reflection_is_valid_dynamic_token:
13657 * Returns TRUE if token is valid.
13660 gboolean
13661 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
13663 return lookup_dyn_token (image, token) != NULL;
13666 MonoMethodSignature *
13667 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
13669 MonoMethodSignature *sig;
13670 g_assert (image_is_dynamic (image));
13672 mono_error_init (error);
13674 sig = (MonoMethodSignature *)g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
13675 if (sig)
13676 return sig;
13678 return mono_method_signature_checked (method, error);
13681 #ifndef DISABLE_REFLECTION_EMIT
13684 * mono_reflection_lookup_dynamic_token:
13686 * Finish the Builder object pointed to by TOKEN and return the corresponding
13687 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
13688 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
13689 * mapping table.
13691 * LOCKING: Take the loader lock
13693 gpointer
13694 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
13696 MonoError error;
13697 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
13698 MonoObject *obj;
13699 MonoClass *klass;
13701 obj = lookup_dyn_token (assembly, token);
13702 if (!obj) {
13703 if (valid_token)
13704 g_error ("Could not find required dynamic token 0x%08x", token);
13705 else
13706 return NULL;
13709 if (!handle_class)
13710 handle_class = &klass;
13711 gpointer result = resolve_object (image, obj, handle_class, context, &error);
13712 mono_error_raise_exception (&error); /* FIXME don't raise here */
13713 return result;
13717 * ensure_complete_type:
13719 * Ensure that KLASS is completed if it is a dynamic type, or references
13720 * dynamic types.
13722 static void
13723 ensure_complete_type (MonoClass *klass, MonoError *error)
13725 mono_error_init (error);
13727 if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
13728 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
13730 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13731 return_if_nok (error);
13733 // Asserting here could break a lot of code
13734 //g_assert (klass->wastypebuilder);
13737 if (klass->generic_class) {
13738 MonoGenericInst *inst = klass->generic_class->context.class_inst;
13739 int i;
13741 for (i = 0; i < inst->type_argc; ++i) {
13742 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]), error);
13743 return_if_nok (error);
13748 static gpointer
13749 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
13751 gpointer result = NULL;
13753 mono_error_init (error);
13755 if (strcmp (obj->vtable->klass->name, "String") == 0) {
13756 result = mono_string_intern_checked ((MonoString*)obj, error);
13757 return_val_if_nok (error, NULL);
13758 *handle_class = mono_defaults.string_class;
13759 g_assert (result);
13760 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
13761 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
13762 return_val_if_nok (error, NULL);
13763 MonoClass *mc = mono_class_from_mono_type (type);
13764 if (!mono_class_init (mc)) {
13765 mono_error_set_exception_instance (error, mono_class_get_exception_for_failure (mc));
13766 return NULL;
13769 if (context) {
13770 MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, error);
13771 return_val_if_nok (error, NULL);
13773 result = mono_class_from_mono_type (inflated);
13774 mono_metadata_free_type (inflated);
13775 } else {
13776 result = mono_class_from_mono_type (type);
13778 *handle_class = mono_defaults.typehandle_class;
13779 g_assert (result);
13780 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
13781 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
13782 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
13783 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
13784 result = ((MonoReflectionMethod*)obj)->method;
13785 if (context) {
13786 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
13787 mono_error_assert_ok (error);
13789 *handle_class = mono_defaults.methodhandle_class;
13790 g_assert (result);
13791 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
13792 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
13793 result = mb->mhandle;
13794 if (!result) {
13795 /* Type is not yet created */
13796 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
13798 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13799 return_val_if_nok (error, NULL);
13802 * Hopefully this has been filled in by calling CreateType() on the
13803 * TypeBuilder.
13806 * TODO: This won't work if the application finishes another
13807 * TypeBuilder instance instead of this one.
13809 result = mb->mhandle;
13811 if (context) {
13812 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
13813 mono_error_assert_ok (error);
13815 *handle_class = mono_defaults.methodhandle_class;
13816 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
13817 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
13819 result = cb->mhandle;
13820 if (!result) {
13821 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
13823 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13824 return_val_if_nok (error, NULL);
13825 result = cb->mhandle;
13827 if (context) {
13828 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
13829 mono_error_assert_ok (error);
13831 *handle_class = mono_defaults.methodhandle_class;
13832 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
13833 MonoClassField *field = ((MonoReflectionField*)obj)->field;
13835 ensure_complete_type (field->parent, error);
13836 return_val_if_nok (error, NULL);
13838 if (context) {
13839 MonoType *inflated = mono_class_inflate_generic_type_checked (&field->parent->byval_arg, context, error);
13840 return_val_if_nok (error, NULL);
13842 MonoClass *klass = mono_class_from_mono_type (inflated);
13843 MonoClassField *inflated_field;
13844 gpointer iter = NULL;
13845 mono_metadata_free_type (inflated);
13846 while ((inflated_field = mono_class_get_fields (klass, &iter))) {
13847 if (!strcmp (field->name, inflated_field->name))
13848 break;
13850 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
13851 result = inflated_field;
13852 } else {
13853 result = field;
13855 *handle_class = mono_defaults.fieldhandle_class;
13856 g_assert (result);
13857 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
13858 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
13859 result = fb->handle;
13861 if (!result) {
13862 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
13864 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13865 return_val_if_nok (error, NULL);
13866 result = fb->handle;
13869 if (fb->handle && fb->handle->parent->generic_container) {
13870 MonoClass *klass = fb->handle->parent;
13871 MonoType *type = mono_class_inflate_generic_type_checked (&klass->byval_arg, context, error);
13872 return_val_if_nok (error, NULL);
13874 MonoClass *inflated = mono_class_from_mono_type (type);
13876 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
13877 g_assert (result);
13878 mono_metadata_free_type (type);
13880 *handle_class = mono_defaults.fieldhandle_class;
13881 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
13882 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
13883 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
13884 return_val_if_nok (error, NULL);
13885 MonoClass *klass;
13887 klass = type->data.klass;
13888 if (klass->wastypebuilder) {
13889 /* Already created */
13890 result = klass;
13892 else {
13893 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13894 return_val_if_nok (error, NULL);
13895 result = type->data.klass;
13896 g_assert (result);
13898 *handle_class = mono_defaults.typehandle_class;
13899 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
13900 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
13901 MonoMethodSignature *sig;
13902 int nargs, i;
13904 if (helper->arguments)
13905 nargs = mono_array_length (helper->arguments);
13906 else
13907 nargs = 0;
13909 sig = mono_metadata_signature_alloc (image, nargs);
13910 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
13911 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
13913 if (helper->unmanaged_call_conv) { /* unmanaged */
13914 sig->call_convention = helper->unmanaged_call_conv - 1;
13915 sig->pinvoke = TRUE;
13916 } else if (helper->call_conv & 0x02) {
13917 sig->call_convention = MONO_CALL_VARARG;
13918 } else {
13919 sig->call_convention = MONO_CALL_DEFAULT;
13922 sig->param_count = nargs;
13923 /* TODO: Copy type ? */
13924 sig->ret = helper->return_type->type;
13925 for (i = 0; i < nargs; ++i) {
13926 sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i, error);
13927 if (!is_ok (error)) {
13928 image_g_free (image, sig);
13929 return NULL;
13933 result = sig;
13934 *handle_class = NULL;
13935 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
13936 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
13937 /* Already created by the managed code */
13938 g_assert (method->mhandle);
13939 result = method->mhandle;
13940 *handle_class = mono_defaults.methodhandle_class;
13941 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
13942 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
13943 return_val_if_nok (error, NULL);
13944 type = mono_class_inflate_generic_type_checked (type, context, error);
13945 return_val_if_nok (error, NULL);
13947 result = mono_class_from_mono_type (type);
13948 *handle_class = mono_defaults.typehandle_class;
13949 g_assert (result);
13950 mono_metadata_free_type (type);
13951 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
13952 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
13953 return_val_if_nok (error, NULL);
13954 type = mono_class_inflate_generic_type_checked (type, context, error);
13955 return_val_if_nok (error, NULL);
13957 result = mono_class_from_mono_type (type);
13958 *handle_class = mono_defaults.typehandle_class;
13959 g_assert (result);
13960 mono_metadata_free_type (type);
13961 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
13962 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
13963 MonoClass *inflated;
13964 MonoType *type;
13965 MonoClassField *field;
13967 if (is_sre_field_builder (mono_object_class (f->fb)))
13968 field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
13969 else if (is_sr_mono_field (mono_object_class (f->fb)))
13970 field = ((MonoReflectionField*)f->fb)->field;
13971 else
13972 g_error ("resolve_object:: can't handle a FTBI with base_method of type %s", mono_type_get_full_name (mono_object_class (f->fb)));
13974 MonoType *finst = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
13975 return_val_if_nok (error, NULL);
13976 type = mono_class_inflate_generic_type_checked (finst, context, error);
13977 return_val_if_nok (error, NULL);
13979 inflated = mono_class_from_mono_type (type);
13981 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
13982 ensure_complete_type (field->parent, error);
13983 if (!is_ok (error)) {
13984 mono_metadata_free_type (type);
13985 return NULL;
13988 g_assert (result);
13989 mono_metadata_free_type (type);
13990 *handle_class = mono_defaults.fieldhandle_class;
13991 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
13992 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
13993 MonoType *cinst = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
13994 return_val_if_nok (error, NULL);
13995 MonoType *type = mono_class_inflate_generic_type_checked (cinst, context, error);
13996 return_val_if_nok (error, NULL);
13998 MonoClass *inflated_klass = mono_class_from_mono_type (type);
13999 MonoMethod *method;
14001 if (is_sre_ctor_builder (mono_object_class (c->cb)))
14002 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
14003 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
14004 method = ((MonoReflectionMethod *)c->cb)->method;
14005 else
14006 g_error ("resolve_object:: can't handle a CTBI with base_method of type %s", mono_type_get_full_name (mono_object_class (c->cb)));
14008 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
14009 *handle_class = mono_defaults.methodhandle_class;
14010 mono_metadata_free_type (type);
14011 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
14012 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
14013 if (m->method_args) {
14014 result = mono_reflection_method_on_tb_inst_get_handle (m, error);
14015 return_val_if_nok (error, NULL);
14016 if (context) {
14017 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
14018 mono_error_assert_ok (error);
14020 } else {
14021 MonoType *minst = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
14022 return_val_if_nok (error, NULL);
14023 MonoType *type = mono_class_inflate_generic_type_checked (minst, context, error);
14024 return_val_if_nok (error, NULL);
14026 MonoClass *inflated_klass = mono_class_from_mono_type (type);
14027 MonoMethod *method;
14029 if (is_sre_method_builder (mono_object_class (m->mb)))
14030 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
14031 else if (is_sr_mono_method (mono_object_class (m->mb)))
14032 method = ((MonoReflectionMethod *)m->mb)->method;
14033 else
14034 g_error ("resolve_object:: can't handle a MTBI with base_method of type %s", mono_type_get_full_name (mono_object_class (m->mb)));
14036 result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
14037 mono_metadata_free_type (type);
14039 *handle_class = mono_defaults.methodhandle_class;
14040 } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
14041 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
14042 MonoType *mtype;
14043 MonoClass *klass;
14044 MonoMethod *method;
14045 gpointer iter;
14046 char *name;
14048 mtype = mono_reflection_type_get_handle (m->parent, error);
14049 return_val_if_nok (error, NULL);
14050 klass = mono_class_from_mono_type (mtype);
14052 /* Find the method */
14054 name = mono_string_to_utf8 (m->name);
14055 iter = NULL;
14056 while ((method = mono_class_get_methods (klass, &iter))) {
14057 if (!strcmp (method->name, name))
14058 break;
14060 g_free (name);
14062 // FIXME:
14063 g_assert (method);
14064 // FIXME: Check parameters/return value etc. match
14066 result = method;
14067 *handle_class = mono_defaults.methodhandle_class;
14068 } else if (is_sre_array (mono_object_get_class(obj)) ||
14069 is_sre_byref (mono_object_get_class(obj)) ||
14070 is_sre_pointer (mono_object_get_class(obj))) {
14071 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
14072 MonoType *type = mono_reflection_type_get_handle (ref_type, error);
14073 return_val_if_nok (error, NULL);
14075 if (context) {
14076 MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, error);
14077 return_val_if_nok (error, NULL);
14079 result = mono_class_from_mono_type (inflated);
14080 mono_metadata_free_type (inflated);
14081 } else {
14082 result = mono_class_from_mono_type (type);
14084 *handle_class = mono_defaults.typehandle_class;
14085 } else {
14086 g_print ("%s\n", obj->vtable->klass->name);
14087 g_assert_not_reached ();
14089 return result;
14092 #else /* DISABLE_REFLECTION_EMIT */
14094 MonoArray*
14095 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
14097 g_assert_not_reached ();
14098 return NULL;
14101 void
14102 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
14104 g_assert_not_reached ();
14107 void
14108 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
14110 g_assert_not_reached ();
14113 void
14114 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
14116 g_assert_not_reached ();
14119 void
14120 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
14122 g_assert_not_reached ();
14125 void
14126 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
14128 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
14131 void
14132 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
14134 g_assert_not_reached ();
14137 void
14138 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
14140 g_assert_not_reached ();
14143 MonoReflectionModule *
14144 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName, MonoError *error)
14146 g_assert_not_reached ();
14147 return NULL;
14150 guint32
14151 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
14153 g_assert_not_reached ();
14154 return 0;
14157 guint32
14158 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
14160 g_assert_not_reached ();
14161 return 0;
14164 guint32
14165 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
14166 gboolean create_open_instance, gboolean register_token, MonoError *error)
14168 g_assert_not_reached ();
14169 return 0;
14172 void
14173 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
14177 void
14178 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
14180 g_assert_not_reached ();
14183 void
14184 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides, MonoError *error)
14186 mono_error_init (error);
14187 *overrides = NULL;
14188 *num_overrides = 0;
14191 MonoReflectionEvent *
14192 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
14194 g_assert_not_reached ();
14195 return NULL;
14198 MonoReflectionType*
14199 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
14201 g_assert_not_reached ();
14202 return NULL;
14205 void
14206 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
14208 g_assert_not_reached ();
14211 MonoArray *
14212 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
14214 g_assert_not_reached ();
14215 return NULL;
14218 MonoArray *
14219 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
14221 g_assert_not_reached ();
14222 return NULL;
14225 void
14226 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
14230 gpointer
14231 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
14233 return NULL;
14236 MonoType*
14237 mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
14239 mono_error_init (error);
14240 if (!ref)
14241 return NULL;
14242 return ref->type;
14245 void
14246 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
14248 g_assert_not_reached ();
14251 #endif /* DISABLE_REFLECTION_EMIT */
14253 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
14254 const static guint32 declsec_flags_map[] = {
14255 0x00000000, /* empty */
14256 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
14257 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
14258 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
14259 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
14260 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
14261 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
14262 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
14263 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
14264 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
14265 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
14266 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
14267 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
14268 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
14269 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
14270 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
14271 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
14272 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
14273 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
14277 * Returns flags that includes all available security action associated to the handle.
14278 * @token: metadata token (either for a class or a method)
14279 * @image: image where resides the metadata.
14281 static guint32
14282 mono_declsec_get_flags (MonoImage *image, guint32 token)
14284 int index = mono_metadata_declsec_from_index (image, token);
14285 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
14286 guint32 result = 0;
14287 guint32 action;
14288 int i;
14290 /* HasSecurity can be present for other, not specially encoded, attributes,
14291 e.g. SuppressUnmanagedCodeSecurityAttribute */
14292 if (index < 0)
14293 return 0;
14295 for (i = index; i < t->rows; i++) {
14296 guint32 cols [MONO_DECL_SECURITY_SIZE];
14298 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14299 if (cols [MONO_DECL_SECURITY_PARENT] != token)
14300 break;
14302 action = cols [MONO_DECL_SECURITY_ACTION];
14303 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
14304 result |= declsec_flags_map [action];
14305 } else {
14306 g_assert_not_reached ();
14309 return result;
14313 * Get the security actions (in the form of flags) associated with the specified method.
14315 * @method: The method for which we want the declarative security flags.
14316 * Return the declarative security flags for the method (only).
14318 * Note: To keep MonoMethod size down we do not cache the declarative security flags
14319 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
14321 guint32
14322 mono_declsec_flags_from_method (MonoMethod *method)
14324 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14325 /* FIXME: No cache (for the moment) */
14326 guint32 idx = mono_method_get_index (method);
14327 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14328 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14329 return mono_declsec_get_flags (method->klass->image, idx);
14331 return 0;
14335 * Get the security actions (in the form of flags) associated with the specified class.
14337 * @klass: The class for which we want the declarative security flags.
14338 * Return the declarative security flags for the class.
14340 * Note: We cache the flags inside the MonoClass structure as this will get
14341 * called very often (at least for each method).
14343 guint32
14344 mono_declsec_flags_from_class (MonoClass *klass)
14346 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
14347 if (!klass->ext || !klass->ext->declsec_flags) {
14348 guint32 idx;
14350 idx = mono_metadata_token_index (klass->type_token);
14351 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14352 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14353 mono_loader_lock ();
14354 mono_class_alloc_ext (klass);
14355 mono_loader_unlock ();
14356 /* we cache the flags on classes */
14357 klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
14359 return klass->ext->declsec_flags;
14361 return 0;
14365 * Get the security actions (in the form of flags) associated with the specified assembly.
14367 * @assembly: The assembly for which we want the declarative security flags.
14368 * Return the declarative security flags for the assembly.
14370 guint32
14371 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
14373 guint32 idx = 1; /* there is only one assembly */
14374 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14375 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
14376 return mono_declsec_get_flags (assembly->image, idx);
14381 * Fill actions for the specific index (which may either be an encoded class token or
14382 * an encoded method token) from the metadata image.
14383 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
14385 static MonoBoolean
14386 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
14387 guint32 id_std, guint32 id_noncas, guint32 id_choice)
14389 MonoBoolean result = FALSE;
14390 MonoTableInfo *t;
14391 guint32 cols [MONO_DECL_SECURITY_SIZE];
14392 int index = mono_metadata_declsec_from_index (image, token);
14393 int i;
14395 t = &image->tables [MONO_TABLE_DECLSECURITY];
14396 for (i = index; i < t->rows; i++) {
14397 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14399 if (cols [MONO_DECL_SECURITY_PARENT] != token)
14400 return result;
14402 /* if present only replace (class) permissions with method permissions */
14403 /* if empty accept either class or method permissions */
14404 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
14405 if (!actions->demand.blob) {
14406 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14407 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14408 actions->demand.blob = (char*) (blob + 2);
14409 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
14410 result = TRUE;
14412 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
14413 if (!actions->noncasdemand.blob) {
14414 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14415 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14416 actions->noncasdemand.blob = (char*) (blob + 2);
14417 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
14418 result = TRUE;
14420 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
14421 if (!actions->demandchoice.blob) {
14422 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14423 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14424 actions->demandchoice.blob = (char*) (blob + 2);
14425 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
14426 result = TRUE;
14431 return result;
14434 static MonoBoolean
14435 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
14436 guint32 id_std, guint32 id_noncas, guint32 id_choice)
14438 guint32 idx = mono_metadata_token_index (klass->type_token);
14439 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14440 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14441 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
14444 static MonoBoolean
14445 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
14446 guint32 id_std, guint32 id_noncas, guint32 id_choice)
14448 guint32 idx = mono_method_get_index (method);
14449 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14450 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14451 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
14455 * Collect all actions (that requires to generate code in mini) assigned for
14456 * the specified method.
14457 * Note: Don't use the content of actions if the function return FALSE.
14459 MonoBoolean
14460 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
14462 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
14463 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
14464 MonoBoolean result = FALSE;
14465 guint32 flags;
14467 /* quick exit if no declarative security is present in the metadata */
14468 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14469 return FALSE;
14471 /* we want the original as the wrapper is "free" of the security informations */
14472 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14473 method = mono_marshal_method_from_wrapper (method);
14474 if (!method)
14475 return FALSE;
14478 /* First we look for method-level attributes */
14479 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14480 mono_class_init (method->klass);
14481 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14483 result = mono_declsec_get_method_demands_params (method, demands,
14484 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
14487 /* Here we use (or create) the class declarative cache to look for demands */
14488 flags = mono_declsec_flags_from_class (method->klass);
14489 if (flags & mask) {
14490 if (!result) {
14491 mono_class_init (method->klass);
14492 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14494 result |= mono_declsec_get_class_demands_params (method->klass, demands,
14495 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
14498 /* The boolean return value is used as a shortcut in case nothing needs to
14499 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
14500 return result;
14505 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
14507 * Note: Don't use the content of actions if the function return FALSE.
14509 MonoBoolean
14510 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
14512 MonoBoolean result = FALSE;
14513 guint32 flags;
14515 /* quick exit if no declarative security is present in the metadata */
14516 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14517 return FALSE;
14519 /* we want the original as the wrapper is "free" of the security informations */
14520 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14521 method = mono_marshal_method_from_wrapper (method);
14522 if (!method)
14523 return FALSE;
14526 /* results are independant - zeroize both */
14527 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
14528 memset (klass, 0, sizeof (MonoDeclSecurityActions));
14530 /* First we look for method-level attributes */
14531 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14532 mono_class_init (method->klass);
14534 result = mono_declsec_get_method_demands_params (method, cmethod,
14535 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
14538 /* Here we use (or create) the class declarative cache to look for demands */
14539 flags = mono_declsec_flags_from_class (method->klass);
14540 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
14541 mono_class_init (method->klass);
14543 result |= mono_declsec_get_class_demands_params (method->klass, klass,
14544 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
14547 return result;
14551 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14553 * @klass The inherited class - this is the class that provides the security check (attributes)
14554 * @demans
14555 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
14557 * Note: Don't use the content of actions if the function return FALSE.
14559 MonoBoolean
14560 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
14562 MonoBoolean result = FALSE;
14563 guint32 flags;
14565 /* quick exit if no declarative security is present in the metadata */
14566 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14567 return FALSE;
14569 /* Here we use (or create) the class declarative cache to look for demands */
14570 flags = mono_declsec_flags_from_class (klass);
14571 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
14572 mono_class_init (klass);
14573 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14575 result |= mono_declsec_get_class_demands_params (klass, demands,
14576 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
14579 return result;
14583 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14585 * Note: Don't use the content of actions if the function return FALSE.
14587 MonoBoolean
14588 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
14590 /* quick exit if no declarative security is present in the metadata */
14591 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14592 return FALSE;
14594 /* we want the original as the wrapper is "free" of the security informations */
14595 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14596 method = mono_marshal_method_from_wrapper (method);
14597 if (!method)
14598 return FALSE;
14601 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14602 mono_class_init (method->klass);
14603 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14605 return mono_declsec_get_method_demands_params (method, demands,
14606 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
14608 return FALSE;
14612 static MonoBoolean
14613 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
14615 guint32 cols [MONO_DECL_SECURITY_SIZE];
14616 MonoTableInfo *t;
14617 int i;
14619 int index = mono_metadata_declsec_from_index (image, token);
14620 if (index == -1)
14621 return FALSE;
14623 t = &image->tables [MONO_TABLE_DECLSECURITY];
14624 for (i = index; i < t->rows; i++) {
14625 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14627 /* shortcut - index are ordered */
14628 if (token != cols [MONO_DECL_SECURITY_PARENT])
14629 return FALSE;
14631 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
14632 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14633 entry->blob = (char*) (metadata + 2);
14634 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
14635 return TRUE;
14639 return FALSE;
14642 MonoBoolean
14643 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
14645 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14646 guint32 idx = mono_method_get_index (method);
14647 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14648 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14649 return get_declsec_action (method->klass->image, idx, action, entry);
14651 return FALSE;
14654 MonoBoolean
14655 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
14657 /* use cache */
14658 guint32 flags = mono_declsec_flags_from_class (klass);
14659 if (declsec_flags_map [action] & flags) {
14660 guint32 idx = mono_metadata_token_index (klass->type_token);
14661 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14662 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14663 return get_declsec_action (klass->image, idx, action, entry);
14665 return FALSE;
14668 MonoBoolean
14669 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
14671 guint32 idx = 1; /* there is only one assembly */
14672 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14673 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
14675 return get_declsec_action (assembly->image, idx, action, entry);
14678 gboolean
14679 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass, MonoError *error)
14681 MonoObject *res, *exc;
14682 void *params [1];
14683 static MonoMethod *method = NULL;
14685 mono_error_init (error);
14687 if (method == NULL) {
14688 method = mono_class_get_method_from_name (mono_class_get_type_builder_class (), "IsAssignableTo", 1);
14689 g_assert (method);
14693 * The result of mono_type_get_object_checked () might be a System.MonoType but we
14694 * need a TypeBuilder so use mono_class_get_ref_info (klass).
14696 g_assert (mono_class_get_ref_info (klass));
14697 g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
14699 params [0] = mono_type_get_object_checked (mono_domain_get (), &oklass->byval_arg, error);
14700 return_val_if_nok (error, FALSE);
14702 res = mono_runtime_try_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc, error);
14704 if (exc || !mono_error_ok (error)) {
14705 mono_error_cleanup (error);
14706 return FALSE;
14707 } else
14708 return *(MonoBoolean*)mono_object_unbox (res);
14712 * mono_reflection_type_get_type:
14713 * @reftype: the System.Type object
14715 * Returns the MonoType* associated with the C# System.Type object @reftype.
14717 MonoType*
14718 mono_reflection_type_get_type (MonoReflectionType *reftype)
14720 g_assert (reftype);
14722 MonoError error;
14723 MonoType *result = mono_reflection_type_get_handle (reftype, &error);
14724 mono_error_assert_ok (&error);
14725 return result;
14729 * mono_reflection_assembly_get_assembly:
14730 * @refassembly: the System.Reflection.Assembly object
14732 * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
14734 MonoAssembly*
14735 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
14737 g_assert (refassembly);
14739 return refassembly->assembly;